source: lliurex-gdrive/trunk/fuentes/lliurex-gdrive-indicator.install/usr/bin/lliurexGdriveIndicator @ 4055

Last change on this file since 4055 was 4055, checked in by jrpelegrina, 2 years ago

Fix indicator spinner

  • Property svn:executable set to *
File size: 11.7 KB
Line 
1#!/usr/bin/env python
2
3import gi
4gi.require_version('Gtk', '3.0')
5from gi.repository import Gtk, Pango, GdkPixbuf, Gdk, Gio, GObject, GLib
6gi.require_version('AppIndicator3', '0.1')
7from gi.repository import AppIndicator3 as appindicator
8
9import os
10import threading
11import subprocess
12import sys
13import gettext
14import json
15import random
16import notify2
17
18
19import pyinotify
20from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
21
22import signal
23signal.signal(signal.SIGINT, signal.SIG_DFL)
24
25import lliurex.lliurexgdrive
26
27import gettext
28gettext.textdomain('lliurex-gdrive')
29_ = gettext.gettext
30
31LOCK_INDICATOR="/tmp/lgdIndicator.lock"
32LOCK_GUI="/tmp/lgdGUI.lock"
33RSRC="/usr/share/lliurex-gdrive/"
34MOUNT_ON_IMAGE=RSRC+"rsrc/mount_on.png"
35MOUNT_OFF_IMAGE=RSRC+"rsrc/mount_off.png"
36MOUNT_WARNING_IMAGE=RSRC+"rsrc/mount_warning.png"
37SP1=RSRC+"rsrc/sp1.png"
38SP2=RSRC+"rsrc/sp2.png"
39SP3=RSRC+"rsrc/sp3.png"
40SP4=RSRC+"rsrc/sp4.png"
41SP5=RSRC+"rsrc/sp5.png"
42
43TIME_CHECK_STATUS=900000
44
45class LlliurexGdriveIndicator:
46
47        WATCH_DIR=os.path.expanduser("~/.config/lliurex-google-drive-profiles/configProfiles")
48       
49        def __init__(self,icon_name):
50               
51                self.LliurexGoogleDriveManager=lliurex.lliurexgdrive.LliurexGoogleDriveManager()
52                self.app_indicator=appindicator.Indicator.new("lliurex-gdrive",icon_name,appindicator.IndicatorCategory.APPLICATION_STATUS)
53                self.app_indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
54                self.menu = Gtk.Menu()
55               
56                self.menu.add_events(Gdk.EventMask.ALL_EVENTS_MASK)
57                self.app_indicator.set_menu(self.menu)
58               
59                self.profiles_info=self.LliurexGoogleDriveManager.profiles_config.copy()
60                self.current_status={}
61
62                       
63                self.createLockToken()
64                self.check_initial_connection()
65                self.populate_menu()
66                self.start_inotify()
67                self.sync_threads={}
68                self.result_sync_threads={}
69                self.profile_clicked=[]
70                self.sp_cont={}
71                self.sp_img={}
72                self.checking_status=False
73               
74
75                GLib.timeout_add(TIME_CHECK_STATUS,self.check_status)
76               
77        #def __init__
78
79        def check_initial_connection(self):
80               
81                self.initial_connection=self.LliurexGoogleDriveManager.check_google_connection()
82                return
83
84        def generate_sync_threads(self,profile):
85               
86                id=int(random.random()*1000)           
87                t=threading.Thread(target=self.check_sync,args=(id,profile))
88                t.daemon=True
89                t.start()
90                self.sync_threads[id]={}
91                self.sync_threads[id]["thread"]=t
92                self.result_sync_threads[id]={}
93                return id
94       
95        def init_connect_thread(self):
96               
97                self.check_connect_t=threading.Thread(target=self.check_connect)
98                self.check_connect_t.daemon=True
99                self.check_connect_t.start()
100               
101        def createLockToken(self):
102
103                #self.lockpath=os.path(LOCK_INDICATOR)
104                if not os.path.exists(LOCK_INDICATOR):
105                        f=open(LOCK_INDICATOR,'w')
106                        f.close
107
108        #def createLockToken
109                       
110        def start_inotify(self):
111
112                t=threading.Thread(target=self._inotify)
113                t.daemon=True
114                t.start()
115
116        #def start_inotif
117
118
119        def _inotify(self):
120               
121               
122                wm=WatchManager()
123                mask=pyinotify.IN_CLOSE_WRITE
124                       
125                class Process_handler(ProcessEvent):
126                               
127                        def __init__(self,main):
128                               
129                                self.main=main
130                               
131                        def process_IN_CLOSE_WRITE(self,event):
132
133                                self.main.update_info()
134                                self.main.initial_connection=True
135                                for profile in self.main.update_profiles:
136                                        if not profile in self.main.profiles_info:
137                                                mountpoint=self.main.update_profiles[profile]["mountpoint"]
138                                                self.main.add_menu_item(profile,mountpoint)
139
140                                for item in self.main.menu.get_children():
141                                        if item.profile !="":
142                                                if not item.profile in self.main.update_profiles:
143                                                        self.main.menu.remove(item)     
144                               
145                                self.main.profiles_info=self.main.update_profiles.copy()
146                                self.main.menu.show_all()                                       
147                                                               
148       
149                notifier=Notifier(wm,Process_handler(self))
150                wdd=wm.add_watch(LlliurexGdriveIndicator.WATCH_DIR,mask,rec=True)
151                       
152                while True:
153                        try:
154                                       
155                                notifier.process_events()
156                                if notifier.check_events():
157                                        notifier.read_events()
158                               
159                        except Exception as e:
160                                notifier.stop()
161                                       
162                return False
163       
164        #def _inotify
165
166        def update_info(self):
167
168                f=open(self.LliurexGoogleDriveManager.config_file)
169
170                try:
171                        self.update_profiles=json.load(f)
172                except:
173                        self.update_profiles={}
174               
175                f.close()
176
177        #def update_info       
178       
179        def add_menu_item(self,profile,mountpoint):
180
181                if self.initial_connection:
182                        status_info=self.LliurexGoogleDriveManager.check_mountpoint_status(mountpoint)
183                        info=self.item_status_info(status_info)
184                        self.current_status[profile]=status_info["status"]     
185                else:
186                        status_info={}
187                        status_info['status']=None
188                        status_info['size']=0
189                        status_info['used']=0
190                        info=self.item_status_info(status_info)
191                        self.current_status[profile]=None
192                               
193                label_item=profile     
194                item=Gtk.ImageMenuItem()
195                item.set_label(label_item)
196                item.set_image(info["img"])
197                item.set_tooltip_text(info["tooltip"])
198                item.profile=profile
199                item.size=False
200                item.status=True
201                item.set_always_show_image(True)
202                item.connect("activate",self.item_clicked,profile)
203                self.menu.insert(item,0)
204
205               
206                item=Gtk.MenuItem()
207                label_item=info["used_size"]
208                item.set_label(label_item)
209                item.profile=profile
210                item.size=True
211                item.status=False
212                self.menu.insert(item,1)
213
214                item=Gtk.MenuItem()
215                label_item=_("Open folder")
216                item.set_label(label_item)
217                item.connect("activate",self.open_folder,profile)
218                item.profile=profile
219                item.size=False
220                item.status=False
221                self.menu.insert(item,2)
222
223                item=Gtk.SeparatorMenuItem()
224                item.profile=profile
225                item.size=False
226                item.status=False
227                self.menu.insert(item,3)
228
229        #def add_menu_item     
230
231
232        def populate_menu(self,empty=True):
233               
234               
235                if empty:
236                        for c in self.menu.get_children():
237                                self.menu.remove(c)
238               
239               
240                for profile in self.profiles_info:
241                        mountpoint=self.profiles_info[profile]["mountpoint"]
242                        self.add_menu_item(profile,mountpoint)
243                       
244                       
245                item=Gtk.ImageMenuItem()
246                label_item=_("Open Lliurex GDrive")
247                item.set_label(label_item)
248                img=Gtk.Image()
249                img.set_from_stock(Gtk.STOCK_PREFERENCES,Gtk.IconSize.MENU)
250                item.set_image(img)
251                item.set_always_show_image(True)
252                item.connect("activate",self.open_gui)
253                item.profile=""
254                item.size=False
255                item.status=False
256                self.menu.append(item)
257
258                item=Gtk.ImageMenuItem()
259                img=Gtk.Image()
260                img.set_from_stock(Gtk.STOCK_CLOSE,Gtk.IconSize.MENU)
261                item.set_image(img)
262                item.set_always_show_image(True)
263                label_item=_("Close")
264                item.set_label(label_item)
265                item.connect("activate",self.quit)
266                item.profile=""
267                item.size=False
268                item.status=False
269                self.menu.append(item)
270
271
272                self.menu.show_all()
273               
274               
275        #def populate_menu
276       
277       
278        def item_clicked(self,widget,profile):
279       
280                if profile not in self.profile_clicked:
281                        self.profile_clicked.append(profile)
282                        id=self.generate_sync_threads(profile)
283                        self.sp_cont[id]=0
284                        self.sp_img[id]=Gtk.Image.new_from_file(SP1)
285                        GLib.timeout_add(100,self.pulsate_check_sync,id,widget,profile)
286                       
287               
288        #def item_clicked
289
290        def spinner_sync(self,id):
291       
292                if self.sp_cont[id]>50:
293                        self.sp_cont[id]=0
294                       
295                if self.sp_cont[id]==0:
296                        img=Gtk.Image.new_from_file(SP1)
297                        self.sp_img[id]=img
298                elif self.sp_cont[id]==10:
299                        img=Gtk.Image.new_from_file(SP2)
300                        self.sp_img[id]=img                     
301                elif self.sp_cont[id]==20:
302                        img=Gtk.Image.new_from_file(SP3)
303                        self.sp_img[id]=img
304                elif self.sp_cont[id]==30:
305                        img=Gtk.Image.new_from_file(SP4)
306                        self.sp_img[id]=img
307                elif self.sp_cont[id]==40:
308                        img=Gtk.Image.new_from_file(SP5)
309                        self.sp_img[id]=img     
310                               
311               
312                       
313        def pulsate_check_sync(self,id,widget,profile):
314               
315               
316                if self.sync_threads[id]["thread"].is_alive():
317                        self.spinner_sync(id)
318                        widget.set_image(self.sp_img[id])
319                        widget.set_tooltip_text(_("Applying changes..."))       
320                        self.sp_cont[id]=self.sp_cont[id]+1
321                        return True
322               
323                else:
324                        self.profile_clicked.remove(profile)
325                        self.current_status[profile]=self.result_sync_threads[id]["status_info"]["status"]     
326                        if self.result_sync_threads[id]["status_mod"]["result"]==False:
327                                if self.result_sync_threads[id]["status_mod"]["code"]==8:
328                                        message=_("Error: Unable to connect with google")       
329                                else:
330                                        status=self.current_status[profile]
331                                        if status:
332                                                action=_("dismount")
333                                        else:
334                                                action=_("mount")       
335                                        message=_("Error: Unable to ") + action + " " 
336                        else:
337                                if self.result_sync_threads[id]["status_mod"]["code"]==9:
338                                        message=_("Status updated. Now you can change it")
339                                else:
340                                        message=_("Changes applied successfully")
341                       
342                        self.show_message(profile + ": " + message)
343                       
344                        info=self.item_status_info(self.result_sync_threads[id]["status_info"])
345                       
346                        for item in self.menu.get_children():
347                                        if item.size:
348                                                if item.profile==profile:
349                                                        item.set_label(info["used_size"])
350                               
351                        widget.set_tooltip_text(info["tooltip"])
352                        widget.set_image(info["img"])   
353                        self.sync_threads.pop(id)
354                        self.sp_cont.pop(id)
355                        self.sp_img.pop(id)
356                        self.result_sync_threads.pop(id)
357               
358                return False
359                       
360       
361        def     check_sync(self,id,profile):
362               
363                mountpoint=self.profiles_info[profile]["mountpoint"]
364
365                current_status=self.current_status[profile]
366               
367                self.result_sync_threads[id]["status_mod"],self.result_sync_threads[id]["status_info"]=self.LliurexGoogleDriveManager.sync_profile(profile,mountpoint,current_status)
368
369
370                #self.result_connect_threads[id]["value"]=self.LliurexGoogleDriveManager.check_google_connection()
371       
372        def open_folder(self,widget,profile):
373
374               
375                mountpoint=self.profiles_info[profile]["mountpoint"]
376                cmd="caja " + mountpoint.encode("utf-8")
377
378                os.system(cmd) 
379
380        #def open_folder       
381
382        def open_gui(self,widget):
383               
384                if not os.path.exists(LOCK_GUI):
385                        cmd='/usr/bin/lliurex-gdrive' +"&" 
386                        os.system(cmd)
387
388        #def open_gui
389               
390        def item_status_info(self,status_info):
391       
392                size=status_info["size"]
393                used=status_info["used"]
394
395                if status_info['status']==None:
396                        img=Gtk.Image.new_from_file(MOUNT_WARNING_IMAGE)
397                        tooltip=_("Without connection. Clicked to update")
398                        used_size=_("Used: not available")
399               
400                elif    status_info["status"]:
401                        img=Gtk.Image.new_from_file(MOUNT_ON_IMAGE)
402                        tooltip=_("Mounted. Clicked to dismount now")
403                        used_size=_("Used: %s of %s")%(used,size)
404               
405                else:
406                        img=Gtk.Image.new_from_file(MOUNT_OFF_IMAGE)
407                        tooltip=_("Dismounted. Clicked to mount now")
408                        used_size=_("Used: not available")     
409
410                return {"img":img ,"tooltip":tooltip, "used_size":used_size}   
411
412        #def item_status_info                   
413
414        def check_status(self):
415               
416                if not self.checking_status:
417                        self.checking_status=True
418                        self.init_connect_thread()
419                        GLib.timeout_add(100,self.get_status_info,id)
420
421                return True
422               
423               
424        #def check_status
425       
426        def get_status_info(self,id):
427               
428                if self.check_connect_t.is_alive():
429                        return True
430               
431                else:   
432                        self.checking_status=False
433                        #self.connect_threads.pop(id)
434                        for profile in self.profiles_info:
435                                if self.connection:
436                                        mountpoint=self.profiles_info[profile]["mountpoint"]
437                                        status_info=self.LliurexGoogleDriveManager.check_mountpoint_status(mountpoint)
438                                else:
439                                        status_info={}
440                                        status_info['status']=None
441                                        status_info['size']=0
442                                        status_info['used']=0
443                                       
444                                info=self.item_status_info(status_info)
445                                self.current_status[profile]=status_info["status"]
446                                                               
447                                for item in self.menu.get_children():
448                                        if item.profile==profile:
449                                                if item.size:
450                                                        item.set_label(info["used_size"])
451                                                if item.status:
452                                                        item.set_tooltip_text(info["tooltip"])
453                                                        item.set_image(info["img"])
454               
455                #self.result_connect_threads.pop(id)           
456                return False   
457                                       
458        def check_connect(self):
459               
460                self.connection=self.LliurexGoogleDriveManager.check_google_connection()
461
462       
463        def show_message(self,message):
464                notify2.init("test")
465                n=notify2.Notification("Lliurex-GDrive",message,"gdrive")
466                n.show()
467                return
468                               
469       
470        def cleanIndicatorLock(self):
471
472                if os.path.exists(LOCK_INDICATOR):
473                        os.remove(LOCK_INDICATOR)
474
475        #def cleanIndicatorLock                 
476       
477        def quit(self,widget):
478
479                self.cleanIndicatorLock()
480                Gtk.main_quit() 
481
482        #def quit       
483
484       
485#class LlliurexGdriveIndicator
486
487if __name__=="__main__":
488       
489        lliurexgdrive=LlliurexGdriveIndicator("gdrive")
490        GObject.threads_init()
491        Gtk.main()
492       
Note: See TracBrowser for help on using the repository browser.