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

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

Fix endesession script and lock token's path

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