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

Last change on this file since 3404 was 3404, checked in by Juanma, 3 years ago

Adds recursos repository when installing infantil flavour

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