source: lliurex-mirror/trunk/fuentes/lliurex-mirror-gui/usr/share/lliurex-mirror/lliurex-mirror.py @ 2612

Last change on this file since 2612 was 2612, checked in by hectorgh, 4 years ago

adding project files

  • Property svn:executable set to *
File size: 54.0 KB
Line 
1#!/usr/bin/env python
2
3import gi
4gi.require_version('Gtk', '3.0')
5gi.require_version('PangoCairo', '1.0')
6
7import cairo
8import os
9import threading
10import ConfigParser
11import platform
12import json
13import random
14import xmlrpclib
15import time
16import math
17import sys
18import tempfile
19from math import pi
20import lliurex_mirror_connect
21
22from gi.repository import Gtk, Gdk, GObject, GLib, PangoCairo, Pango,GdkPixbuf
23
24import signal
25signal.signal(signal.SIGINT, signal.SIG_DFL)
26
27import glob
28
29import gettext
30gettext.textdomain('lliurex-mirror')
31_ = gettext.gettext
32
33BANNERS_PATH="./banners/"
34UNKNOWN_BANNER=BANNERS_PATH+"mirror_banner.png"
35SHADOW_BANNER=BANNERS_PATH+"shadow.png"
36MIRROR_CONF_DIR="./mirrors/"
37GLADE_FILE="rsrc/lliurex-mirror.ui"
38ADD_IMAGE="rsrc/a1.png"
39ADD_IMAGE_OVER="rsrc/a2.png"
40TOKEN_FILE="/run/lliurex-mirror.pid"
41ERROR=Gtk.MessageType.ERROR
42INFO=Gtk.MessageType.INFO
43
44class MirrorButton:
45       
46        def __init__(self,info):
47               
48                self.info=info # "pkg"
49                self.info["updating"]=False
50                self.info["exporting"]=False
51                self.info["executing"]=False
52                self.info["shadow_alpha"]=0.1
53                self.info["animation_active"]=False
54                self.info["shadow_start"]=0
55                self.info["available"]=True
56                self.info["degree_offset"]=0
57                self.info["red_position"]=0
58                self.info["red_right"]=True
59                self.info["max_random_lights"]=30
60                self.info["random_lights"]=[]
61                self.info["cancelled"]=False
62               
63                if os.path.exists(BANNERS_PATH+self.info["BANNER"]+".png"):
64                        self.info["image"]=BANNERS_PATH+self.info["BANNER"]+".png"
65                else:
66                        self.info["image"]=UNKNOWN_BANNER
67               
68        #def init
69       
70       
71#class GridButton
72
73class LightPoint:
74       
75        def __init__(self,x,y,radius=None):
76               
77                #self.degree=degree
78                self.radius=radius
79               
80                self.x=x
81                self.y=y
82                self.opacity=1.0
83               
84        #def
85
86class CustomColor:
87       
88        def __init__(self,r,g,b):
89               
90                self.r=r/255.0
91                self.g=g/255.0
92                self.b=b/255.0
93
94#class CustomColor             
95
96class LliurexMirror:
97       
98        def __init__(self):
99       
100                self.frame_size=116
101                self.percentage=0
102                self.circle={}
103                self.circle["x"]=58
104                self.circle["y"]=58
105                self.circle["radius"]=46
106                self.degree_offset=0
107                self.y_offset=5
108               
109                self.wave_xoffset=0
110                self.wave_yoffset=0
111                self.wave_lenght=80
112                self.wave_amplitude=3
113                self.wave_amplitude2=2
114                self.wave_amplitude3=2
115                self.wave_xoffset2=50
116                self.wave_xoffset3=80
117               
118                self.add_flag=False
119               
120                self.current_grid_width=0
121                self.current_grid_height=0
122                self.max_grid_width=2
123       
124                self.dark_gray=CustomColor(130.0,151.0,161.0)
125                self.light_gray=CustomColor(185.0,195.0,195.0)
126               
127                self.green=CustomColor(74.0,166.,69.0)
128                self.light_green=CustomColor(88.0,208.0,86.0)
129               
130               
131                self.conf_light=CustomColor(49.0,55.0,66.0)
132                self.conf_dark=CustomColor(30.0,36.0,42.0)
133               
134                self.conf_light_shadow=CustomColor(107.0,116.0,137.0)
135                self.conf_dark_shadow=CustomColor(0,0,0)
136                self.red=CustomColor(255,0,0)
137               
138                self.update_water_colors=[]
139               
140                self.update_water_colors.append(CustomColor(12,54,64))
141                self.update_water_colors.append(CustomColor(17,92,108))
142                self.update_water_colors.append(CustomColor(0.2*255,0.93*255,0.97*255))
143                self.update_water_colors.append(CustomColor(82, 176, 225))
144                self.update_water_colors.append(CustomColor(68, 159, 255))
145               
146               
147                self.export_water_colors=[]
148               
149               
150               
151                self.export_water_colors.append(CustomColor(29,12,64))
152                self.export_water_colors.append(CustomColor(47,17,108))
153                self.export_water_colors.append(CustomColor(93,51,247))
154                self.export_water_colors.append(CustomColor(153,82,225))
155                self.export_water_colors.append(CustomColor(182,68,225))
156               
157                #self.update_water_colors=self.export_water_colors
158               
159                self.login_animation_x=236 + 127/2
160                self.login_animation_y=131 + 128/2
161                self.login_animation_r=60
162               
163                self.login_enabled=True
164               
165                self.current_mirror=None
166                self.updating_mirror=None
167               
168                self.update_percentage_time=10000
169                self.update_y_time=50
170                self.update_degree_time=50
171                self.update_mirror_button_time=50
172               
173               
174        #def init
175       
176        def check_root(self):
177               
178                try:
179               
180                        f=open(TOKEN_FILE,"w")
181                        f.write(str(os.getpid()))
182                        f.close()
183                       
184                        return True
185                       
186                except:
187                       
188                        dialog = Gtk.MessageDialog(self.window, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.CANCEL, "Lliurex Mirror")
189                        dialog.format_secondary_text("You need administration privileges to run this application.")
190                        dialog.run()
191                        sys.exit(1)
192               
193        #def check_root
194       
195        def start_gui(self):
196               
197                ui_path=GLADE_FILE
198                builder=Gtk.Builder()
199                builder.add_from_file(ui_path)
200               
201               
202               
203               
204                self.stack = Gtk.Stack()
205                self.stack.set_transition_duration(1000)
206                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
207               
208                self.label_image=builder.get_object("label_da")
209                self.label_image1=builder.get_object("label_da1")
210                self.label_image.connect("draw",self.draw_label)
211                self.label_image1.connect("draw",self.draw_label)
212               
213               
214                self.window=builder.get_object("main_window")
215                self.mirror_header_box=builder.get_object("mirror_header_box")
216                self.mirror_name_label=builder.get_object("mirror_name_label")
217                self.conf_mirror_name_label=builder.get_object("conf_mirror_name_label")
218                self.llx_mirror_label=builder.get_object("llx_mirror_label")
219                self.arch_label=builder.get_object("arch_label")
220                self.progress_da=builder.get_object("progress_drawingarea")
221                self.shadow_box=builder.get_object("shadow_box")
222                self.shadow_box1=builder.get_object("shadow_box1")
223                self.shadow_box2=builder.get_object("shadow_box2")
224                self.content_box=builder.get_object("mirror_box")
225                #self.main_content_box=builder.get_object("main_content_box")
226                self.progress_label=builder.get_object("progress_label")
227                self.list_box=builder.get_object("list_box")
228                self.arrow_eb=builder.get_object("arrow_eventbox")
229                self.main_header_box=builder.get_object("main_header_box")
230                self.update_label_box=builder.get_object("update_label_box")
231                self.export_label_box=builder.get_object("export_label_box")
232                self.configuration_label_box=builder.get_object("configuration_label_box")
233                self.folder_fcb=builder.get_object("folder_fcb")
234                self.folder_fcb.connect("file-set",self.folder_fcb_changed)
235                self.local_folder_label=builder.get_object("local_folder_label")
236                self.destination_fcb=builder.get_object("destination_fcb")
237                self.destination_fcb.connect("file-set",self.destination_fcb_changed)
238                self.destination_label=builder.get_object("destination_label")
239                self.scrolledwindow=builder.get_object("scrolledwindow1")
240               
241                self.internet_rb=builder.get_object("internet_rb")
242                self.local_folder_rb=builder.get_object("local_folder_rb")
243                self.url_rb=builder.get_object("url_rb")
244                self.url_entry=builder.get_object("url_entry")
245               
246                self.configuration_infobar=builder.get_object("configuration_infobar")
247                self.configuration_panel_label=builder.get_object("configuration_panel_label")
248                self.configuration_infobar.connect("response",self.ib_response)
249               
250                self.arrow_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK )
251                self.arrow_eb.connect("button-release-event",self.arrow_clicked)
252               
253                self.update_eb=builder.get_object("update_eventbox")
254                self.update_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK )
255                self.update_eb.connect("motion-notify-event",self.mouse_over_update)
256                self.update_eb.connect("leave_notify_event",self.mouse_exit_update)
257                self.update_eb.connect("button-release-event",self.update_clicked)
258               
259                self.export_eb=builder.get_object("export_eventbox")
260                self.export_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK )
261                self.export_eb.connect("motion-notify-event",self.mouse_over_export)
262                self.export_eb.connect("leave_notify_event",self.mouse_exit_export)
263                self.export_eb.connect("button-release-event",self.export_clicked)
264               
265                self.configuration_eb=builder.get_object("configuration_eventbox")
266                self.configuration_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK )
267                self.configuration_eb.connect("motion-notify-event",self.mouse_over_conf)
268                self.configuration_eb.connect("leave_notify_event",self.mouse_exit_conf)
269                self.configuration_eb.connect("button-release-event",self.conf_clicked)
270               
271               
272                self.configuration_box=builder.get_object("configuration_box")
273                self.configuration_header_box=builder.get_object("configuration_header_box")
274                self.configuration_arrow_eb=builder.get_object("configuration_arrow_eventbox")
275                self.configuration_arrow_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK )
276                self.configuration_arrow_eb.connect("button-release-event",self.configuration_arrow_clicked)
277               
278                self.name_label=builder.get_object("name_label")
279                self.banner_label=builder.get_object("banner_label")
280                self.origin_label=builder.get_object("origin_label")
281                self.distributions_label=builder.get_object("distributions_label")
282                self.sections_label=builder.get_object("sections_label")
283                self.architectures_label=builder.get_object("architectures_label")
284                self.local_path_label=builder.get_object("local_path_label")
285                self.check_md5_label=builder.get_object("check_md5_label")
286                self.ign_gpg_label=builder.get_object("ign_gpg_label")
287                self.ign_release_label=builder.get_object("ign_release_label")
288               
289                self.name_entry=builder.get_object("name_entry")
290                self.banner_combobox=builder.get_object("banner_combobox")
291                self.origin_entry=builder.get_object("origin_entry")
292                self.distributions_entry=builder.get_object("distributions_entry")
293                self.sections_entry=builder.get_object("sections_entry")
294                self.i386_cb=builder.get_object("i386_checkbutton")
295                self.amd64_cb=builder.get_object("amd64_checkbutton")
296                self.mirror_path_entry=builder.get_object("mirror_path_entry")
297                self.check_md5_cb=builder.get_object("check_md5_checkbutton")
298                self.ign_gpg_cb=builder.get_object("ign_gpg_checkbutton")
299                self.ign_release_cb=builder.get_object("ign_release_checkbutton")
300               
301               
302                self.save_button_box=builder.get_object("save_button_box")
303                self.save_eb=builder.get_object("save_eventbox")
304                self.save_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK  )
305                self.save_eb.connect("button-release-event",self.save_button_clicked)
306                self.save_eb.connect("motion-notify-event",self.mouse_over_save)
307                self.save_eb.connect("leave_notify_event",self.mouse_exit_save)
308               
309                self.export_label=builder.get_object("export_label")
310                self.update_label=builder.get_object("update_label")
311                self.save_label=builder.get_object("save_label")
312                self.conf_label=builder.get_object("conf_label")
313                self.i386_label=builder.get_object("i386_label")
314                self.amd64_label=builder.get_object("amd64_label")
315               
316                self.update_header_label=builder.get_object("update_header_label")
317                self.export_header_label=builder.get_object("export_header_label")
318                self.internet_rb_label=builder.get_object("internet_rb_label")
319                self.internet_rb_label=builder.get_object("internet_rb_label")
320                self.local_folder_rb_label=builder.get_object("local_folder_rb_label")
321                self.url_rb_label=builder.get_object("url_rb_label")
322                self.destination_opt_label=builder.get_object("destination_opt_label")
323                               
324                self.ib=builder.get_object("infobar1")
325                self.ib.connect("response",self.ib_response)
326                self.info_label=builder.get_object("info_label")
327               
328                self.info_button=builder.get_object("info_button")
329                self.info_button.connect("clicked",self.info_button_clicked)
330               
331                self.main_content_box=Gtk.Grid()
332                self.main_content_box.set_column_homogeneous(True)
333                self.main_content_box.set_row_spacing(10)
334                self.main_content_box.set_margin_top(15)
335                self.main_content_box.set_margin_left(40)
336               
337                self.viewport=builder.get_object("viewport1")
338                self.viewport.add(self.main_content_box)
339               
340       
341                self.overlay=Gtk.Overlay()
342                self.overlay.add(self.list_box)
343                self.overlay.show_all()
344               
345                eb=Gtk.EventBox()
346                eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK  )
347                b=Gtk.Image()
348               
349                eb.connect("button-release-event",self.add_clicked)
350                eb.connect("motion-notify-event",self.add_mouse_over,b)
351                eb.connect("leave_notify_event",self.add_mouse_left,b)
352                b.set_from_file(ADD_IMAGE)
353                b.show()
354               
355                eb.add(b)
356               
357                eb.set_valign(Gtk.Align.END)
358                eb.set_halign(Gtk.Align.END)
359                eb.set_margin_bottom(5)
360                eb.set_margin_right(20)
361                self.overlay.add_overlay(eb)
362               
363               
364                self.login_da_box=builder.get_object("login_da_box")
365                self.login_da=builder.get_object("login_drawingarea")
366                self.login_da.connect("draw",self.draw_login)
367               
368                self.login_overlay=Gtk.Overlay()
369                self.login_overlay.add(self.login_da_box)
370               
371                '''
372                self.login_box=Gtk.VBox()
373               
374                self.login_button=Gtk.Button("Login")
375                self.login_button.connect("clicked",self.login_clicked)
376               
377                self.login_box.pack_end(self.login_button,False,True,5)
378                self.login_box.pack_end(Gtk.Entry(),False,True,5)
379                self.login_box.pack_end(Gtk.Entry(),False,True,5)
380                self.tmp_label=Gtk.Label("hola")
381                self.login_box.pack_start(self.tmp_label,False,True,100)
382                '''
383               
384                self.login_box=builder.get_object("login_box")
385                self.login_eb=builder.get_object("login_eventbox")
386                self.login_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK  )
387                self.login_eb.connect("button-press-event",self.login_clicked)
388                self.login_eb.connect("motion-notify-event",self.mouse_over_login)
389                self.login_eb.connect("leave_notify_event",self.mouse_exit_login)
390                self.user_entry=builder.get_object("user_entry")
391                self.user_entry.connect("activate",self.entries_press_event)
392                self.password_entry=builder.get_object("password_entry")
393                self.password_entry.connect("activate",self.entries_press_event)
394                self.login_eb_box=builder.get_object("login_eb_box")
395                self.login_msg_label=builder.get_object("login_msg_label")
396               
397                self.server_ip_entry=builder.get_object("server_ip_entry")
398                self.server_ip_entry.connect("activate",self.entries_press_event)
399               
400                self.button1=builder.get_object("button1")
401                self.button1.grab_focus()
402               
403               
404                self.login_overlay.add_overlay(self.login_box)
405                self.login_overlay.show_all()
406               
407               
408                self.stack.add_titled(self.login_overlay,"login","Login")
409                self.stack.add_titled(self.overlay, "main", "Main")
410                self.stack.add_titled(self.content_box, "mirror", "Mirror")
411                self.stack.add_titled(self.configuration_box,"configuration","Configuration")
412               
413               
414                self.banner_combo=builder.get_object("banner_combobox")
415                self.banner_store=Gtk.ListStore(GdkPixbuf.Pixbuf,str)
416               
417                for x in glob.glob(BANNERS_PATH+"*.png"):
418                        f_name=x.replace(BANNERS_PATH,"").split(".png")[0]
419                        image=Gtk.Image()
420                        image.set_from_file(x)
421                        pixbuf=image.get_pixbuf()
422                        pixbuf=pixbuf.scale_simple(64,64,GdkPixbuf.InterpType.BILINEAR)
423                        self.banner_store.append([pixbuf,f_name])
424                       
425                       
426                self.banner_combobox.set_model(self.banner_store)
427                txt_renderer=Gtk.CellRendererText()
428                pixbuf_renderer=Gtk.CellRendererPixbuf()
429               
430                self.banner_combobox.pack_start(pixbuf_renderer,True)
431                self.banner_combobox.add_attribute(pixbuf_renderer,"pixbuf",0)
432                self.banner_combobox.pack_start(txt_renderer,True)
433                self.banner_combobox.add_attribute(txt_renderer,"text",1)
434               
435               
436                self.window.add(self.stack)
437               
438                self.check_root()
439               
440                self.set_css_info()
441               
442                self.window.show_all()
443                self.ib.hide()
444                self.button1.hide()
445                self.configuration_infobar.hide()
446               
447                self.progress_da.connect("draw",self.draw_progress)
448                self.window.connect("destroy",self.quit)
449               
450                               
451               
452               
453               
454                #self.set_previous_values()
455               
456               
457                GObject.threads_init()
458                Gtk.main()
459               
460        #def start_gui
461       
462       
463        def set_css_info(self):
464               
465                css = """
466               
467                #BLUE_HEADER {
468                        background-image:-gtk-gradient (linear, left top, left bottom, from (#455A64),  to (#455A64));;
469                       
470                }
471               
472                #LIGHT_BLUE_BACKGROUND {
473                        background-image:-gtk-gradient (linear, left top, left bottom, from (#338fef),  to (#338fef));;
474                       
475                }
476               
477                #HEADER_SHADOW {
478                        background-image:-gtk-gradient (linear, left top, left bottom, from (#7b7b7b),  to (#ffffff));;
479               
480                }
481               
482               
483                #WHITE_BACKGROUND {
484                        background-image:-gtk-gradient (linear, left top, left bottom, from (#ffffff),  to (#ffffff));;
485               
486                }
487               
488                #RED_BACKGROUND {
489                        background-image:-gtk-gradient (linear, left top, left bottom, from (#cc0000),  to (#cc0000));;
490               
491                }
492               
493                #ORANGE_BACKGROUND {
494                        background-image:-gtk-gradient (linear, left top, left bottom, from (#ff6600),  to (#ff6600));;
495                }
496               
497                #LIGHT_RED_BACKGROUND {
498                        background-image:-gtk-gradient (linear, left top, left bottom, from (#ff2d2d),  to (#ff2d2d));;
499               
500                }
501               
502                #BUTTON_COLOR {
503                        background-image:-gtk-gradient (linear, left top, left bottom, from (#448AFF),  to (#448AFF));;
504                       
505               
506                }
507               
508                #DISABLED_BUTTON_OVER{
509                        background-image:-gtk-gradient (linear, left top, left bottom, from (#888888),  to (#888888));;
510                }
511               
512                #DISABLED_BUTTON{
513                        background-image:-gtk-gradient (linear, left top, left bottom, from (#666666),  to (#666666));;
514                }
515               
516                #CANCEL_BUTTON{
517                        background-image:-gtk-gradient (linear, left top, left bottom, from (#D32F2F),  to (#D32F2F));;
518                }
519               
520                #CANCEL_BUTTON_OVER{
521                        background-image:-gtk-gradient (linear, left top, left bottom, from (#F44336),  to (#F44336));;
522                }
523               
524                #SECTION_LABEL {
525                        font: Roboto 16;
526                }
527               
528               
529                #BUTTON_OVER_COLOR {
530                        background-image:-gtk-gradient (linear, left top, left bottom, from (#449fff),  to (#449fff));;
531                       
532               
533                }
534               
535                #BUTTON_LABEL{
536                        color:white;
537                        font: Roboto 10;
538                }
539               
540               
541                #WHITE_MIRROR_NAME {
542                        color: white;
543                        font: Roboto Medium 20;
544               
545                }
546               
547                #WHITE_EXTRA_INFO {
548                        color: white;
549                        font: Roboto Light 12;
550               
551                }
552               
553                #BLUE_FONT {
554                        color: #3366cc;
555                        font: Roboto 10;
556                       
557                }
558
559                #LABEL_OPTION{
560               
561                        color: #808080;
562                        font: Roboto 11;
563                }
564               
565                #LOGIN_BUTTON {
566                        background-image:-gtk-gradient (linear, left top, left bottom, from (#448AFF),  to (#448AFF));;
567                        color: #FFFFFF;
568                        font: Roboto 12;
569                }
570               
571                #LOGIN_BUTTON_OVER {
572                        background-image:-gtk-gradient (linear, left top, left bottom, from (#449fff),  to (#449fff));;
573                        color: #FFFFFF;
574                        font: Roboto 12;
575                }
576               
577                #LOGIN_BUTTON_DISABLED {
578                        background-image:-gtk-gradient (linear, left top, left bottom, from (#666666),  to (#666666));;
579                        color: #FFFFFF;
580                        font: Roboto 12;
581                }
582               
583                #LOGIN_BUTTON_DISABLED_OVER {
584                        background-image:-gtk-gradient (linear, left top, left bottom, from (#888888),  to (#888888));;
585                        color: #FFFFFF;
586                        font: Roboto 12;
587                }
588               
589                #ERROR_FONT {
590                        color: #CC0000;
591                        font: Roboto 10;
592                }
593               
594
595                """
596               
597                self.style_provider=Gtk.CssProvider()
598                self.style_provider.load_from_data(css)
599                Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),self.style_provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
600               
601                self.mirror_header_box.set_name("BLUE_HEADER")
602                self.main_header_box.set_name("BLUE_HEADER")
603                self.update_label_box.set_name("BUTTON_COLOR")
604                self.export_label_box.set_name("BUTTON_COLOR")
605                self.save_button_box.set_name("BUTTON_COLOR")
606                self.configuration_header_box.set_name("BLUE_HEADER")
607                self.configuration_label_box.set_name("BUTTON_COLOR")
608               
609                self.mirror_name_label.set_name("WHITE_MIRROR_NAME")
610                self.llx_mirror_label.set_name("WHITE_MIRROR_NAME")
611                self.conf_mirror_name_label.set_name("WHITE_MIRROR_NAME")
612                self.arch_label.set_name("WHITE_EXTRA_INFO")
613                self.shadow_box.set_name("HEADER_SHADOW")
614                self.shadow_box1.set_name("HEADER_SHADOW")
615                self.shadow_box2.set_name("HEADER_SHADOW")
616                self.content_box.set_name("WHITE_BACKGROUND")
617                self.list_box.set_name("WHITE_BACKGROUND")
618                self.configuration_box.set_name("WHITE_BACKGROUND")
619               
620                self.name_label.set_name("LABEL_OPTION")
621                self.banner_label.set_name("LABEL_OPTION")
622                self.origin_label.set_name("LABEL_OPTION")
623                self.distributions_label.set_name("LABEL_OPTION")
624                self.sections_label.set_name("LABEL_OPTION")
625                self.architectures_label.set_name("LABEL_OPTION")
626                self.local_path_label.set_name("LABEL_OPTION")
627                self.check_md5_label.set_name("LABEL_OPTION")
628                self.ign_gpg_label.set_name("LABEL_OPTION")
629                self.ign_release_label.set_name("LABEL_OPTION")
630       
631                self.update_label.set_name("BUTTON_LABEL")
632                self.export_label.set_name("BUTTON_LABEL")
633                self.save_label.set_name("BUTTON_LABEL")
634                self.conf_label.set_name("BUTTON_LABEL")
635               
636                self.url_entry.set_name("BLUE_FONT")
637                self.name_entry.set_name("BLUE_FONT")
638                self.origin_entry.set_name("BLUE_FONT")
639                self.distributions_entry.set_name("BLUE_FONT")
640                self.sections_entry.set_name("BLUE_FONT")
641                self.mirror_path_entry.set_name("BLUE_FONT")
642                self.i386_label.set_name("BLUE_FONT")
643                self.amd64_label.set_name("BLUE_FONT")
644               
645                self.user_entry.set_name("BLUE_FONT")
646                self.password_entry.set_name("BLUE_FONT")
647                self.server_ip_entry.set_name("BLUE_FONT")
648               
649                self.update_header_label.set_name("SECTION_LABEL")
650                self.export_header_label.set_name("SECTION_LABEL")
651               
652                self.internet_rb_label.set_name("LABEL_OPTION")
653                self.local_folder_rb_label.set_name("LABEL_OPTION")
654                self.url_rb_label.set_name("LABEL_OPTION")
655                self.destination_opt_label.set_name("LABEL_OPTION")
656               
657                self.local_folder_label.set_name("BLUE_FONT")
658                self.destination_label.set_name("BLUE_FONT")
659                self.login_eb.set_name("LOGIN_BUTTON")
660                #self.login_eb_box.set_name("HEADER_SHADOW")
661                self.login_msg_label.set_name("ERROR_FONT")
662               
663               
664        #def set_css
665       
666        def set_mirror_info(self,mirror_button):
667
668
669                '''
670                "NAME": "",
671                "BANNER": "",
672                "ORIGS" : {"1":"lliruex.net/xenial","2":"","3":""},
673                "ARCHITECTURES": [ "amd64", "i386"],
674                "SECTIONS": ["main", "main/debian-installer", "universe", "restricted", "multiverse", "partner"],
675                "MIRROR_PATH": "/net/mirror/llx16",
676                "DISTROS": ["xenial","xenial-updates","xenial-security"],
677                "IGN_GPG":1,
678                "IGN_RELEASE":0,
679                "CHK_MD5":0,
680                "CURRENT_UPDATE_OPTION":"1"
681                '''
682
683                self.url_entry.set_text(mirror_button.info["ORIGS"]["3"])
684                if len(mirror_button.info["NAME"]) < 22 :
685                        self.mirror_name_label.set_text(mirror_button.info["NAME"])
686                        self.conf_mirror_name_label.set_text(mirror_button.info["NAME"])
687                        self.mirror_name_label.set_tooltip_text("")
688                        self.conf_mirror_name_label.set_tooltip_text("")
689                else:
690                        self.mirror_name_label.set_text(mirror_button.info["NAME"][0:19]+"...")
691                        self.mirror_name_label.set_tooltip_text(mirror_button.info["NAME"])
692                        self.conf_mirror_name_label.set_tooltip_text(mirror_button.info["NAME"])       
693                        self.conf_mirror_name_label.set_text(mirror_button.info["NAME"][0:19]+"...")
694               
695               
696               
697               
698                self.arch_label.set_text(", ".join(mirror_button.info["ARCHITECTURES"]))
699               
700                self.internet_rb.set_active(True)
701               
702                #if mirror_button.info["CURRENT_UPDATE_OPTION"]=="2":
703                #       self.local_folder_rb.set_active(True)
704                       
705                if mirror_button.info["CURRENT_UPDATE_OPTION"]=="3":
706                        self.url_rb.set_active(True)
707               
708                self.name_entry.set_text(mirror_button.info["NAME"])
709               
710                c=0
711               
712                for i in self.banner_store:
713                        if i[1]==mirror_button.info["BANNER"]:
714                                break
715                        c+=1
716                       
717                self.banner_combobox.set_active(c)
718                       
719                       
720               
721                self.origin_entry.set_text(mirror_button.info["ORIGS"]["1"])
722                self.distributions_entry.set_text(", ".join(mirror_button.info["DISTROS"]))
723                self.sections_entry.set_text(", ".join(mirror_button.info["SECTIONS"]))
724                self.i386_cb.set_active("i386" in mirror_button.info["ARCHITECTURES"])
725                self.amd64_cb.set_active("amd64" in mirror_button.info["ARCHITECTURES"])
726                self.mirror_path_entry.set_text(mirror_button.info["MIRROR_PATH"])
727               
728                self.check_md5_cb.set_active(mirror_button.info["CHK_MD5"]==1)
729                self.ign_gpg_cb.set_active(mirror_button.info["IGN_GPG"]==1)
730                self.ign_release_cb.set_active(mirror_button.info["IGN_RELEASE"]==1)
731               
732                self.progress_label.set_text("")
733               
734                self.current_mirror=mirror_button
735
736               
737               
738               
739                if self.updating_mirror!=None:
740                        if self.current_mirror!=self.updating_mirror and self.updating_mirror.info["updating"]:
741                                self.update_label_box.set_name("DISABLED_BUTTON")
742                                self.update_label.set_text("Update")
743                               
744                        if self.current_mirror!=self.updating_mirror and self.updating_mirror.info["exporting"]:
745                                self.export_label_box.set_name("DISABLED_BUTTON")
746                                self.export_label.set_text("Export")
747                               
748                        if self.current_mirror==self.updating_mirror:
749                               
750                                if self.updating_mirror.info["updating"]:
751                                        self.update_label.set_text("Cancel")
752                                        self.update_label_box.set_name("CANCEL_BUTTON")
753                                       
754                                if self.updating_mirror.info["exporting"]:
755                                        self.export_label.set_text("Cancel")
756                                        self.export_label_box.set_name("CANCEL_BUTTON")
757                                       
758               
759                '''
760                if "2.5" in self.current_mirror.info["ORIGS"]:
761               
762                        if self.current_mirror.info["ORIGS"]["2.5"]!="":
763                                self.folder_fcb.set_filename(self.current_mirror.info["ORIGS"]["2.5"])
764                                self.local_folder_label.set_text(self.current_mirror.info["ORIGS"]["2.5"])
765                        else:
766                                self.folder_fcb.set_filename(os.environ["HOME"])
767                                self.local_folder_label.set_text(os.environ["HOME"])
768                '''             
769               
770               
771                self.destination_fcb.set_filename(os.environ["HOME"])
772                self.destination_label.set_text(os.environ["HOME"])
773               
774               
775               
776                return True
777               
778        #def set_mirror_info
779
780
781        def parse_mirrors(self):
782                '''
783                self.mirrors={}
784               
785                once=True
786               
787                for t in range(0,1):
788               
789                        for m_file in glob.glob(MIRROR_CONF_DIR+"*"):
790                               
791                                f=open(m_file,"r")
792                                data=json.load(f)
793                                f.close()
794                                m=MirrorButton(data)
795
796                                if once:
797                                       
798                                        if m.info["updating"]:
799                                                if once:
800                                                        GLib.timeout_add(5,self.update_mirror_button_animation,m)
801                                                        once=False
802                                                               
803                                else:
804                                               
805                                        m.info["updating"]=False
806                                       
807                                if t == 0:
808                                        self.mirrors[m_file.split("/")[-1]]=m
809                                else:
810                                        self.mirrors[m_file.split("/")[-1]+"%s"%t]=m
811                                self.add_mirror_button(m)
812               
813                return True
814                '''
815               
816                self.mirrors=self.llx_conn.mirror_list()
817               
818                #print self.mirrors["mippa"]
819               
820                mirror_key=self.llx_conn.is_alive()
821               
822                for key in self.mirrors:
823               
824                        m=MirrorButton(self.mirrors[key])
825                        m.info["KEY"]=key
826                        if key==mirror_key["msg"] and mirror_key["status"]:
827                                m.info["executing"]=True
828                                m.info["updating"]=True
829                                self.updating_mirror=m
830                               
831                                GLib.timeout_add(self.update_y_time,self.update_ys)
832                                GLib.timeout_add(self.update_percentage_time,self.update_percentage)
833                                GLib.timeout_add(self.update_degree_time,self.update_degree)
834                               
835                                GLib.timeout_add(self.update_mirror_button_time,self.update_mirror_button_animation,self.updating_mirror)
836                                self.export_label_box.set_name("DISABLED_BUTTON")
837                               
838                               
839                               
840                        self.add_mirror_button(m)
841               
842                return True
843               
844               
845        #def parse_mirrors
846       
847
848        def set_previous_values(self):
849               
850                #self.folder_fcb.set_filename("/home/cless")
851                #self.local_folder_label.set_text("/home/cless")
852               
853                #self.destination_fcb.set_filename("/home/cless")
854                #self.destination_label.set_text("/home/cless")
855               
856                pass
857               
858        #def set_previous_values
859       
860        def set_info_text(self,txt,message_type=Gtk.MessageType.INFO):
861               
862                self.ib.set_message_type(message_type)
863                self.info_label.set_markup(txt)
864                self.ib.show()
865               
866        #def set_info_text
867       
868        def set_conf_text(self,txt,message_type=Gtk.MessageType.INFO):
869               
870                self.configuration_infobar.set_message_type(message_type)
871                self.configuration_panel_label.set_markup(txt)
872                self.configuration_infobar.show()
873               
874        #def set_info_text
875       
876        def show_content(self,widget):
877               
878                self.ib.hide()
879                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
880                self.stack.set_visible_child_name("mirror")
881               
882               
883        #show_content
884       
885        def add_mirror_button(self,mirror_button):
886               
887                #print mirror_button.info
888               
889                da=Gtk.DrawingArea()
890                da.set_size_request(140,148)
891                da.add_events(Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.BUTTON_PRESS_MASK )
892               
893                da.connect("draw",self.draw_button,mirror_button)
894                da.connect("motion-notify-event",self.mouse_over,mirror_button)
895                da.connect("leave_notify_event",self.mouse_left,mirror_button)
896                da.connect("button-press-event",self.mirror_button_clicked,mirror_button)
897               
898                da.size_request()
899               
900                da.show()
901               
902                mirror_button.info["da"]=da
903               
904                self.main_content_box.attach(da,self.current_grid_width,self.current_grid_height,1,1)
905               
906                self.current_grid_width+=1
907               
908                if self.current_grid_width > self.max_grid_width:
909                        self.current_grid_width=0
910                        self.current_grid_height+=1
911                       
912        #def add_mirror_button
913       
914
915        def add_clicked(self,widget,event):
916               
917                print "add clicked"
918               
919                self.add_flag=True
920       
921                info={}
922               
923                info["NAME"]=""
924                info["ARCHITECTURES"]=""
925                info["CURRENT_UPDATE_OPTION"]=""
926                info["BANNER"]=""
927                info["DISTROS"]=""
928                info["SECTIONS"]=""
929                info["MIRROR_PATH"]=""
930                info["ORIGS"]={}
931                info["ORIGS"]["1"]=""
932                info["ORIGS"]["2"]=""
933                info["ORIGS"]["3"]=""
934                info["CHK_MD5"]=""
935                info["IGN_GPG"]=""
936                info["IGN_RELEASE"]=""
937               
938               
939                mirror=MirrorButton(info)
940                mirror.info["updating"]=False
941               
942                self.set_mirror_info(mirror)
943                self.banner_combobox.set_active(0)
944                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
945                self.stack.set_visible_child_name("configuration")
946               
947               
948               
949        #def add_clicked
950       
951        def add_mouse_over(self,widget,event,i):
952               
953                i.set_from_file(ADD_IMAGE_OVER)
954               
955        #def add_mouse_over
956       
957       
958        def add_mouse_left(self,widget,event,i):
959               
960                i.set_from_file(ADD_IMAGE)
961               
962        #def add_mouse_over
963       
964        def entries_press_event(self,widget):
965               
966               
967               
968                self.login_clicked(None,None)
969
970        def ib_response(self,widget,response):
971
972                widget.hide()
973               
974        #
975       
976        def folder_fcb_changed(self,widget):
977               
978               
979                self.local_folder_label.set_text(self.folder_fcb.get_filename())
980               
981        #def
982       
983        def destination_fcb_changed(self,widget):
984               
985               
986                self.destination_label.set_text(self.destination_fcb.get_filename())
987               
988        #def
989       
990       
991        def configuration_arrow_clicked(self,widget,event):
992               
993                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_RIGHT)
994                if self.add_flag:
995                        self.stack.set_visible_child_name("main")
996                        self.add_flag=False
997                        return True
998               
999                self.ib.hide()                 
1000                self.stack.set_visible_child_name("mirror")
1001               
1002               
1003        #def arrow_clicked
1004       
1005       
1006        def arrow_clicked(self,widget,event):
1007               
1008                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_RIGHT)
1009                self.stack.set_visible_child_name("main")
1010               
1011               
1012               
1013        #def arrow_clicked
1014
1015       
1016        def mouse_over_update(self,widget,event):
1017               
1018               
1019                if self.updating_mirror!=None and self.updating_mirror.info["updating"]:
1020                       
1021                        if self.updating_mirror==self.current_mirror:
1022                                self.update_label_box.set_name("CANCEL_BUTTON_OVER")
1023                                return True
1024                               
1025                        self.update_label_box.set_name("DISABLED_BUTTON_OVER")
1026                        return True
1027                       
1028               
1029                if self.updating_mirror!=None and self.updating_mirror.info["exporting"]:
1030                       
1031                        self.update_label_box.set_name("DISABLED_BUTTON_OVER")
1032                        return True
1033               
1034                       
1035                self.update_label_box.set_name("BUTTON_OVER_COLOR")
1036               
1037        #def mouse_over_event
1038       
1039        def mouse_exit_update(self,widget,event):
1040               
1041               
1042                if self.updating_mirror!=None and self.updating_mirror.info["updating"]:
1043                       
1044                        if self.updating_mirror==self.current_mirror:
1045                                self.update_label_box.set_name("CANCEL_BUTTON")
1046                                return True
1047                               
1048                        self.update_label_box.set_name("DISABLED_BUTTON")
1049                        return True
1050                       
1051               
1052                if self.updating_mirror!=None and self.updating_mirror.info["exporting"]:
1053                       
1054                        self.update_label_box.set_name("DISABLED_BUTTON")
1055                        return True
1056               
1057                       
1058                self.update_label_box.set_name("BUTTON_COLOR")
1059               
1060               
1061        #def mouse left_update
1062       
1063        def update_clicked(self,widget,event):
1064               
1065                print "Update clicked"
1066       
1067                mode="1"
1068                data=None
1069       
1070                self.current_mirror.info["cancelled"]=False
1071               
1072                if self.updating_mirror!=None and self.updating_mirror!=self.current_mirror:
1073                        if self.updating_mirror.info["executing"]:
1074                                self.set_info_text("'%s' is currently %s."%(self.updating_mirror.info["NAME"], 'updating' if self.updating_mirror.info["updating"] else 'exporting'),Gtk.MessageType.ERROR)
1075                                return False
1076               
1077                if self.current_mirror.info["exporting"]:
1078                        self.set_info_text("'%s' is currently exporting."%self.updating_mirror.info["NAME"],Gtk.MessageType.ERROR)
1079                        return False
1080               
1081                if self.internet_rb.get_active():
1082                        print "INTERNET"
1083               
1084                if self.local_folder_rb.get_active():
1085                        print "LOCAL_FOLDER: %s"%self.folder_fcb.get_filename()
1086                        mode="2"
1087                        data=self.folder_fcb.get_filename()
1088                        self.current_mirror.info["ORIGS"]["2"]=data
1089                       
1090                       
1091                if self.url_rb.get_active():
1092                        print "URL: %s"%self.url_entry.get_text()
1093                        mode="3"
1094                        data=self.url_entry.get_text()
1095                        self.current_mirror.info["ORIGS"]["3"]=data
1096               
1097                self.current_mirror.info["CURRENT_UPDATE_OPTION"]=mode
1098               
1099                if not self.current_mirror.info["executing"]:
1100                       
1101                        self.percentage=0
1102                        self.progress_label.set_text("")
1103                        GLib.idle_add(self.ib.hide)
1104                        self.updating_mirror=self.current_mirror
1105                        self.current_mirror.info["updating"]=True
1106                        self.current_mirror.info["executing"]=True
1107                        self.current_mirror.info["cancelled"]=False
1108                        GLib.timeout_add(self.update_y_time,self.update_ys)
1109                        GLib.timeout_add(self.update_percentage_time,self.update_percentage)
1110                        GLib.timeout_add(self.update_degree_time,self.update_degree)
1111                       
1112                        self.llx_conn.update(self.current_mirror.info["KEY"],mode,data)
1113                       
1114                        GLib.timeout_add(self.update_mirror_button_time,self.update_mirror_button_animation,self.updating_mirror)
1115                        self.update_label.set_text("Cancel")
1116                        self.update_label_box.set_name("CANCEL_BUTTON_OVER")
1117                        self.export_label_box.set_name("DISABLED_BUTTON")
1118                       
1119                else:
1120                       
1121                        self.llx_conn.stop_update()
1122                       
1123                        self.updating_mirror.info["updating"]=False
1124                        self.updating_mirror.info["executing"]=False
1125                        self.updating_mirror.info["cancelled"]=True
1126                        self.update_label.set_text("Update")
1127                        self.update_label_box.set_name("BUTTON_COLOR")
1128                        self.export_label_box.set_name("BUTTON_COLOR")
1129
1130        #def update_clicked
1131
1132       
1133        def mouse_over_export(self,widget,event):
1134               
1135               
1136                if self.updating_mirror!=None and self.updating_mirror.info["exporting"]:
1137                       
1138                        if self.updating_mirror==self.current_mirror:
1139                                self.export_label_box.set_name("CANCEL_BUTTON_OVER")
1140                                return True
1141                               
1142                        self.export_label_box.set_name("DISABLED_BUTTON_OVER")
1143                        return True
1144                       
1145               
1146                if self.updating_mirror!=None and self.updating_mirror.info["updating"]:
1147                       
1148                        self.export_label_box.set_name("DISABLED_BUTTON_OVER")
1149                        return True
1150               
1151                self.export_label_box.set_name("BUTTON_OVER_COLOR")
1152               
1153        #def mouse_over_event
1154       
1155        def mouse_exit_export(self,widget,event):
1156               
1157                if self.updating_mirror!=None and self.updating_mirror.info["exporting"]:
1158                       
1159                        if self.updating_mirror==self.current_mirror:
1160                                self.export_label_box.set_name("CANCEL_BUTTON")
1161                                return True
1162                               
1163                        self.export_label_box.set_name("DISABLED_BUTTON")
1164                        return True
1165                       
1166               
1167                if self.updating_mirror!=None and self.updating_mirror.info["updating"]:
1168                       
1169                        self.export_label_box.set_name("DISABLED_BUTTON")
1170                        return True
1171               
1172                self.export_label_box.set_name("BUTTON_COLOR")
1173               
1174        #def mouse left_update
1175       
1176        def export_clicked(self,widget,event):
1177               
1178                print "Export clicked: %s"%self.destination_fcb.get_filename()
1179               
1180               
1181                if self.updating_mirror!=None and self.updating_mirror!=self.current_mirror:
1182                        if self.updating_mirror.info["executing"]:
1183                                self.set_info_text("'%s' is currently %s."%(self.updating_mirror.info["NAME"], 'updating' if self.updating_mirror.info["updating"] else 'exporting'),Gtk.MessageType.ERROR)
1184                                return False
1185               
1186
1187                if self.current_mirror.info["updating"]:
1188                        self.set_info_text("'%s' is currently updating."%self.updating_mirror.info["NAME"],Gtk.MessageType.ERROR)
1189                        return False
1190
1191                if not self.current_mirror.info["exporting"]:
1192                       
1193                        self.percentage=0
1194                        self.updating_mirror=self.current_mirror
1195                        self.updating_mirror.info["exporting"]=True
1196                        self.updating_mirror.info["executing"]=True
1197                        self.updating_mirror.info["cancelled"]=False
1198                        GLib.timeout_add(self.update_y_time,self.update_ys)
1199                        GLib.timeout_add(self.update_percentage_time,self.update_percentage)
1200                        GLib.timeout_add(self.update_degree_time,self.update_degree)
1201                       
1202                        self.llx_conn.export(self.updating_mirror.info["KEY"],self.destination_fcb.get_filename())
1203                       
1204                        GLib.timeout_add(self.update_mirror_button_time,self.update_mirror_button_animation,self.updating_mirror)
1205                       
1206                       
1207
1208                        self.export_label.set_text("Cancel")
1209                        self.export_label_box.set_name("CANCEL_BUTTON_OVER")
1210                       
1211                        self.update_label_box.set_name("DISABLED_BUTTON")
1212
1213                       
1214                else:
1215                       
1216                        self.updating_mirror.info["exporting"]=False
1217                        self.updating_mirror.info["executing"]=False
1218                        self.updating_mirror.info["cancelled"]=True
1219                        self.export_label.set_text("Export")
1220                        self.update_label_box.set_name("BUTTON_COLOR")
1221                        self.export_label_box.set_name("BUTTON_COLOR")
1222               
1223               
1224               
1225               
1226               
1227               
1228        #def update_clicked
1229               
1230
1231        def mouse_over_conf(self,widget,event):
1232               
1233                self.configuration_label_box.set_name("BUTTON_OVER_COLOR")
1234               
1235        #def mouse_over_event
1236       
1237        def mouse_exit_conf(self,widget,event):
1238               
1239                self.configuration_label_box.set_name("BUTTON_COLOR")
1240               
1241        #def mouse left_update
1242       
1243        def conf_clicked(self,widget,event):
1244               
1245                print "Configuration clicked"
1246                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
1247                self.stack.set_visible_child_name("configuration")
1248               
1249        #def update_clicked
1250
1251        def mirror_button_clicked(self,widget,event,mirror_button):
1252               
1253                self.set_mirror_info(mirror_button)
1254                self.show_content(None)
1255               
1256        #def button_clicked
1257       
1258        def mouse_over_save(self,widget,event):
1259               
1260                self.save_button_box.set_name("BUTTON_OVER_COLOR")
1261               
1262        #def mouse_over_event
1263       
1264        def mouse_exit_save(self,widget,event):
1265               
1266                self.save_button_box.set_name("BUTTON_COLOR")
1267               
1268        #def mouse left_update
1269       
1270       
1271        def save_button_clicked(self,widget,event):
1272               
1273                self.current_mirror.info["NAME"]=self.name_entry.get_text()
1274               
1275                self.current_mirror.info["BANNER"]=self.banner_store[self.banner_combobox.get_active()][1]
1276               
1277                # internal info based on banner name
1278                if os.path.exists(BANNERS_PATH+self.current_mirror.info["BANNER"]+".png"):
1279                        self.current_mirror.info["image"]=BANNERS_PATH+self.current_mirror.info["BANNER"]+".png"
1280                else:
1281                        self.current_mirror.info["image"]=UNKNOWN_BANNER
1282                       
1283                if "img" in self.current_mirror.info:
1284                        self.current_mirror.info.pop("img")
1285               
1286                #
1287               
1288               
1289               
1290                self.label_image.queue_draw()
1291                self.label_image1.queue_draw()
1292               
1293               
1294                self.current_mirror.info["ORIGS"]["1"]=self.origin_entry.get_text()
1295               
1296                self.current_mirror.info["DISTROS"]=[]
1297                for item in self.distributions_entry.get_text().split(","):
1298                       
1299                        item=item.lstrip(" ").rstrip(" ")
1300                        self.current_mirror.info["DISTROS"].append(item)
1301               
1302                self.current_mirror.info["SECTIONS"]=[]
1303                for item in self.sections_entry.get_text().split(","):
1304                       
1305                        item=item.lstrip(" ").rstrip(" ")
1306                        self.current_mirror.info["SECTIONS"].append(item)
1307                       
1308                self.current_mirror.info["ARCHITECTURES"]=[]
1309                if self.i386_cb.get_active():
1310                        self.current_mirror.info["ARCHITECTURES"].append("i386")
1311                if self.amd64_cb.get_active():
1312                        self.current_mirror.info["ARCHITECTURES"].append("amd64")
1313               
1314                self.current_mirror.info["MIRROR_PATH"]=self.mirror_path_entry.get_text()
1315               
1316                self.current_mirror.info["IGN_GPG"]=0
1317                if self.ign_gpg_cb.get_active():
1318                        self.current_mirror.info["IGN_GPG"]=1
1319               
1320                self.current_mirror.info["IGN_RELEASE"]=0
1321                if self.ign_release_cb.get_active():
1322                        self.current_mirror.info["IGN_RELEASE"]=1
1323               
1324                self.current_mirror.info["CHK_MD5"]=0
1325                if self.check_md5_cb.get_active():
1326                        self.current_mirror.info["CHK_MD5"]=1
1327
1328                self.set_mirror_info(self.current_mirror)
1329               
1330                if self.add_flag:
1331                       
1332                        self.mirrors[str(random.random())]=self.current_mirror
1333                        self.add_mirror_button(self.current_mirror)
1334                        self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_RIGHT)
1335                        self.ib.hide()
1336                        self.stack.set_visible_child_name("mirror")
1337                       
1338                        self.add_flag=False
1339                       
1340                        try:
1341                                key=self.llx_conn.create_config(self.current_mirror.info)
1342                                self.current_mirror.info["KEY"]=key
1343                                self.set_conf_text("Configuration Saved",INFO)
1344                        except Exception as e:
1345                                self.set_conf_text("Could not save configuration [%s]"%e,ERROR)
1346               
1347                else:
1348                        try:
1349                                self.llx_conn.save_config(self.current_mirror.info["KEY"],self.current_mirror.info)
1350                                self.configuration_infobar.hide()
1351                                self.set_conf_text("Configuration Saved",INFO)
1352                        except Exception as e:
1353                                self.set_conf_text("Could not save configuration [%s]"%e,ERROR)
1354               
1355        #def save_button_clicked
1356
1357       
1358        def mouse_over_login(self,widget,event):
1359               
1360                if self.login_enabled:
1361               
1362                        self.login_eb.set_name("LOGIN_BUTTON_OVER")
1363                       
1364                else:
1365                       
1366                        self.login_eb.set_name("LOGIN_BUTTON_DISABLED")
1367               
1368        #def mouse_over_login
1369       
1370        def mouse_exit_login(self,widget,event):
1371               
1372                if self.login_enabled:
1373               
1374                        self.login_eb.set_name("LOGIN_BUTTON")
1375                else:
1376                       
1377                        self.login_eb.set_name("LOGIN_BUTTON_DISABLED")
1378               
1379        #def mouse_over_login
1380
1381        def validate_user(self):
1382               
1383                GLib.idle_add(self.validate_thread)
1384               
1385        #validate_user
1386       
1387        def validate_thread(self):
1388               
1389                print self.server_ip
1390               
1391                c=xmlrpclib.ServerProxy("https://"+self.server_ip+":9779")
1392                self.ret=None
1393
1394                try:
1395                        self.ret=c.validate_user(self.user,self.password)
1396                except Exception as e:
1397                        self.ret=[False,str(e)]
1398                        GLib.idle_add(self.set_login_msg,str(e))
1399                        GLib.idle_add(self.login_form_sensitive)
1400                        return
1401
1402               
1403                if self.ret[0]:
1404                        GLib.timeout_add(10,self.update_login_animation)
1405                        GLib.idle_add(self.set_login_msg,"")
1406                else:
1407                        GLib.idle_add(self.set_login_msg,"Wrong user and/or password")
1408                        GLib.idle_add(self.login_form_sensitive)
1409                       
1410               
1411        #def validate_thread
1412
1413        def set_login_msg(self,msg):
1414               
1415                self.login_msg_label.set_text(msg)
1416               
1417        #def set_login_msg
1418       
1419       
1420        def login_form_sensitive(self,state=None):
1421               
1422                if state==None:
1423                        state=not self.login_enabled
1424               
1425                self.login_enabled=state
1426               
1427                self.user_entry.set_sensitive(state)
1428                self.password_entry.set_sensitive(state)
1429                self.server_ip_entry.set_sensitive(state)
1430               
1431                if state:
1432                        self.login_eb.set_name("LOGIN_BUTTON")
1433                else:
1434                        self.login_eb.set_name("LOGIN_BUTTON_DISABLED")
1435               
1436               
1437        #def login_form_sensible
1438       
1439
1440        def login_clicked(self,widget,event):
1441               
1442               
1443                if self.login_enabled:
1444               
1445                       
1446                        self.user=self.user_entry.get_text()
1447                        self.password=self.password_entry.get_text()
1448                        self.server_ip=self.server_ip_entry.get_text()
1449                       
1450                        if self.server_ip=="":
1451                                #self.server_ip="server"
1452                                self.server_ip="localhost"
1453                               
1454                        if self.user=="":       
1455                                self.user="lliurex"
1456                        if self.password=="":
1457                                self.password="lliurex"
1458                       
1459                        self.login_animation_r=60
1460                        self.login_form_sensitive()
1461                       
1462                       
1463                       
1464                        self.t=threading.Thread(target=self.validate_thread)
1465                        self.t.daemon=True
1466                        self.t.start()
1467                       
1468                       
1469                       
1470               
1471               
1472        #def login_clicked
1473       
1474        def update_login_animation(self):
1475               
1476                #print "update_login_animation"
1477               
1478                self.login_animation_r+=8
1479               
1480                if self.login_animation_r<650:
1481                        self.login_da.queue_draw()
1482                        return True
1483                else:
1484                        #return False
1485                        self.stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
1486                        self.stack.set_visible_child_name("main")
1487                        self.llx_conn=lliurex_mirror_connect.LliurexMirrorN4d(self.server_ip,(self.user,self.password))
1488                        self.parse_mirrors()
1489                       
1490        def update_mirror_button_animation(self,mirror_button):
1491               
1492                #print "update_button_animation"
1493               
1494                if self.stack.get_visible_child_name()!="main":
1495                        return True
1496               
1497                mirror_button.info["degree_offset"]+=1
1498               
1499                if self.updating_mirror.info["executing"]:
1500                        if self.stack.get_visible_child_name()=="main":
1501                                mirror_button.info["da"].queue_draw()
1502                        return True
1503               
1504        #def update_mirror_animation
1505       
1506                       
1507               
1508
1509
1510        def update_ys(self):
1511               
1512               
1513               
1514               
1515               
1516                self.wave_xoffset-=1
1517                self.wave_xoffset2+=2
1518                self.wave_xoffset3+=1
1519               
1520                if self.stack.get_visible_child_name()=="mirror":
1521                        self.progress_da.queue_draw()
1522
1523                if self.updating_mirror.info["executing"]:
1524               
1525                        return True
1526                       
1527
1528               
1529               
1530               
1531        #def update_ys
1532
1533               
1534        def update_percentage(self):
1535               
1536                print "Update %"
1537               
1538                ret={}
1539                ret["status"]=False
1540               
1541                if self.updating_mirror.info["updating"]:
1542                        ret=self.llx_conn.is_alive()
1543                        self.percentage=self.llx_conn.get_percentage(self.updating_mirror.info["KEY"])
1544                if self.updating_mirror.info["exporting"]:
1545                        print "exporting updat percentagee"
1546                        ret=self.llx_conn.is_alive_export()
1547                        print ret
1548                        self.percentage=self.llx_conn.get_percentage_export()
1549                        print self.percentage
1550               
1551               
1552               
1553                self.progress_label.set_text(str(self.percentage) + "%")
1554               
1555               
1556                '''
1557               
1558                if self.percentage>=100:
1559                                       
1560                        self.updating_mirror.info["executing"]=False
1561                        self.updating_mirror.info["updating"]=False
1562                        self.updating_mirror.info["exporting"]=False
1563                        self.export_label_box.set_name("BUTTON_COLOR")
1564                        self.update_label_box.set_name("BUTTON_COLOR")
1565                                       
1566                        self.update_label.set_text("Update")
1567                        self.export_label.set_text("Export")
1568
1569                '''
1570
1571                if ret["status"]:
1572                        return True
1573                else:
1574                       
1575                        self.updating_mirror.info["executing"]=False
1576                        self.updating_mirror.info["updating"]=False
1577                        self.updating_mirror.info["exporting"]=False
1578                        self.export_label_box.set_name("BUTTON_COLOR")
1579                        self.update_label_box.set_name("BUTTON_COLOR")
1580                                               
1581                        self.update_label.set_text("Update")
1582                        self.export_label.set_text("Export")
1583
1584
1585                        if not self.updating_mirror.info["cancelled"]:
1586                                ret=self.llx_conn.get_status(self.updating_mirror.info["KEY"])
1587                                if ret["status"]:
1588                                        pass
1589                                else:
1590                                        error="Error:\n"
1591                                        print ret["msg"],len(ret["msg"])
1592                                        error+=ret["msg"].lstrip().rstrip()
1593                                        self.set_info_text(error,Gtk.MessageType.ERROR)
1594                                               
1595                                        self.updating_mirror.info["executing"]=False
1596                                        self.updating_mirror.info["updating"]=False
1597                                        self.updating_mirror.info["exporting"]=False
1598                                        self.updating_mirror.info["cancelled"]=True
1599                                        self.export_label_box.set_name("BUTTON_COLOR")
1600                                        self.update_label_box.set_name("BUTTON_COLOR")
1601                                        self.update_label.set_text("Update")
1602                                        self.export_label.set_text("Export")
1603
1604               
1605        #def update_percentage
1606
1607               
1608        def update_degree(self):
1609               
1610                #print "update degree"
1611               
1612                self.degree_offset+=1
1613               
1614                if self.degree_offset==360:
1615                        self.dregree_offset=0
1616               
1617                if self.updating_mirror.info["executing"]:
1618                        if self.stack.get_visible_child_name()=="mirror":
1619                                self.updating_mirror.info["da"].queue_draw()
1620                       
1621                        return True
1622               
1623        #def update_degree
1624       
1625
1626        def draw_label(self,widget,ctx):
1627               
1628                if self.stack.get_visible_child_name()=="main" :
1629                        return
1630               
1631                ctx.move_to(0,0)
1632                if "img" not in self.current_mirror.info:
1633                        self.current_mirror.info["img"]=cairo.ImageSurface.create_from_png(self.current_mirror.info["image"])
1634                ctx.set_source_surface(self.current_mirror.info["img"],(140-116)/-2,(140-116)/-2)
1635                ctx.paint()
1636               
1637                ctx.set_source_rgba(69/255.0,90/255.0,100/255.0,1)
1638                ctx.rectangle(0,0,116,116)
1639                ctx.arc_negative(self.circle["x"],self.circle["y"],self.circle["radius"]*0.9,self.to_rad(360),self.to_rad(0))
1640                ctx.set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
1641                ctx.fill()
1642               
1643                ctx.set_fill_rule(cairo.FILL_RULE_WINDING)
1644                ctx.set_source_rgba(1,1,1,1)
1645                ctx.set_line_width(1)
1646                ctx.arc(self.circle["x"],self.circle["y"],self.circle["radius"]*0.9,self.to_rad(0),self.to_rad(360))
1647                ctx.stroke()
1648               
1649        #def draw
1650
1651       
1652        def draw_progress(self,widget,ctx):
1653
1654                if self.stack.get_visible_child_name()!="mirror":
1655                        return
1656
1657                if self.current_mirror==self.updating_mirror and self.updating_mirror.info["executing"]:
1658                        percentage=self.percentage
1659                else:
1660                        percentage=110
1661
1662                ctx.set_source_rgba(1,1,1,1)
1663                ctx.rectangle(0,0,self.frame_size,self.frame_size)
1664                ctx.fill()
1665               
1666                ctx.move_to(0,self.frame_size)
1667
1668               
1669               
1670                ctx.set_source_rgba(self.update_water_colors[0].r,self.update_water_colors[0].g,self.update_water_colors[0].b,1)
1671                self.wave_yoffset=self.frame_size-(self.frame_size - (self.circle["radius"]*2))/2 - 7  - self.circle["radius"]*2*percentage/100
1672               
1673               
1674                first=True
1675                for x in range(0,self.frame_size + 1):
1676                       
1677                        y=self.get_wave_y(x,2)
1678                        if y>self.frame_size:
1679                                y=self.frame_size
1680                        if first:
1681                                fy=y
1682                                first=False
1683                        ctx.line_to(x,y)
1684               
1685                ctx.line_to(x,self.frame_size)
1686                ctx.line_to(0,self.frame_size)
1687                ctx.fill()
1688               
1689                               
1690                ctx.set_source_rgba(self.update_water_colors[1].r,self.update_water_colors[1].g,self.update_water_colors[1].b,1)
1691                self.wave_yoffset=self.frame_size-(self.frame_size - (self.circle["radius"]*2))/2 - 5  - self.circle["radius"]*2*percentage/100
1692               
1693                first=True
1694                for x in range(0,self.frame_size + 1):
1695                       
1696                        y=self.get_wave_y(x,1)
1697                        if y>self.frame_size:
1698                                y=self.frame_size
1699                        if first:
1700                                fy=y
1701                                first=False
1702                        ctx.line_to(x,y)
1703               
1704                ctx.line_to(x,self.frame_size)
1705                ctx.line_to(0,self.frame_size)
1706                ctx.fill()
1707               
1708                               
1709                ctx.set_source_rgba(self.update_water_colors[2].r,self.update_water_colors[2].g,self.update_water_colors[2].b,1)
1710                self.wave_yoffset=self.frame_size- (self.frame_size - (self.circle["radius"]*2))/2  - 2  - self.circle["radius"]*2*percentage/100
1711               
1712                first=True
1713               
1714                ys=[]           
1715                for x in range(0,self.frame_size + 1):
1716                       
1717                        y=self.get_wave_y(x)
1718                        ys.append(y)
1719                        if y>self.frame_size:
1720                                y=self.frame_size
1721                       
1722                        if first:
1723                                fy=y
1724                                first=False
1725                               
1726                       
1727                        ctx.line_to(x,y)
1728               
1729                ctx.line_to(x,self.frame_size)
1730                ctx.line_to(0,self.frame_size)
1731                ctx.fill()
1732               
1733               
1734               
1735                r2 = cairo.RadialGradient(0, 40, 1,0, 50, 100)
1736                r2.add_color_stop_rgb(0,self.update_water_colors[3].r,self.update_water_colors[3].g,self.update_water_colors[3].b)
1737                r2.add_color_stop_rgb(1, self.update_water_colors[4].r,self.update_water_colors[4].g,self.update_water_colors[4].b)
1738                ctx.set_source(r2)
1739                self.wave_yoffset=self.frame_size -  (self.frame_size - (self.circle["radius"]*2))/2   - self.circle["radius"]*2*percentage/100
1740               
1741                first=True
1742               
1743                for x in range(0,self.frame_size + 1):
1744                       
1745                        y=ys[x]+3
1746                       
1747                        if y>self.frame_size:
1748                                y=self.frame_size
1749                       
1750                        if first:
1751                                fy=y
1752                                first=False
1753                               
1754                       
1755                        ctx.line_to(x,y)
1756               
1757                ctx.line_to(x,self.frame_size)
1758                ctx.line_to(0,self.frame_size)
1759                ctx.fill()
1760               
1761                ctx.set_source_rgba(69/255.0,90/255.0,100/255.0,1)
1762                ctx.rectangle(0,0,self.frame_size,self.frame_size)
1763                ctx.arc_negative(self.circle["x"],self.circle["y"],self.circle["radius"],self.to_rad(360),self.to_rad(0))
1764                ctx.set_fill_rule(cairo.FILL_RULE_EVEN_ODD)
1765                ctx.fill()
1766               
1767                ctx.set_fill_rule(cairo.FILL_RULE_WINDING)
1768                ctx.set_source_rgba(52/255.0,52/255.0,52/255.0,1)
1769                ctx.set_line_width(2)
1770                ctx.arc(self.circle["x"],self.circle["y"],self.circle["radius"],self.to_rad(0),self.to_rad(360))
1771                ctx.stroke()
1772               
1773                ctx.set_line_width(2)
1774                ctx.set_source_rgba(1,1,1,1)
1775                if self.current_mirror.info["cancelled"]:
1776                        ctx.set_source_rgba(1,0,0,1)
1777                ctx.arc(self.circle["x"],self.circle["y"],self.circle["radius"]+1,self.to_rad(0+self.degree_offset),self.to_rad(percentage*360/100+self.degree_offset))
1778                ctx.stroke()
1779               
1780        #
1781
1782        def draw_login(self,widget,ctx):
1783               
1784               
1785               
1786               
1787                ctx.move_to(0,0)
1788                ctx.set_source_rgba(1,1,1,1)
1789                ctx.rectangle(0,0,600,1000)
1790                ctx.fill()
1791               
1792               
1793                '''
1794                ctx.set_source_rgba(0.4,0.4,1,1)
1795                ctx.arc(300,150,50,self.to_rad(0),self.to_rad(360))
1796                ctx.fill()
1797                '''
1798               
1799               
1800               
1801                #ctx.set_source_rgba(0,0,0,0.1)
1802               
1803       
1804               
1805                ctx.set_source_rgba(69/255.0,90/255.0,100/255.0,1)
1806               
1807               
1808                ctx.arc(self.login_animation_x,self.login_animation_y,self.login_animation_r,self.to_rad(0),self.to_rad(360))
1809                ctx.fill()
1810               
1811                               
1812                '''
1813                ctx.arc(self.login_animation_x,self.login_animation_y,self.login_animation_r,self.to_rad(0),self.to_rad(360))
1814                x,y=ctx.get_current_point()
1815
1816                r2 = cairo.RadialGradient(x, y, self.login_animation_r/2,x, y, self.login_animation_r)
1817                r2.add_color_stop_rgba(0, 1,1,0,1)
1818                r2.add_color_stop_rgba(1, 0, 0, ,1)
1819                ctx.set_line_width(8)
1820                ctx.set_source(r2)
1821                       
1822                ctx.stroke()
1823                '''
1824               
1825               
1826        #def draw_login
1827
1828
1829        def draw_button(self,widget,ctx,mirror_button):
1830               
1831                if self.stack.get_visible_child_name()!="main":
1832                        return 
1833               
1834                ctx.move_to(0,0)
1835                img=cairo.ImageSurface.create_from_png(SHADOW_BANNER)
1836                ctx.set_source_surface(img,0,mirror_button.info["shadow_start"])
1837                ctx.paint_with_alpha(mirror_button.info["shadow_alpha"])
1838               
1839                ctx.move_to(0,0)
1840                img=cairo.ImageSurface.create_from_png(mirror_button.info["image"])
1841                ctx.set_source_surface(img,0,0)
1842                ctx.paint()
1843               
1844                ctx.move_to(0,0)
1845                ctx.set_source_rgba(1,1,1,1)
1846                ctx.rectangle(0,110,140,30)
1847                ctx.fill()
1848               
1849                ctx.set_source_rgba(self.dark_gray.r,self.dark_gray.g,self.dark_gray.b,1)
1850               
1851                pctx = PangoCairo.create_layout(ctx)
1852               
1853                desc = Pango.font_description_from_string ("Roboto 9")
1854                pctx.set_font_description(desc)
1855                pctx.set_markup(mirror_button.info["NAME"])
1856                width=pctx.get_pixel_size()[0]
1857               
1858                if width > 130:
1859                        pctx.set_markup(mirror_button.info["NAME"][0:22]+"...")
1860                       
1861                       
1862               
1863                ctx.move_to(5,118)
1864                PangoCairo.show_layout(ctx, pctx)
1865               
1866               
1867               
1868               
1869                if mirror_button.info["executing"]:
1870                       
1871                        ctx.move_to(0,0)
1872                        ctx.set_source_rgba(0,0,0,0.5)
1873                        ctx.rectangle(0,0,140,110)
1874                        ctx.fill()
1875                       
1876                        ctx.arc(70,70-15,40,self.to_rad(0+mirror_button.info["degree_offset"]),self.to_rad(180+mirror_button.info["degree_offset"]))
1877                        x,y=ctx.get_current_point()
1878
1879                        r2 = cairo.RadialGradient(x, y, 10,x, y, 60)
1880                        r2.add_color_stop_rgba(0, 1,1,1,1)
1881                        r2.add_color_stop_rgba(1, 68/255.0, 159/255.0, 255/255.0,0)
1882                        ctx.set_line_width(8)
1883                        ctx.set_source(r2)
1884                       
1885                        ctx.stroke()
1886                       
1887                        ctx.set_line_width(1)
1888                       
1889                        ctx.set_source_rgba(1,1,1,1)
1890                        ctx.arc(x,y,4,self.to_rad(0),self.to_rad(360))
1891                        ctx.fill()
1892                       
1893                        if int(random.random()*100) > 35:
1894       
1895                                if len(mirror_button.info["random_lights"]) < mirror_button.info["max_random_lights"]:
1896                                       
1897                                        offset=int(random.random()*12)
1898                                       
1899                                        if offset > 6:
1900                                               
1901                                                offset=offset/-2
1902                                       
1903                                        mirror_button.info["random_lights"].append(LightPoint(x+offset,y,random.random()*2))
1904
1905                               
1906                        for i in range(len(mirror_button.info["random_lights"])-1,-1,-1):
1907                               
1908                                mirror_button.info["random_lights"][i].opacity-=0.02
1909                                if mirror_button.info["random_lights"][i].opacity <=0.0:
1910                                        mirror_button.info["random_lights"].pop(i)
1911                                        continue
1912                               
1913                                #ctx.set_source_rgba(1,1,1,mirror_button.info["random_lights"][i].opacity)
1914                                ctx.set_source_rgba(random.random(),1,1,mirror_button.info["random_lights"][i].opacity)
1915                                ctx.arc(mirror_button.info["random_lights"][i].x,mirror_button.info["random_lights"][i].y,mirror_button.info["random_lights"][i].radius,self.to_rad(0),self.to_rad(360))
1916                                #ctx.arc(mirror_button.info["random_lights"][i].x,mirror_button.info["random_lights"][i].y,random.random()*3,self.to_rad(0),self.to_rad(360))
1917                                ctx.fill()
1918       
1919        #def draw_button
1920
1921       
1922        def mouse_over(self,widget,event,mirror_button):
1923               
1924                #print mirror_button.info
1925                mirror_button.info["animation_active"]=False
1926                if mirror_button.info["shadow_alpha"] <0.3 :
1927                        mirror_button.info["shadow_alpha"]+=0.1
1928                        widget.queue_draw()
1929                        return True
1930                       
1931                return False
1932               
1933        #def mouse_over
1934
1935       
1936        def mouse_left(self,widget,event,mirror_button):
1937               
1938                if not mirror_button.info["animation_active"]:
1939                       
1940                        mirror_button.info["animation_active"]=True
1941                        GLib.timeout_add(10,self.restore_shadow_alpha,mirror_button,widget)
1942                       
1943        #def mouse_left
1944
1945        def info_button_clicked(self,button):
1946               
1947                buffer=self.textview.get_buffer()
1948                ret=self.llx_conn.get_last_log()
1949                if ret!=None:
1950                        os.system("xdg-open %s &"%ret)
1951               
1952        #def info_button_clicked
1953
1954        def hide_window(self,widget,event):
1955               
1956                widget.hide()
1957                return True
1958               
1959        #def
1960
1961       
1962        def restore_shadow_alpha(self,mirror_button,widget):
1963
1964                if mirror_button.info["shadow_alpha"] >=0.2 :
1965                        mirror_button.info["shadow_alpha"]-=0.1
1966                        widget.queue_draw()
1967                        return True
1968                       
1969                mirror_button.info["animation_active"]=False
1970                return False
1971               
1972        #def  restore_shadow_alpha
1973       
1974
1975        def to_rad(self,degree):
1976               
1977                return degree * (pi/180)
1978               
1979        #def to_rad
1980       
1981       
1982        def get_wave_y(self,x,wtype=0):
1983               
1984               
1985                #return 1
1986               
1987                x_offset=self.wave_xoffset
1988                amplitude=self.wave_amplitude
1989               
1990                if wtype==1:
1991                        x_offset=self.wave_xoffset2
1992                        amplitude=self.wave_amplitude2
1993                       
1994                if wtype==2:
1995                        x_offset=self.wave_xoffset3
1996                        amplitude=self.wave_amplitude3
1997               
1998                return amplitude * math.sin((2*pi / self.wave_lenght)*(x - x_offset)) + self.wave_yoffset
1999               
2000               
2001        #def get_wave_y
2002
2003
2004        def quit(self,widget):
2005               
2006                Gtk.main_quit()
2007       
2008        #def quit
2009
2010       
2011#class LliurexMirror
2012
2013lm=LliurexMirror()
2014lm.start_gui()
Note: See TracBrowser for help on using the repository browser.