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

Last change on this file since 3407 was 3407, checked in by Juanma, 2 years ago

Adds recursos repository when installing infantil flavour

  • Property svn:executable set to *
File size: 22.8 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                        log_msg=("Removing recursos repository from sources")
446                        self.log(log_msg)
447                        reposInfantil=glob.glob("/etc/apt/sources.list.d/*recursos*")
448                        for repo in reposInfantil:
449                                os.remove(repo)
450                        cmdInfantil=("apt-get","update")
451                        x=subprocess.Popen(cmdInfantil,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
452                        x.communicate()
453                self.thread_ret=p.returncode
454                self.flavour_error=output[1]
455               
456        #def execute
457       
458       
459        def pulsate_pbar(self,da):
460               
461                if self.t.is_alive():
462                       
463                        self.pbar.pulse()
464                               
465                if not self.t.is_alive():
466                        self.progress_window.hide()
467                        if self.thread_ret==0:
468                                for item in self.install_metas:
469                               
470                                        if item.info["checked"]:
471                                                item.info["checked"]=False
472                                                item.info["drawingarea"].queue_draw()
473                                                self.mouse_left(item.info["drawingarea"],None,item)
474                                                item.info["installed"]=True
475                                try:
476                                        self.remove_desktop.info["checked"]=False
477                                        self.remove_desktop.info["drawingarea"].queue_draw()
478                                        self.mouse_left(self.remove_desktop.info["drawingarea"],None,self.remove_desktop)
479                                except:
480                                        print "No desktop flavour to remove"
481                                       
482                                self.install_metas=[]   
483                                self.msg_label.show()
484                                self.msg_label.set_markup("<span foreground='#4aa645'><b>"+_("Installation succesful. A reboot is required")+"</b></span>")
485                                log_msg="Installation of new flavour OK"
486                                self.log(log_msg)
487                        else:
488                                self.msg_label.show()
489                                msg=_("An error ocurred. See log in /var/log/lliurex-flavours-selector")
490                                self.msg_label.set_markup(msg)
491                                log_msg="Error during installation of new flavours. " + self.flavour_error
492                                self.log(log_msg)       
493                return self.t.is_alive()
494       
495        #def pulsate_pbar
496
497       
498       
499               
500        def add_grid_button(self,grid_button):
501               
502                da=Gtk.DrawingArea()
503                da.set_size_request(140,148)
504                da.add_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.BUTTON_PRESS_MASK )
505               
506                da.connect("draw",self.draw_button,grid_button)
507                da.connect("motion-notify-event",self.mouse_over,grid_button)
508                da.connect("leave_notify_event",self.mouse_left,grid_button)
509                da.connect("button-press-event",self.button_clicked,grid_button)
510                grid_button.info["drawingarea"]=da
511               
512                da.show()
513                self.installers_grid.attach(da,self.current_grid_width,self.current_grid_height,1,1)
514               
515                self.current_grid_width+=1
516               
517                if self.current_grid_width > self.max_grid_width:
518                        self.current_grid_width=0
519                        self.current_grid_height+=1
520                       
521                       
522        #def add_grid_button
523       
524       
525        def button_clicked(self,widget,event,grid_button):
526               
527                if not (grid_button.info["installed"] or grid_button.info["incompatible"]):
528                        if grid_button.info["checked"]:
529                                self.install_metas.remove(grid_button)
530                                grid_button.info["checked"]=False
531                                grid_button.info["drawingarea"].queue_draw()
532                                self.mouse_left(grid_button.info["drawingarea"],None,grid_button)
533                        else:
534                                self.install_metas.append(grid_button)
535                                grid_button.info["checked"]=True
536                                grid_button.info["shadow_alpha"]+=0.1
537                               
538                                widget.queue_draw()
539               
540        #def button_clicked
541       
542       
543        def accept_clicked(self,widget,even=None):
544               
545                ret, msg=self.check_meta_compatibility()
546               
547                if not ret:
548                        self.msg_label.show()
549                        self.msg_label.set_markup(msg)
550                        return
551                else:
552                        self.msg_label.hide()
553                        self.show_confirm_dialog(widget)
554       
555        # def accept_clicked                   
556       
557        def show_confirm_dialog(self, widget):
558                message=_("The selected flavours will be installed. Do you wish to continue?")
559                label = Gtk.Label(message)
560
561                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))
562                dialog.vbox.pack_start(label,True,True,10)
563
564                label.show()
565                dialog.set_border_width(6)
566                dialog.set_name("BACK_GRADIENT")
567                label.set_name("DIALOG_LABEL")
568
569                response = dialog.run()
570
571                if response==Gtk.ResponseType.YES:
572                        self.install_packages(widget)
573                dialog.destroy()               
574               
575        # def show_confirm_dialog       
576                               
577        def install_packages(self,widget):
578               
579                       
580                cmd='lliurex-preseed --update; apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y '
581                pkg=""
582                log_pkg=""
583                for item in self.update_metas:
584                        pkg+=item.info["pkg"] + ' '
585                       
586                for item in self.install_metas:
587                        if item.info["pkg"]=="lliurex-meta-infantil":
588                                cmdInfantil=["sudo","/usr/bin/add-apt-repository", "ppa:llxdev/recursos"]
589                                x=subprocess.Popen((cmdInfantil),stdin=subprocess.PIPE,stdout=subprocess.PIPE)
590                                log_msg="Adding repository recursos"
591                                self.log(log_msg)
592                                x.communicate("\n")[0]
593
594                        pkg+=item.info["pkg"] + ' '
595                        log_pkg=log_pkg+item.info["pkg"]+ ' '
596
597                command=cmd+pkg
598       
599                self.t=threading.Thread(target=self.execute,args=(command,))
600                self.t.daemon=True
601                self.t.start()
602                log_msg="-New flavours to install:"
603                self.log(log_msg)
604                log_msg=str(log_pkg)
605                self.log(log_msg)
606                GLib.timeout_add(100,self.pulsate_pbar,widget)
607                self.progress_window.show()     
608               
609               
610        # def install_packages 
611               
612        def check_meta_compatibility(self):
613                               
614                if len(self.install_metas)>0:
615                       
616                        for gb in self.gbs:
617                                if gb.info["available"]:
618                                        if gb.info["installed"]:
619                                                if not gb in self.update_metas:
620                                                        self.update_metas.append(gb)
621                                                       
622                                                if gb.info["pkg"]=="lliurex-meta-server":
623                                                        for item in self.install_metas:
624                                                                if item.info["pkg"]=="lliurex-meta-client":
625                                                                        return [False,_("Incompatibility between Server and Client detected")]
626                                                                                                                                               
627                                                                if item.info["pkg"]=="lliurex-meta-desktop":
628                                                                        return [False, _("Is not possible adding Desktop Flavour in Server")]   
629                                                                       
630                                                if gb.info["pkg"]=="lliurex-meta-client":
631                                                        for item in self.install_metas:
632                                                                if item.info["pkg"]=="lliurex-meta-server":
633                                                                        return [False,_("Incompatibility between Server and Client detected")]
634                                               
635                                                if gb.info["pkg"]=="lliurex-meta-desktop":
636                                                        for item in self.install_metas:
637                                                                if item.info["pkg"]=="lliurex-meta-server":
638                                                                        if  gb in self.update_metas:
639                                                                                self.update_metas.remove(gb)                   
640                        i=0             
641                       
642                        for item in self.install_metas:
643                                if item.info["pkg"]=="lliurex-meta-server":
644                                        i+=1
645                                        for item in self.install_metas:
646                                                if item.info["pkg"]=="lliurex-meta-client":
647                                                        i+=1
648                                                if item.info["pkg"]=="lliurex-meta-desktop":
649                                                        self.install_metas.remove(item)
650                                                        self.remove_desktop=item
651                                                                       
652                        if i>1:
653                                return [False,_("Incompatibility between Server and Client detected")]
654                       
655                        return [True,""]
656                       
657                else:
658                        return [False,_("Choose new flavour to incorporate or close button")]
659                       
660        #def check_meta_compatibility
661                               
662        def draw_button(self,widget,ctx,grid_button):
663               
664                ctx.move_to(0,0)
665                img=cairo.ImageSurface.create_from_png(SHADOW_BANNER)
666                ctx.set_source_surface(img,0,grid_button.info["shadow_start"])
667                ctx.paint_with_alpha(grid_button.info["shadow_alpha"])
668               
669                ctx.move_to(0,0)
670                img=cairo.ImageSurface.create_from_png(grid_button.info["image"])
671                ctx.set_source_surface(img,0,0)
672                ctx.paint()
673               
674                ctx.move_to(0,0)
675                ctx.set_source_rgba(1,1,1,1)
676                ctx.rectangle(0,110,140,30)
677                ctx.fill()
678               
679               
680                ctx.set_source_rgba(self.dark_gray.r,self.dark_gray.g,self.dark_gray.b,1)
681               
682                pctx = PangoCairo.create_layout(ctx)
683                desc = Pango.font_description_from_string ("Noto Sans Bold 7.5")
684                pctx.set_font_description(desc)
685                pctx.set_markup(grid_button.info["name"])
686                ctx.move_to(5,118)
687                PangoCairo.show_layout(ctx, pctx)
688                width=pctx.get_pixel_size()[0]
689               
690               
691               
692                if grid_button.info["installed"]:
693               
694                        desc = Pango.font_description_from_string ("Noto Sans Bold 7")
695                        pctx.set_font_description(desc)
696                        ctx.set_source_rgba(self.green.r,self.green.g,self.green.b,1)
697                        txt=_("Installed")
698                        pctx.set_markup(txt)
699                        width=pctx.get_pixel_size()[0]
700                        ctx.move_to(140-width-5,120)
701                        PangoCairo.show_layout(ctx, pctx)
702                       
703                        ctx.rectangle(5,139,130,1)
704                        ctx.fill()
705               
706                if grid_button.info["checked"]:
707               
708                        desc = Pango.font_description_from_string ("Noto Sans Bold 7")
709                        pctx.set_font_description(desc)
710                        ctx.set_source_rgba(self.green.r,self.green.g,self.green.b,1)
711                        txt=_("Install")
712                        pctx.set_markup(txt)
713                        width=pctx.get_pixel_size()[0]
714                        ctx.move_to(140-width-5,120)
715                        PangoCairo.show_layout(ctx, pctx)
716                       
717                        ctx.rectangle(5,139,130,1)
718                        ctx.fill()
719               
720
721                if grid_button.info["incompatible"]:
722               
723                        desc = Pango.font_description_from_string ("Noto Sans Bold 7")
724                        pctx.set_font_description(desc)
725                        ctx.set_source_rgba(255,0,0,1)
726                        txt=_("Incompatible")
727                        pctx.set_markup(txt)
728                        width=pctx.get_pixel_size()[0]
729                        ctx.move_to(140-width-5,120)
730                        PangoCairo.show_layout(ctx, pctx)
731                       
732                        ctx.rectangle(5,139,130,1)
733                        ctx.fill()
734        #def draw_button
735       
736       
737        def drawing_label_event(self,widget,ctx,id):
738               
739                if id==self.current_tab:
740
741                        lg1 = cairo.LinearGradient(0.0,0.0, 300.0, 3.0)
742                        lg1.add_color_stop_rgba(0, 0, 1, 1, 0)
743                        lg1.add_color_stop_rgba(0.5, 0, 1, 1, 1)
744                        lg1.add_color_stop_rgba(1, 0, 1, 1, 0)
745                        ctx.rectangle(0, 0, 300, 3)
746                        ctx.set_source(lg1)
747                        ctx.fill()
748                       
749        #drawing_label_event
750       
751       
752        def draw_apply_button(self,widget,ctx):
753               
754               
755                button_border=22
756               
757                pctx = PangoCairo.create_layout(ctx)
758                desc = Pango.font_description_from_string ("Noto Sans Bold 10")
759                pctx.set_font_description(desc)
760               
761                pctx.set_markup(_("APPLY"))
762                width=pctx.get_pixel_size()[0]
763                widget.set_size_request(width+button_border*2,30)
764               
765                ctx.set_source_rgba(1,1,0,1)
766                xx=0
767                yx=0
768                widthx=width+44
769                heightx=30
770                radius=5
771               
772                r=47.0
773                g=167.0
774                b=223.0
775                alpha=1.0
776               
777                r=r/255.0
778                g=g/255.0
779                b=b/255.0
780               
781                r2=83
782                g2=153
783                b2=252
784               
785                r2=r2/255.0
786                g2=g2/255.0
787                b2=b2/255.0
788               
789               
790                lg1 = cairo.LinearGradient(0.0,0.0, 90.0, 0)
791                lg1.add_color_stop_rgba(0, r, g, b, 1)
792                lg1.add_color_stop_rgba(1, r2, g2, b2, 1)
793                ctx.set_source(lg1)
794               
795               
796                ctx.move_to (xx + radius, yx);
797                ctx.arc (xx + widthx - radius, yx + radius, radius, pi * 1.5, pi * 2);
798                ctx.arc (xx + widthx - radius, yx + heightx - radius, radius, 0, pi * .5);
799                ctx.arc (xx + radius, yx + heightx - radius, radius, pi * .5, pi);
800                ctx.arc (xx + radius, yx + radius, radius, pi , pi * 1.5);
801                ctx.fill ();
802               
803                ctx.set_source_rgb(0.9,0.9,0.9)
804                ctx.move_to(button_border,7)
805                PangoCairo.show_layout(ctx, pctx)
806       
807        #draw_apply_button
808       
809        def draw_close_button(self,widget,ctx):
810               
811               
812                button_border=22
813               
814                pctx = PangoCairo.create_layout(ctx)
815                desc = Pango.font_description_from_string ("Noto Sans Bold 10")
816                pctx.set_font_description(desc)
817               
818                pctx.set_markup(_("CLOSE"))
819                width=pctx.get_pixel_size()[0]
820                widget.set_size_request(width+button_border*2,30)
821               
822                ctx.set_source_rgba(1,1,0,1)
823                xx=0
824                yx=0
825                widthx=width+44
826                heightx=30
827                radius=5
828               
829                r=47.0
830                g=167.0
831                b=223.0
832                alpha=1.0
833               
834                r=r/255.0
835                g=g/255.0
836                b=b/255.0
837               
838                r2=83
839                g2=153
840                b2=252
841               
842                r2=r2/255.0
843                g2=g2/255.0
844                b2=b2/255.0
845               
846               
847                lg1 = cairo.LinearGradient(0.0,0.0, 90.0, 0)
848                lg1.add_color_stop_rgba(0, r, g, b, 1)
849                lg1.add_color_stop_rgba(1, r2, g2, b2, 1)
850                ctx.set_source(lg1)
851               
852               
853                ctx.move_to (xx + radius, yx);
854                ctx.arc (xx + widthx - radius, yx + radius, radius, pi * 1.5, pi * 2);
855                ctx.arc (xx + widthx - radius, yx + heightx - radius, radius, 0, pi * .5);
856                ctx.arc (xx + radius, yx + heightx - radius, radius, pi * .5, pi);
857                ctx.arc (xx + radius, yx + radius, radius, pi , pi * 1.5);
858                ctx.fill ();
859               
860                ctx.set_source_rgb(0.9,0.9,0.9)
861                ctx.move_to(button_border,7)
862                PangoCairo.show_layout(ctx, pctx)
863               
864        #def draw_close_button
865
866       
867        def draw_top_divider(self,widget,ctx):
868               
869                r=self.dark_gray.r
870                g=self.dark_gray.g
871                b=self.dark_gray.b
872                alpha=1.0
873               
874                ctx.set_source_rgba(r,g,b,alpha)
875                ctx.rectangle(0,1,500,3)
876                ctx.fill()
877               
878               
879        #def draw_top_divider
880       
881       
882        def draw_bottom_divider(self,widget,ctx):
883               
884                r=self.dark_gray.r
885                g=self.dark_gray.g
886                b=self.dark_gray.b
887                alpha=1.0
888               
889                ctx.set_source_rgba(r,g,b,alpha)
890                ctx.rectangle(0,1,500,3)
891                ctx.fill()
892               
893        #def draw_bottom_divider
894       
895       
896        def mouse_over(self,widget,event,grid_button):
897               
898                grid_button.info["animation_active"]=False
899                if grid_button.info["shadow_alpha"] <0.5 :
900                        grid_button.info["shadow_alpha"]+=0.1
901                        widget.queue_draw()
902                        return True
903                       
904                return False
905               
906        #def mouse_over
907
908        def mouse_left(self,widget,event,grid_button):
909                if not grid_button.info["checked"]:
910                        if not grid_button.info["animation_active"]:
911                       
912                                grid_button.info["animation_active"]=True
913                                GLib.timeout_add(10,self.restore_shadow_alpha,grid_button,widget)
914                       
915        #def mouse_left
916
917       
918        def restore_shadow_alpha(self,grid_button,widget):
919               
920                if grid_button.info["shadow_alpha"] >0.2 :
921                        grid_button.info["shadow_alpha"]-=0.1
922               
923                        widget.queue_draw()
924                        return True
925                       
926                grid_button.info["animation_active"]=False
927                return False
928               
929        # def restore_shadow_alfpha     
930
931        def log(self,log_msg):
932                log_file="/var/log/lliurex-flavour-selector.log"
933                f=open(log_file,"a+")
934                f.write(log_msg + '\n')
935                f.close()
936               
937        # def log               
938               
939
940                       
941#awesome tabs
942
943if __name__=="__main__":
944       
945        at=AwesomeTabs()
Note: See TracBrowser for help on using the repository browser.