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

Last change on this file since 5574 was 5574, checked in by jrpelegrina, 21 months ago

Clean cache when mountpoint is dismounted

  • Property svn:executable set to *
File size: 12.3 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 check_initial_connection   
85
86        def generate_sync_threads(self,profile):
87               
88                id=int(random.random()*1000)           
89                t=threading.Thread(target=self.check_sync,args=(id,profile))
90                t.daemon=True
91                t.start()
92                self.sync_threads[id]={}
93                self.sync_threads[id]["thread"]=t
94                self.result_sync_threads[id]={}
95                return id
96
97        #def generate_sync_threads     
98       
99        def init_connect_thread(self):
100               
101                self.check_connect_t=threading.Thread(target=self.check_connect)
102                self.check_connect_t.daemon=True
103                self.check_connect_t.start()
104
105        #def init_connect_thread       
106               
107        def createLockToken(self):
108
109                #self.lockpath=os.path(LOCK_INDICATOR)
110                if not os.path.exists(LOCK_INDICATOR):
111                        f=open(LOCK_INDICATOR,'w')
112                        f.close
113
114        #def createLockToken
115                       
116        def start_inotify(self):
117
118                t=threading.Thread(target=self._inotify)
119                t.daemon=True
120                t.start()
121
122        #def start_inotif
123
124
125        def _inotify(self):
126               
127               
128                wm=WatchManager()
129                mask=pyinotify.IN_CLOSE_WRITE
130                       
131                class Process_handler(ProcessEvent):
132                               
133                        def __init__(self,main):
134                               
135                                self.main=main
136                               
137                        def process_IN_CLOSE_WRITE(self,event):
138
139                                self.main.update_info()
140                                self.main.initial_connection=True
141                                for profile in self.main.update_profiles:
142                                        if not profile in self.main.profiles_info:
143                                                mountpoint=self.main.update_profiles[profile]["mountpoint"]
144                                                self.main.add_menu_item(profile,mountpoint)
145
146                                for item in self.main.menu.get_children():
147                                        if item.profile !="":
148                                                if not item.profile in self.main.update_profiles:
149                                                        self.main.menu.remove(item)     
150                               
151                                self.main.profiles_info=self.main.update_profiles.copy()
152                                self.main.menu.show_all()                                       
153                                                               
154       
155                notifier=Notifier(wm,Process_handler(self))
156                wdd=wm.add_watch(LlliurexGdriveIndicator.WATCH_DIR,mask,rec=True)
157                       
158                while True:
159                        try:
160                                       
161                                notifier.process_events()
162                                if notifier.check_events():
163                                        notifier.read_events()
164                               
165                        except Exception as e:
166                                notifier.stop()
167                                       
168                return False
169       
170        #def _inotify
171
172        def update_info(self):
173
174                f=open(self.LliurexGoogleDriveManager.config_file)
175
176                try:
177                        self.update_profiles=json.load(f)
178                except:
179                        self.update_profiles={}
180               
181                f.close()
182
183        #def update_info       
184       
185        def add_menu_item(self,profile,mountpoint):
186
187                if self.initial_connection:
188                        status_info=self.LliurexGoogleDriveManager.check_mountpoint_status(mountpoint)
189                        info=self.item_status_info(status_info)
190                        self.current_status[profile]=status_info["status"]     
191                else:
192                        status_info={}
193                        status_info['status']=None
194                        status_info['size']=0
195                        status_info['used']=0
196                        info=self.item_status_info(status_info)
197                        self.current_status[profile]=None
198                               
199                label_item=profile     
200                item=Gtk.ImageMenuItem()
201                item.set_label(label_item)
202                item.set_image(info["img"])
203                item.set_tooltip_text(info["tooltip"])
204                item.profile=profile
205                item.size=False
206                item.status=True
207                item.set_always_show_image(True)
208                item.connect("activate",self.item_clicked,profile)
209                self.menu.insert(item,0)
210
211               
212                item=Gtk.MenuItem()
213                label_item=info["used_size"]
214                item.set_label(label_item)
215                item.profile=profile
216                item.size=True
217                item.status=False
218                self.menu.insert(item,1)
219
220                item=Gtk.MenuItem()
221                label_item=_("Open folder")
222                item.set_label(label_item)
223                item.connect("activate",self.open_folder,profile)
224                item.profile=profile
225                item.size=False
226                item.status=False
227                self.menu.insert(item,2)
228
229                item=Gtk.MenuItem()
230                label_item=_("Update cache")
231                item.set_label(label_item)
232                item.set_tooltip_text(_("Click if do not see all the files in the Google Drive account"))
233                item.connect("activate",self.refresh_cache,profile)
234                item.profile=profile
235                item.size=False
236                item.status=False
237                self.menu.insert(item,3)
238
239                item=Gtk.SeparatorMenuItem()
240                item.profile=profile
241                item.size=False
242                item.status=False
243                self.menu.insert(item,4)
244
245        #def add_menu_item     
246
247
248        def populate_menu(self,empty=True):
249               
250               
251                if empty:
252                        for c in self.menu.get_children():
253                                self.menu.remove(c)
254               
255               
256                for profile in self.profiles_info:
257                        mountpoint=self.profiles_info[profile]["mountpoint"]
258                        self.add_menu_item(profile,mountpoint)
259                       
260                       
261                item=Gtk.ImageMenuItem()
262                label_item=_("Open Lliurex GDrive")
263                item.set_label(label_item)
264                img=Gtk.Image()
265                img.set_from_stock(Gtk.STOCK_PREFERENCES,Gtk.IconSize.MENU)
266                item.set_image(img)
267                item.set_always_show_image(True)
268                item.connect("activate",self.open_gui)
269                item.profile=""
270                item.size=False
271                item.status=False
272                self.menu.append(item)
273
274                item=Gtk.ImageMenuItem()
275                img=Gtk.Image()
276                img.set_from_stock(Gtk.STOCK_CLOSE,Gtk.IconSize.MENU)
277                item.set_image(img)
278                item.set_always_show_image(True)
279                label_item=_("Close")
280                item.set_label(label_item)
281                item.connect("activate",self.quit)
282                item.profile=""
283                item.size=False
284                item.status=False
285                self.menu.append(item)
286
287
288                self.menu.show_all()
289               
290               
291        #def populate_menu
292       
293       
294        def item_clicked(self,widget,profile):
295       
296                if profile not in self.profile_clicked:
297                        self.profile_clicked.append(profile)
298                        id=self.generate_sync_threads(profile)
299                        self.sp_cont[id]=0
300                        self.sp_img[id]=Gtk.Image.new_from_file(SP1)
301                        GLib.timeout_add(100,self.pulsate_check_sync,id,widget,profile)
302                       
303               
304        #def item_clicked
305
306        def spinner_sync(self,id):
307       
308                if self.sp_cont[id]>50:
309                        self.sp_cont[id]=0
310                       
311                if self.sp_cont[id]==0:
312                        img=Gtk.Image.new_from_file(SP1)
313                        self.sp_img[id]=img
314                elif self.sp_cont[id]==10:
315                        img=Gtk.Image.new_from_file(SP2)
316                        self.sp_img[id]=img                     
317                elif self.sp_cont[id]==20:
318                        img=Gtk.Image.new_from_file(SP3)
319                        self.sp_img[id]=img
320                elif self.sp_cont[id]==30:
321                        img=Gtk.Image.new_from_file(SP4)
322                        self.sp_img[id]=img
323                elif self.sp_cont[id]==40:
324                        img=Gtk.Image.new_from_file(SP5)
325                        self.sp_img[id]=img     
326                               
327        #def spinner_sync       
328                       
329        def pulsate_check_sync(self,id,widget,profile):
330               
331               
332                if self.sync_threads[id]["thread"].is_alive():
333                        self.spinner_sync(id)
334                        widget.set_image(self.sp_img[id])
335                        widget.set_tooltip_text(_("Applying changes..."))       
336                        self.sp_cont[id]=self.sp_cont[id]+1
337                        return True
338               
339                else:
340                        self.profile_clicked.remove(profile)
341                        self.current_status[profile]=self.result_sync_threads[id]["status_info"]["status"]     
342                        if self.result_sync_threads[id]["status_mod"]["result"]==False:
343                                if self.result_sync_threads[id]["status_mod"]["code"]==8:
344                                        message=_("Error: Unable to connect with google")       
345                                else:
346                                        status=self.current_status[profile]
347                                        if status:
348                                                action=_("dismount")
349                                        else:
350                                                action=_("mount")       
351                                        message=_("Error: Unable to ") + action + " " 
352                        else:
353                                if self.result_sync_threads[id]["status_mod"]["code"]==9:
354                                        message=_("Status updated. Now you can change it")
355                                else:
356                                        message=_("Changes applied successfully")
357                       
358                        self.show_message(profile + ": " + message)
359                       
360                        info=self.item_status_info(self.result_sync_threads[id]["status_info"])
361                       
362                        for item in self.menu.get_children():
363                                        if item.size:
364                                                if item.profile==profile:
365                                                        item.set_label(info["used_size"])
366                               
367                        widget.set_tooltip_text(info["tooltip"])
368                        widget.set_image(info["img"])   
369                        self.sync_threads.pop(id)
370                        self.sp_cont.pop(id)
371                        self.sp_img.pop(id)
372                        self.result_sync_threads.pop(id)
373               
374                return False
375
376        #def pulsate_check_sync
377                       
378       
379        def     check_sync(self,id,profile):
380               
381                mountpoint=self.profiles_info[profile]["mountpoint"]
382
383                current_status=self.current_status[profile]
384               
385                self.result_sync_threads[id]["status_mod"],self.result_sync_threads[id]["status_info"]=self.LliurexGoogleDriveManager.sync_profile(profile,mountpoint,current_status)
386
387
388                #self.result_connect_threads[id]["value"]=self.LliurexGoogleDriveManager.check_google_connection()
389
390        #def check_sync
391       
392        def open_folder(self,widget,profile):
393
394               
395                mountpoint=self.profiles_info[profile]["mountpoint"]
396                cmd="caja " + mountpoint.encode("utf-8")
397
398                os.system(cmd) 
399
400        #def open_folder
401
402        def refresh_cache (self,widget,profile):
403
404                cmd="google-drive-ocamlfuse -cc -label %s"%profile
405                os.system(cmd) 
406
407        #def refresh_cache     
408
409        def open_gui(self,widget):
410               
411                if not os.path.exists(LOCK_GUI):
412                        cmd='/usr/bin/lliurex-gdrive' +"&" 
413                        os.system(cmd)
414
415        #def open_gui
416               
417        def item_status_info(self,status_info):
418       
419                size=status_info["size"]
420                used=status_info["used"]
421
422                if status_info['status']==None:
423                        img=Gtk.Image.new_from_file(MOUNT_WARNING_IMAGE)
424                        tooltip=_("Without connection. Clicked to update")
425                        used_size=_("Used: not available")
426               
427                elif    status_info["status"]:
428                        img=Gtk.Image.new_from_file(MOUNT_ON_IMAGE)
429                        tooltip=_("Mounted. Clicked to dismount now")
430                        used_size=_("Used: %s of %s")%(used,size)
431               
432                else:
433                        img=Gtk.Image.new_from_file(MOUNT_OFF_IMAGE)
434                        tooltip=_("Dismounted. Clicked to mount now")
435                        used_size=_("Used: not available")     
436
437                return {"img":img ,"tooltip":tooltip, "used_size":used_size}   
438
439        #def item_status_info                   
440
441        def check_status(self):
442               
443                if not self.checking_status:
444                        self.checking_status=True
445                        self.init_connect_thread()
446                        GLib.timeout_add(100,self.get_status_info,id)
447
448                return True
449               
450               
451        #def check_status
452       
453        def get_status_info(self,id):
454               
455                if self.check_connect_t.is_alive():
456                        return True
457               
458                else:   
459                        self.checking_status=False
460                        #self.connect_threads.pop(id)
461                        for profile in self.profiles_info:
462                                if self.connection:
463                                        mountpoint=self.profiles_info[profile]["mountpoint"]
464                                        status_info=self.LliurexGoogleDriveManager.check_mountpoint_status(mountpoint)
465                                else:
466                                        status_info={}
467                                        status_info['status']=None
468                                        status_info['size']=0
469                                        status_info['used']=0
470                                       
471                                info=self.item_status_info(status_info)
472                                self.current_status[profile]=status_info["status"]
473                                                               
474                                for item in self.menu.get_children():
475                                        if item.profile==profile:
476                                                if item.size:
477                                                        item.set_label(info["used_size"])
478                                                if item.status:
479                                                        item.set_tooltip_text(info["tooltip"])
480                                                        item.set_image(info["img"])
481               
482                #self.result_connect_threads.pop(id)           
483                return False   
484
485        #def get_status_info   
486                                       
487        def check_connect(self):
488               
489                self.connection=self.LliurexGoogleDriveManager.check_google_connection()
490
491        #def check_connect     
492
493       
494        def show_message(self,message):
495                notify2.init("test")
496                n=notify2.Notification("Lliurex-GDrive",message,"gdrive")
497                n.show()
498                return
499
500        #def show_message       
501                               
502       
503        def cleanIndicatorLock(self):
504
505                if os.path.exists(LOCK_INDICATOR):
506                        os.remove(LOCK_INDICATOR)
507
508        #def cleanIndicatorLock                 
509       
510        def quit(self,widget):
511
512                self.cleanIndicatorLock()
513                Gtk.main_quit() 
514
515        #def quit       
516
517       
518#class LlliurexGdriveIndicator
519
520if __name__=="__main__":
521       
522        lliurexgdrive=LlliurexGdriveIndicator("gdrive")
523        GObject.threads_init()
524        Gtk.main()
525       
Note: See TracBrowser for help on using the repository browser.