source: zero-lliurex-installers/trunk/fuentes/zero-lliurex-recursos.install/usr/share/zero-lliurex-recursos/lliurex-resources-installer.py @ 5681

Last change on this file since 5681 was 5681, checked in by jrpelegrina, 2 years ago

WIP in new gui for zero-lliurex-recursos

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