source: zero-lliurex-flavours/trunk/fuentes/install-files/usr/share/lliurex-flavours-selector/lliurex-flavours-selector.py @ 2311

Last change on this file since 2311 was 2311, checked in by jrpelegrina, 5 years ago

Improve general performance

  • Property svn:executable set to *
File size: 21.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import gi
5gi.require_version('Gtk', '3.0')
6gi.require_version('PangoCairo', '1.0')
7
8import cairo
9import os
10import threading
11import ConfigParser
12import platform
13import subprocess
14import sys
15import datetime
16from math import pi
17
18from gi.repository import Gtk, Gdk, GObject, GLib, PangoCairo, Pango
19
20import signal
21signal.signal(signal.SIGINT, signal.SIG_DFL)
22
23
24import gettext
25gettext.textdomain('zero-lliurex-flavours')
26_ = gettext.gettext
27
28
29BASE_DIR="/usr/share/lliurex-flavours-selector/"
30RSRC_DIR=BASE_DIR+"rsrc/"
31SHADOW_BANNER=RSRC_DIR+"shadow.png"
32UNKNOWN_BANNER=RSRC_DIR+"unknown.png"
33BANNERS_PATH=BASE_DIR+"banners/"
34FLAVOURS_CONFIG_PATH=BASE_DIR+"supported-flavours/"
35
36CURRENT_PLATFORM=platform.machine()
37
38class GridButton:
39       
40        def __init__(self,info):
41               
42                self.info=info
43                self.info["installed"]=False
44                self.info["checked"]=False
45                self.info["incompatible"]=False
46                self.info["shadow_alpha"]=0.1
47                self.info["animation_active"]=False
48                self.info["shadow_start"]=0
49                self.info["available"]=True
50                self.info["drawingarea"]=None
51               
52                if os.path.exists(BANNERS_PATH+self.info["pkg"]+".png"):
53                        self.info["image"]=BANNERS_PATH+self.info["pkg"]+".png"
54                else:
55                        self.info["image"]=UNKNOWN_BANNER
56               
57        #def init
58       
59       
60#class GridButton
61
62
63class ConfButton:
64       
65        def __init__(self,info):
66               
67                self.txt=info["txt"]
68                self.icon=info["icon"]
69                self.name=info["name"]
70                self.da=None
71                if "active" not in info:
72                        self.active=False
73                else:
74                        self.active=info["active"]
75               
76        #def
77
78#class ConfButton
79       
80       
81class ConfigurationParser:
82       
83        def __init__(self):
84                pass
85       
86        def load_plugin(self,path):
87       
88                try:
89                        config = ConfigParser.ConfigParser()
90                        config.optionxform=str
91                        config.read(path)
92                        if config.has_section("FLAVOUR"):
93                                info={}
94                                info["pkg"]=config.get("FLAVOUR","pkg")
95                                info["name"]=config.get("FLAVOUR","name")
96                               
97                                return GridButton(info)
98                               
99                except Exception as e:
100                        print e
101                        return None
102       
103       
104#class ConfigParser
105
106
107class CustomColor:
108       
109        def __init__(self,r,g,b):
110               
111                self.r=r/255.0
112                self.g=g/255.0
113                self.b=b/255.0
114
115#class CustomColor             
116
117class AwesomeTabs:
118       
119        def __init__(self):
120               
121                self.configuration_parser=ConfigurationParser()
122               
123                self.current_tab=-1
124                self.current_width=0
125                self.animation_left=False
126                self.animation_right=False
127               
128                self.current_red_width=0
129                self.current_red_pos=0
130                self.configuration_start=0
131               
132                self.current_grid_width=0
133                self.current_grid_height=0
134               
135                self.max_grid_width=2
136               
137                self.dark_gray=CustomColor(130.0,151.0,161.0)
138                self.light_gray=CustomColor(185.0,195.0,195.0)
139               
140                self.green=CustomColor(74.0,166.,69.0)
141                self.light_green=CustomColor(88.0,208.0,86.0)
142               
143                self.conf_light=CustomColor(49.0,55.0,66.0)
144                self.conf_dark=CustomColor(30.0,36.0,42.0)
145               
146                self.conf_light_shadow=CustomColor(107.0,116.0,137.0)
147                self.conf_dark_shadow=CustomColor(0,0,0)
148               
149                self.current_conf_height=0
150                self.conf_buttons=[]
151                self.start_gui()
152               
153               
154        #def __init__
155       
156       
157       
158        def start_gui(self):
159               
160                builder=Gtk.Builder()
161                builder.set_translation_domain('zero-lliurex-flavours')
162                glade_path=RSRC_DIR+"lliurex-flavours-selector.ui"
163                builder.add_from_file(glade_path)
164               
165                self.installers_eb=builder.get_object("installers_eventbox")
166                self.installers_label=builder.get_object("installers_label")
167               
168               
169                self.top_divider_da=builder.get_object("top_divider_drawingarea")
170                self.bottom_divider_da=builder.get_object("bottom_divider_drawingarea")
171                self.top_divider_da.connect("draw",self.draw_top_divider)
172                self.bottom_divider_da.connect("draw",self.draw_bottom_divider)
173               
174                self.button_scroll=builder.get_object("button_scrolledwindow")
175                self.main_box=builder.get_object("main_box")
176                self.apply_eb=builder.get_object("apply_eventbox")
177                self.apply_da=builder.get_object("apply_drawingarea")
178                self.apply_eb.connect("button-press-event",self.accept_clicked)
179                self.apply_da.connect("draw",self.draw_apply_button)
180                self.close_eb=builder.get_object("close_eventbox")
181                self.close_da=builder.get_object("close_drawingarea")
182                self.close_eb.connect("button-press-event",self.quit)
183                self.close_da.connect("draw",self.draw_close_button)
184                self.msg_label=builder.get_object("msg_label")
185               
186                self.stack = Gtk.Stack()
187                self.stack.set_transition_duration(1000)
188                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
189               
190                self.installers_grid=builder.get_object("button_grid")
191                               
192               
193               
194                self.stack.add_titled(self.button_scroll, "installers", "Installers")
195               
196               
197                self.main_box.add(self.stack)
198               
199                self.main_window=builder.get_object("main_window")
200               
201               
202                self.main_window.connect("destroy",self.quit)
203               
204               
205                self.progress_window=builder.get_object("progress_window")
206                self.pbar=builder.get_object("progressbar")
207                self.progress_window.set_transient_for(self.main_window)
208               
209                self.gather_window=builder.get_object("gather_window")
210                self.gather_pbar=builder.get_object("progressbar1")
211                self.progress_label=builder.get_object("progress_label")
212               
213                       
214                self.set_css_info()
215               
216                self.gather_window.show_all()
217                GLib.timeout_add(100,self.pulsate_gathering_info)
218               
219                self.t=threading.Thread(target=self.gather_info)
220                self.t.daemon=True
221                self.t.start()
222                self.install_metas=[]
223                self.update_metas=[]
224                GObject.threads_init()         
225                Gtk.main()
226               
227        #def start_gui
228       
229        def gather_info(self):
230               
231                import time
232                base_apt_cmd="apt-cache policy "
233               
234                self.gbs=[]
235                self.flavours_installed=0
236               
237                for item in sorted(os.listdir(FLAVOURS_CONFIG_PATH)):
238                        if os.path.isfile(FLAVOURS_CONFIG_PATH+item):
239                                gb=self.configuration_parser.load_plugin(FLAVOURS_CONFIG_PATH+item)
240                                if gb!=None:
241                                        sys.stdout.write("* Checking %s ...\t"%gb.info["pkg"])
242                                        gb.info["installed"]=self.is_installed(gb.info["pkg"])
243                                        sys.stdout.write("%s\n"%gb.info["installed"])
244                                        base_apt_cmd += "%s "%gb.info["pkg"]
245                                        self.gbs.append(gb)
246                                       
247                p=subprocess.Popen([base_apt_cmd],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)     
248                output=p.communicate()
249               
250                for gb in self.gbs:
251                       
252                        if gb.info["pkg"] not in output[0]:
253                                print(" [!] %s not available [!] "%gb.info["pkg"])
254                                gb.info["available"]=False
255                        else:
256                                if gb.info["installed"]==True:
257                                        self.check_meta_blocked(gb, self.gbs)
258                                        self.flavours_installed+=1     
259                                self.add_grid_button(gb)       
260                       
261        #def gather_info
262       
263        def check_meta_blocked(self, gb, gbs):
264
265                if gb.info["pkg"]=="lliurex-meta-server":
266                        for gb in self.gbs:
267                                if gb.info["pkg"]=="lliurex-meta-client": 
268                                        gb.info["incompatible"]=True
269                                elif gb.info["pkg"]=="lliurex-meta-desktop" and not gb.info["installed"]:
270                                        gb.info["incompatible"]=True   
271                elif gb.info["pkg"]=="lliurex-meta-client":
272                        for gb in self.gbs:
273                                if gb.info["pkg"]=="lliurex-meta-server":
274                                        gb.info["incompatible"]=True                           
275
276        #def check_meta_blocked                         
277
278        def pulsate_gathering_info(self):
279               
280                self.gather_pbar.pulse()
281               
282                if not self.t.is_alive():
283                       
284                        self.gather_window.hide()
285                        self.main_window.show_all()
286               
287                        if self.flavours_installed<1:
288                                msg=_("No flavour detected. Check one at least")
289                                self.msg_label.show()
290                                self.msg_label.set_markup(msg)
291                return self.t.is_alive()
292               
293        #def pulsate_gathering
294       
295        def set_css_info(self):
296               
297                css = """
298               
299                #BLUE {
300                        background-image:-gtk-gradient (linear, left top, left bottom, from (#0f72ff),  to (#0f72ff));;
301               
302                }
303               
304                #BLACK{
305                        background-image:-gtk-gradient (linear, left top, left bottom, from (#000000),  to (#000000));;
306               
307                }
308               
309               
310                #BACK_GRADIENT{
311                        background-image:-gtk-gradient (linear, left top, left bottom, from (#ffffff), to (#eceff3));;
312                }
313               
314                #WHITE {
315                        color: white;
316                        text-shadow: 0px 1px black;
317                }
318               
319                #MAIN_LABEL_ENABLED{
320                        color: #8297a1;
321                        font: Noto Sans Bold 18;
322                }
323               
324                #ALTERNATIVES_LABEL{
325                        color: #8297a1;
326                        font: Noto Sans Bold 12;               
327                }
328               
329                #DIALOG_LABEL{
330                        color: #8297a1;
331                        font: Noto Sans Bold 10;               
332                }
333
334                #MAIN_LABEL_DISABLED{
335                        color: #c9d4e2;
336                        font: Noto Sans Bold 18;
337                }
338               
339                #RED_PROGRESS{
340                       
341                        background-color: #FF0000;
342                        border: 0px;
343
344                }
345               
346                #DARK_BACK{
347                        background-color: #070809;
348                }
349               
350                #GREEN {
351                        background-image:-gtk-gradient (linear, left top, left bottom, from (#41ff70),  to (#41ff70));;
352               
353                }
354               
355                #ORANGE {
356                        background-image:-gtk-gradient (linear, left top, left bottom, from (#ff7f2a),  to (#ff7f2a));;
357               
358                }
359               
360                #LIGHTBLUE {
361                        -unico-border-gradient: -gtk-gradient (linear, left top, left bottom,
362                        from (shade (#ff0000, 0.68)),
363                        to (shade (#ff0000, 0.68)));
364               
365                }
366               
367                #RED_LABEL{
368                       
369                        color: red;
370                        font: Noto Sans Bold 11;
371                }
372
373               
374                GtkButton#RED GtkLabel {
375                        color: #8297a1;
376                        font: Noto Sans 11;
377                }
378
379
380                """
381                self.style_provider=Gtk.CssProvider()
382                self.style_provider.load_from_data(css)
383                Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),self.style_provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
384               
385                self.main_window.set_name("BACK_GRADIENT")
386                self.installers_label.set_name("MAIN_LABEL_ENABLED")
387                self.pbar.set_name("RED_PROGRESS")
388                self.gather_pbar.set_name("RED_PROGRESS")
389                self.progress_label.set_name("ALTERNATIVES_LABEL")
390                self.msg_label.set_name("RED_LABEL")
391               
392               
393        #def css_info
394
395        def is_installed(self,pkg):
396               
397               
398                p=subprocess.Popen(["dpkg-query -W -f='${db:Status-Status}' %s"%pkg],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
399                output=p.communicate()
400               
401                if output[0]=="installed":
402                        return True
403                       
404                return False
405               
406               
407        #def is_installed
408       
409        def quit(self,widget,event=None):
410               
411                Gtk.main_quit()
412               
413        #def quit
414       
415        def execute(self,command):
416               
417                self.thread_ret=-1
418                p=subprocess.Popen([command],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) 
419                output=p.communicate()
420                self.thread_ret=p.returncode
421                self.flavour_error=output[1]
422               
423        #def execute
424       
425       
426        def pulsate_pbar(self,da):
427               
428                if self.t.is_alive():
429                       
430                        self.pbar.pulse()
431                               
432                if not self.t.is_alive():
433                        self.progress_window.hide()
434                        if self.thread_ret==0:
435                                for item in self.install_metas:
436                               
437                                        if item.info["checked"]:
438                                                item.info["checked"]=False
439                                                item.info["drawingarea"].queue_draw()
440                                                self.mouse_left(item.info["drawingarea"],None,item)
441                                                item.info["installed"]=True
442                                try:
443                                        self.remove_desktop.info["checked"]=False
444                                        self.remove_desktop.info["drawingarea"].queue_draw()
445                                        self.mouse_left(self.remove_desktop.info["drawingarea"],None,self.remove_desktop)
446                                except:
447                                        print "No desktop flavour to remove"
448                                       
449                                self.install_metas=[]   
450                                self.msg_label.show()
451                                self.msg_label.set_markup("<span foreground='#4aa645'><b>"+_("Installation succesful. A reboot is required")+"</b></span>")
452                        else:
453                                self.msg_label.show()
454                                msg=_("An error ocurred. See log in /tmp/lliurex-flavours-selector")
455                                self.msg_label.set_markup(msg)
456                                self.log(self.flavour_error)   
457                return self.t.is_alive()
458       
459        #def pulsate_pbar
460
461       
462       
463               
464        def add_grid_button(self,grid_button):
465               
466                da=Gtk.DrawingArea()
467                da.set_size_request(140,148)
468                da.add_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.BUTTON_PRESS_MASK )
469               
470                da.connect("draw",self.draw_button,grid_button)
471                da.connect("motion-notify-event",self.mouse_over,grid_button)
472                da.connect("leave_notify_event",self.mouse_left,grid_button)
473                da.connect("button-press-event",self.button_clicked,grid_button)
474                grid_button.info["drawingarea"]=da
475               
476                da.show()
477                self.installers_grid.attach(da,self.current_grid_width,self.current_grid_height,1,1)
478               
479                self.current_grid_width+=1
480               
481                if self.current_grid_width > self.max_grid_width:
482                        self.current_grid_width=0
483                        self.current_grid_height+=1
484                       
485                       
486        #def add_grid_button
487       
488       
489        def button_clicked(self,widget,event,grid_button):
490               
491                if not (grid_button.info["installed"] or grid_button.info["incompatible"]):
492                        if grid_button.info["checked"]:
493                                self.install_metas.remove(grid_button)
494                                grid_button.info["checked"]=False
495                                grid_button.info["drawingarea"].queue_draw()
496                                self.mouse_left(grid_button.info["drawingarea"],None,grid_button)
497                        else:
498                                self.install_metas.append(grid_button)
499                                grid_button.info["checked"]=True
500                                grid_button.info["shadow_alpha"]+=0.1
501                               
502                                widget.queue_draw()
503               
504        #def button_clicked
505       
506       
507        def accept_clicked(self,widget,even=None):
508               
509                ret, msg=self.check_meta_compatibility()
510               
511                if not ret:
512                        self.msg_label.show()
513                        self.msg_label.set_markup(msg)
514                        return
515                else:
516                        self.msg_label.hide()
517                        self.show_confirm_dialog(widget)
518       
519        # def accept_clicked                   
520       
521        def show_confirm_dialog(self, widget):
522                message=_("The selected flavours will be installed. Do you wish to continue?")
523                label = Gtk.Label(message)
524
525                dialog = Gtk.Dialog("Warning", None, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT, (Gtk.STOCK_YES, Gtk.ResponseType.YES, Gtk.STOCK_NO, Gtk.ResponseType.NO))
526                dialog.vbox.pack_start(label,True,True,10)
527
528                label.show()
529                #dialog.set_border_width(6)
530                dialog.set_name("BACK_GRADIENT")
531                label.set_name("DIALOG_LABEL")
532
533                response = dialog.run()
534
535                if response==Gtk.ResponseType.YES:
536                        self.install_packages(widget)
537                dialog.destroy()               
538               
539        # def show_confirm_dialog       
540                               
541        def install_packages(self,widget):
542               
543                       
544                cmd='apt-get update && apt-get install -y '
545                pkg=""
546                for item in self.update_metas:
547                        pkg+=item.info["pkg"] + ' '
548                       
549                for item in self.install_metas:
550                        pkg+=item.info["pkg"] + ' '
551               
552                command=cmd+pkg
553       
554                self.t=threading.Thread(target=self.execute,args=(command,))
555                self.t.daemon=True
556                self.t.start()
557                GLib.timeout_add(100,self.pulsate_pbar,widget)
558                self.progress_window.show()     
559               
560               
561        # def install_packages 
562               
563        def check_meta_compatibility(self):
564                               
565                if len(self.install_metas)>0:
566                       
567                        for gb in self.gbs:
568                                if gb.info["available"]:
569                                        if gb.info["installed"]:
570                                                if not gb in self.update_metas:
571                                                        self.update_metas.append(gb)
572                                                       
573                                                if gb.info["pkg"]=="lliurex-meta-server":
574                                                        for item in self.install_metas:
575                                                                if item.info["pkg"]=="lliurex-meta-client":
576                                                                        return [False,_("Incompatibility between Server and Client detected")]
577                                                                                                                                               
578                                                                if item.info["pkg"]=="lliurex-meta-desktop":
579                                                                        return [False, _("Is not possible adding Desktop Flavour in Server")]   
580                                                                       
581                                                if gb.info["pkg"]=="lliurex-meta-client":
582                                                        for item in self.install_metas:
583                                                                if item.info["pkg"]=="lliurex-meta-server":
584                                                                        return [False,_("Incompatibility between Server and Client detected")]
585                                               
586                                                if gb.info["pkg"]=="lliurex-meta-desktop":
587                                                        for item in self.install_metas:
588                                                                if item.info["pkg"]=="lliurex-meta-server":
589                                                                        if  gb in self.update_metas:
590                                                                                self.update_metas.remove(gb)                   
591                        i=0             
592                       
593                        for item in self.install_metas:
594                                if item.info["pkg"]=="lliurex-meta-server":
595                                        i+=1
596                                        for item in self.install_metas:
597                                                if item.info["pkg"]=="lliurex-meta-client":
598                                                        i+=1
599                                                if item.info["pkg"]=="lliurex-meta-desktop":
600                                                        self.install_metas.remove(item)
601                                                        self.remove_desktop=item
602                                                                       
603                        if i>1:
604                                return [False,_("Incompatibility between Server and Client detected")]
605                       
606                        return [True,""]
607                       
608                else:
609                        return [False,_("Choose new flavour to incorporate or close button")]
610                       
611        #def check_meta_compatibility
612                               
613        def draw_button(self,widget,ctx,grid_button):
614               
615                ctx.move_to(0,0)
616                img=cairo.ImageSurface.create_from_png(SHADOW_BANNER)
617                ctx.set_source_surface(img,0,grid_button.info["shadow_start"])
618                ctx.paint_with_alpha(grid_button.info["shadow_alpha"])
619               
620                ctx.move_to(0,0)
621                img=cairo.ImageSurface.create_from_png(grid_button.info["image"])
622                ctx.set_source_surface(img,0,0)
623                ctx.paint()
624               
625                ctx.move_to(0,0)
626                ctx.set_source_rgba(1,1,1,1)
627                ctx.rectangle(0,110,140,30)
628                ctx.fill()
629               
630               
631                ctx.set_source_rgba(self.dark_gray.r,self.dark_gray.g,self.dark_gray.b,1)
632               
633                pctx = PangoCairo.create_layout(ctx)
634                desc = Pango.font_description_from_string ("Noto Sans Bold 7.5")
635                pctx.set_font_description(desc)
636                pctx.set_markup(grid_button.info["name"])
637                ctx.move_to(5,118)
638                PangoCairo.show_layout(ctx, pctx)
639                width=pctx.get_pixel_size()[0]
640               
641               
642               
643                if grid_button.info["installed"]:
644               
645                        desc = Pango.font_description_from_string ("Noto Sans Bold 7")
646                        pctx.set_font_description(desc)
647                        ctx.set_source_rgba(self.green.r,self.green.g,self.green.b,1)
648                        txt=_("Installed")
649                        pctx.set_markup(txt)
650                        width=pctx.get_pixel_size()[0]
651                        ctx.move_to(140-width-5,120)
652                        PangoCairo.show_layout(ctx, pctx)
653                       
654                        ctx.rectangle(5,139,130,1)
655                        ctx.fill()
656               
657                if grid_button.info["checked"]:
658               
659                        desc = Pango.font_description_from_string ("Noto Sans Bold 7")
660                        pctx.set_font_description(desc)
661                        ctx.set_source_rgba(self.green.r,self.green.g,self.green.b,1)
662                        txt=_("Install")
663                        pctx.set_markup(txt)
664                        width=pctx.get_pixel_size()[0]
665                        ctx.move_to(140-width-5,120)
666                        PangoCairo.show_layout(ctx, pctx)
667                       
668                        ctx.rectangle(5,139,130,1)
669                        ctx.fill()
670               
671
672                if grid_button.info["incompatible"]:
673               
674                        desc = Pango.font_description_from_string ("Noto Sans Bold 7")
675                        pctx.set_font_description(desc)
676                        ctx.set_source_rgba(255,0,0,1)
677                        txt=_("Incompatible")
678                        pctx.set_markup(txt)
679                        width=pctx.get_pixel_size()[0]
680                        ctx.move_to(140-width-5,120)
681                        PangoCairo.show_layout(ctx, pctx)
682                       
683                        ctx.rectangle(5,139,130,1)
684                        ctx.fill()
685        #def draw_button
686       
687       
688        def drawing_label_event(self,widget,ctx,id):
689               
690                if id==self.current_tab:
691
692                        lg1 = cairo.LinearGradient(0.0,0.0, 300.0, 3.0)
693                        lg1.add_color_stop_rgba(0, 0, 1, 1, 0)
694                        lg1.add_color_stop_rgba(0.5, 0, 1, 1, 1)
695                        lg1.add_color_stop_rgba(1, 0, 1, 1, 0)
696                        ctx.rectangle(0, 0, 300, 3)
697                        ctx.set_source(lg1)
698                        ctx.fill()
699                       
700        #drawing_label_event
701       
702       
703        def draw_apply_button(self,widget,ctx):
704               
705               
706                button_border=22
707               
708                pctx = PangoCairo.create_layout(ctx)
709                desc = Pango.font_description_from_string ("Noto Sans Bold 10")
710                pctx.set_font_description(desc)
711               
712                pctx.set_markup(_("APPLY"))
713                width=pctx.get_pixel_size()[0]
714                widget.set_size_request(width+button_border*2,30)
715               
716                ctx.set_source_rgba(1,1,0,1)
717                xx=0
718                yx=0
719                widthx=width+44
720                heightx=30
721                radius=5
722               
723                r=47.0
724                g=167.0
725                b=223.0
726                alpha=1.0
727               
728                r=r/255.0
729                g=g/255.0
730                b=b/255.0
731               
732                r2=83
733                g2=153
734                b2=252
735               
736                r2=r2/255.0
737                g2=g2/255.0
738                b2=b2/255.0
739               
740               
741                lg1 = cairo.LinearGradient(0.0,0.0, 90.0, 0)
742                lg1.add_color_stop_rgba(0, r, g, b, 1)
743                lg1.add_color_stop_rgba(1, r2, g2, b2, 1)
744                ctx.set_source(lg1)
745               
746               
747                ctx.move_to (xx + radius, yx);
748                ctx.arc (xx + widthx - radius, yx + radius, radius, pi * 1.5, pi * 2);
749                ctx.arc (xx + widthx - radius, yx + heightx - radius, radius, 0, pi * .5);
750                ctx.arc (xx + radius, yx + heightx - radius, radius, pi * .5, pi);
751                ctx.arc (xx + radius, yx + radius, radius, pi , pi * 1.5);
752                ctx.fill ();
753               
754                ctx.set_source_rgb(0.9,0.9,0.9)
755                ctx.move_to(button_border,7)
756                PangoCairo.show_layout(ctx, pctx)
757       
758        #draw_apply_button
759       
760        def draw_close_button(self,widget,ctx):
761               
762               
763                button_border=22
764               
765                pctx = PangoCairo.create_layout(ctx)
766                desc = Pango.font_description_from_string ("Noto Sans Bold 10")
767                pctx.set_font_description(desc)
768               
769                pctx.set_markup(_("CLOSE"))
770                width=pctx.get_pixel_size()[0]
771                widget.set_size_request(width+button_border*2,30)
772               
773                ctx.set_source_rgba(1,1,0,1)
774                xx=0
775                yx=0
776                widthx=width+44
777                heightx=30
778                radius=5
779               
780                r=47.0
781                g=167.0
782                b=223.0
783                alpha=1.0
784               
785                r=r/255.0
786                g=g/255.0
787                b=b/255.0
788               
789                r2=83
790                g2=153
791                b2=252
792               
793                r2=r2/255.0
794                g2=g2/255.0
795                b2=b2/255.0
796               
797               
798                lg1 = cairo.LinearGradient(0.0,0.0, 90.0, 0)
799                lg1.add_color_stop_rgba(0, r, g, b, 1)
800                lg1.add_color_stop_rgba(1, r2, g2, b2, 1)
801                ctx.set_source(lg1)
802               
803               
804                ctx.move_to (xx + radius, yx);
805                ctx.arc (xx + widthx - radius, yx + radius, radius, pi * 1.5, pi * 2);
806                ctx.arc (xx + widthx - radius, yx + heightx - radius, radius, 0, pi * .5);
807                ctx.arc (xx + radius, yx + heightx - radius, radius, pi * .5, pi);
808                ctx.arc (xx + radius, yx + radius, radius, pi , pi * 1.5);
809                ctx.fill ();
810               
811                ctx.set_source_rgb(0.9,0.9,0.9)
812                ctx.move_to(button_border,7)
813                PangoCairo.show_layout(ctx, pctx)
814               
815        #def draw_close_button
816
817       
818        def draw_top_divider(self,widget,ctx):
819               
820                r=self.dark_gray.r
821                g=self.dark_gray.g
822                b=self.dark_gray.b
823                alpha=1.0
824               
825                ctx.set_source_rgba(r,g,b,alpha)
826                ctx.rectangle(0,1,500,3)
827                ctx.fill()
828               
829               
830        #def draw_top_divider
831       
832       
833        def draw_bottom_divider(self,widget,ctx):
834               
835                r=self.dark_gray.r
836                g=self.dark_gray.g
837                b=self.dark_gray.b
838                alpha=1.0
839               
840                ctx.set_source_rgba(r,g,b,alpha)
841                ctx.rectangle(0,1,500,3)
842                ctx.fill()
843               
844        #def draw_bottom_divider
845       
846       
847        def mouse_over(self,widget,event,grid_button):
848               
849                grid_button.info["animation_active"]=False
850                if grid_button.info["shadow_alpha"] <0.5 :
851                        grid_button.info["shadow_alpha"]+=0.1
852                        widget.queue_draw()
853                        return True
854                       
855                return False
856               
857        #def mouse_over
858
859        def mouse_left(self,widget,event,grid_button):
860                if not grid_button.info["checked"]:
861                        if not grid_button.info["animation_active"]:
862                       
863                                grid_button.info["animation_active"]=True
864                                GLib.timeout_add(10,self.restore_shadow_alpha,grid_button,widget)
865                       
866        #def mouse_left
867
868       
869        def restore_shadow_alpha(self,grid_button,widget):
870               
871                if grid_button.info["shadow_alpha"] >0.2 :
872                        grid_button.info["shadow_alpha"]-=0.1
873               
874                        widget.queue_draw()
875                        return True
876                       
877                grid_button.info["animation_active"]=False
878                return False
879               
880        # def restore_shadow_alfpha     
881
882        def log(self,error):
883                log_file="/tmp/lliurex-flavour-selector"
884                f=open(log_file,"a")
885                f.write("[" +datetime.datetime.today().strftime("%d/%m/%y %H:%M:%S") + " ] " + "\n" + error + "\n")
886                f.close()
887               
888        # def log               
889               
890
891                       
892#awesome tabs
893
894if __name__=="__main__":
895       
896        at=AwesomeTabs()
Note: See TracBrowser for help on using the repository browser.