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

Last change on this file since 3329 was 3329, checked in by jrpelegrina, 3 years ago

Add desktop file and lliurex-preseed update call

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