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

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

Adds recursos repository when installing infantil flavour

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