source: lliurex-gdrive/trunk/WIP_files/lliurexGdriveIndicator @ 6071

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

WIP files. Fix indicator spiner

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