source: lliurex-up/trunk/fuentes/lliurex-up-gui/lliurex-up @ 2669

Last change on this file since 2669 was 2669, checked in by jrpelegrina, 3 years ago

WIP in gui. View packages to install

File size: 13.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import gi
5gi.require_version('Gtk', '3.0')
6gi.require_version('PangoCairo', '1.0')
7gi.require_version('Vte', '2.91')
8
9import cairo
10import os
11import threading
12import ConfigParser
13import platform
14import subprocess
15import sys
16import time
17
18from gi.repository import Gtk, Gdk, GObject, GLib, PangoCairo, Pango, Vte
19
20import signal
21signal.signal(signal.SIGINT, signal.SIG_DFL)
22
23import gettext
24gettext.textdomain('lliurex-up')
25_ = gettext.gettext
26
27
28
29RSRC_DIR="rsrc/"
30
31class Package:
32
33        def __init__(self,name,version,size,desktop_file,changelog_file):
34
35                self.name=name
36                self.version=version
37                self.size=size
38                self.parse_desktop(desktop_file)
39                self.parse_changelog(changelog_file)
40
41
42        def parse_desktop(self,desktop_file):
43               
44                try:
45                        config = ConfigParser.ConfigParser()
46                        config.optionxform=str
47                        config.read(desktop_file)
48                       
49                        if config.has_section("Desktop Entry") and config.has_option("Desktop Entry","Icon"):
50                                self.icon=config.get("Desktop Entry","Icon")
51                        else:
52                                self.icon="package"
53                               
54                except Exception as e:
55                       
56                        self.icon="package"
57                       
58
59        def parse_changelog(self,changelog_file):
60               
61                try:
62                       
63                        f=open(changelog_file,"r")
64                        self.changelog=f.readlines()
65                        f.close()
66                                               
67                except Exception as e:
68                       
69                        self.changelog="Changelog not found"
70
71
72
73class LliurexUp:
74
75        def __init__(self):
76
77
78                self.start_gui()
79
80        def start_gui(self):
81               
82                builder=Gtk.Builder()
83               
84                glade_path=RSRC_DIR+"lliurex-up.ui"
85                builder.add_from_file(glade_path)
86
87                self.stack = Gtk.Stack()
88                self.stack.set_transition_duration(1000)
89                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
90
91
92                self.window=builder.get_object("main_window")
93                self.main_box=builder.get_object("main_box")
94                self.pbar=builder.get_object("progressbar")
95                #self.pbar_label=builder.get_object("pbar_label")
96               
97
98                self.cancel_button_box=builder.get_object("cancel_button_box")
99                self.cancel_eb=builder.get_object("cancel_button_eventbox")
100                self.cancel_eb.connect("button-press-event", self.quit)
101                self.cancel_label=builder.get_object("cancel_button_label")
102
103
104                self.gather_box=builder.get_object("gather_box")
105                self.yes_button_box=builder.get_object("yes_button_box")
106                self.yes_button_label=builder.get_object("yes_button_label")
107                self.no_button_box=builder.get_object("no_button_box")
108                self.no_button_eb=builder.get_object("no_button_eventbox")
109                self.no_button_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
110                self.no_button_eb.connect("button-release-event", self.no_button_clicked)
111                self.no_button_label=builder.get_object("no_button_label")
112                self.gather_logo_box=builder.get_object("gather_logo_box")
113                self.gather_label=builder.get_object("gather_label")
114
115                self.update_box=builder.get_object("update_box")
116                self.version_available_label=builder.get_object("version_available_label")
117                self.version_update_label=builder.get_object("version_update_label")
118                self.number_packages_label=builder.get_object("number_packages_label")
119                self.size_update_label=builder.get_object("size_update_label")
120                self.view_packages_button_box=builder.get_object("view_packages_button_box")
121                self.view_packages_eb=builder.get_object("view_packages_eventbox")
122                self.view_packages_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
123                self.view_packages_eb.connect("button-release-event", self.view_packages_clicked)
124                self.view_packages_label=builder.get_object("view_packages_label")
125
126                self.update_button_box=builder.get_object("update_button_box")
127                self.update_button_eb=builder.get_object("update_button_eventbox")
128                self.update_button_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
129                self.update_button_eb.connect("button-release-event", self.install_packages)
130                self.update_button_label=builder.get_object("update_button_label")
131                self.terminal_label=builder.get_object("terminal_label")
132                self.viewport=builder.get_object("viewport")
133                self.terminal_scrolled=builder.get_object("terminalScrolledWindow")
134                self.vterminal=Vte.Terminal()
135                font_terminal = Pango.FontDescription("monospace normal 10")
136                self.vterminal.set_font(font_terminal)
137                self.terminal_scrolled.add(self.vterminal)
138               
139
140                self.packages_box=builder.get_object("packages_box")
141                self.return_arrow_box=builder.get_object("return_arrow_box")
142                self.return_arrow_eb=builder.get_object("return_arrow_eventbox")
143                self.return_arrow_eb.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
144                self.return_arrow_eb.connect("button-release-event", self.arrow_clicked)
145                self.packages_label=builder.get_object("packages_label")
146                self.packages_tv=builder.get_object("packages_treeview")
147                self.changelog_texview=builder.get_object("changelog_textview")
148
149                self.packages_store=Gtk.ListStore(str,str,str)
150                self.packages_tv.set_model(self.packages_store)
151                column=Gtk.TreeViewColumn("")
152                cell=Gtk.CellRendererPixbuf()
153                cell.set_property("stock-size",Gtk.IconSize.DIALOG)
154                column.pack_start(cell,True)
155                column.add_attribute(cell,"icon-name",0)
156                self.packages_tv.append_column(column)
157               
158                column=Gtk.TreeViewColumn("Package")
159                cell=Gtk.CellRendererText()
160                column.pack_start(cell,True)
161                column.add_attribute(cell,"markup",1)
162                column.set_expand(True)
163
164               
165                self.packages_tv.append_column(column)
166               
167                self.packages_tv.connect("button-release-event",self.package_clicked)
168               
169                column=Gtk.TreeViewColumn("Size")
170                cell=Gtk.CellRendererText()
171                cell.set_property("alignment",Pango.Alignment.CENTER)
172                column.pack_start(cell,False)
173                column.add_attribute(cell,"markup",2)
174                self.packages_tv.append_column(column)         
175               
176                self.changelog_textview=builder.get_object("changelog_textview")
177                self.changelog_label=builder.get_object("changelog_label")
178
179
180                self.stack.add_titled(self.gather_box,"gather","Gather")
181                self.stack.add_titled(self.update_box,"update", "Update")
182                self.stack.add_titled(self.packages_box, "packages", "Packages")
183
184                self.main_box.pack_start(self.stack,True,False,5)
185
186                self.window.show_all()
187                self.terminal_scrolled.hide()
188                self.viewport.hide()
189                self.terminal_label.hide()
190                self.cancel_button_box.hide()
191                self.yes_button_box.hide()
192                self.no_button_box.hide()
193
194                #self.pbar_label.hide()
195                self.pbar.show()
196               
197                self.window.connect("destroy",self.quit)
198               
199               
200                self.set_css_info()
201                #self.get_update_info()
202
203
204                GLib.timeout_add(100,self.pulsate_gathering_info)
205               
206                self.t=threading.Thread(target=self.gather_info)
207                self.t.daemon=True
208                self.t.start()
209                self.no_mirror=False
210
211                self.package_list=[]
212
213                GObject.threads_init()
214                Gtk.main()
215
216
217        def set_css_info(self):
218       
219                css = """
220
221
222                #WHITE_BACKGROUND {
223                        background-image:-gtk-gradient (linear, left top, left bottom, from (#ffffff),  to (#ffffff));;
224               
225                }
226
227                #BUTTON_LABEL{
228                        color:white;
229                        font: Roboto 10;
230                }
231
232                #DISABLED_BUTTON_OVER{
233                        background-image:-gtk-gradient (linear, left top, left bottom, from (#888888),  to (#888888));;
234                }
235               
236                #DISABLED_BUTTON{
237                        background-image:-gtk-gradient (linear, left top, left bottom, from (#666666),  to (#666666));;
238                }
239               
240                #CANCEL_BUTTON{
241                        background-image:-gtk-gradient (linear, left top, left bottom, from (#D32F2F),  to (#D32F2F));;
242                }
243               
244                #CANCEL_BUTTON_OVER{
245                        background-image:-gtk-gradient (linear, left top, left bottom, from (#F44336),  to (#F44336));;
246                }
247
248                #BUTTON_COLOR {
249                        background-image:-gtk-gradient (linear, left top, left bottom, from (#448AFF),  to (#448AFF));;
250               
251                }
252               
253                #UPDATE_BUTTON_LABEL{
254                        color:white;
255                        font: Roboto 11;
256                }
257               
258                #UPDATE_BUTTON_COLOR {
259                        background-image:-gtk-gradient (linear, left top, left bottom, from (#43A047),  to (#43A047));;
260               
261                }
262               
263                #GATHER_ICON_COLOR {
264                        background-image:-gtk-gradient (linear, left top, left bottom, from (#b0bec5),  to (#b0bec5));;
265               
266                }
267               
268               
269                #BLUE_FONT {
270                        color: #3366cc;
271                        font: Roboto 10;
272                       
273                }       
274               
275
276                #CHANGELOG_FONT {
277                        color: #3366cc;
278                        font: Roboto 11;
279                       
280                }
281
282                #LABEL_OPTION{
283               
284                        color: #808080;
285                        font: Roboto 11;
286                }
287               
288                """
289
290                self.style_provider=Gtk.CssProvider()
291                self.style_provider.load_from_data(css)
292                Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),self.style_provider,Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
293               
294                self.update_box.set_name("WHITE_BACKGROUN")
295                self.gather_logo_box.set_name("GATHER_ICON_COLOR")
296                self.gather_label.set_name("BLUE_FONT")
297
298                self.yes_button_box.set_name("BUTTON_COLOR")
299                self.yes_button_label.set_name("BUTTON_LABEL")
300
301                self.no_button_box.set_name("BUTTON_COLOR")
302                self.no_button_label.set_name("BUTTON_LABEL")
303
304                self.view_packages_button_box.set_name("BUTTON_COLOR")
305                self.view_packages_label.set_name("BUTTON_LABEL")
306
307                self.cancel_button_box.set_name("BUTTON_COLOR")
308                self.cancel_label.set_name("BUTTON_LABEL")     
309
310                self.version_available_label.set_name("LABEL_OPTION")
311                self.version_update_label.set_name("LABEL_OPTION")     
312                self.number_packages_label.set_name("LABEL_OPTION")
313                self.size_update_label.set_name("LABEL_OPTION")
314                self.update_button_label.set_name("UPDATE_BUTTON_LABEL")
315                self.update_button_box.set_name("UPDATE_BUTTON_COLOR")
316                self.terminal_label.set_name("LABEL_OPTION")
317
318
319                self.packages_label.set_name("LABEL_OPTION")
320                self.changelog_label.set_name("LABEL_OPTION")
321                self.changelog_texview.set_name("CHANGELOG_FONT")
322
323        def check_lliurexup_version(self):
324
325                print "Checking lliurex-up version"
326                msg_gather="<span><b>"+_("Checking for new version of lliurex-up")+"</b></span>"
327                self.gather_label.set_markup(msg_gather)
328                time.sleep(2)
329                return True
330
331
332        def check_mirror(self):
333                print "Checking mirror"
334                self.response=-1
335                t=0
336                self.yes_button_box.show()
337                self.no_button_box.show()
338                msg_gather="<span><b>"+_("Do you want to update your mirror?")+"</b></span>"
339                self.gather_label.set_markup(msg_gather)
340               
341                while self.response==-1:
342                        time.sleep(t)
343                        t=t+1
344
345                self.yes_button_box.hide()
346                self.no_button_box.hide()       
347                return True
348
349
350        def gather_info(self):
351
352                self.check_lliurexup_version()
353                self.check_mirror()
354                               
355
356                cmd="sudo apt-get update"
357                msg_gather="<span><b>"+_("Checking for new updates")+"</b></span>"
358                self.gather_label.set_markup(msg_gather)
359               
360                #p=subprocess.Popen([cmd],shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)     
361                #output=p.communicate()
362                try:
363                        p1=subprocess.Popen(["llxcfg-upgrade-version-scripts","details"],stdout=subprocess.PIPE,stderr=subprocess.PIPE)
364                        output=p1.communicate()[0]
365                        f=open("/tmp/.lliurex_up_log","w")
366                        if output!=None:
367                                f.write(output)
368                        f.close()
369       
370                except:
371                        pass 
372
373
374
375        def pulsate_gathering_info(self):
376               
377                self.pbar.pulse()
378               
379                if not self.t.is_alive():
380                       
381                        self.parse_simulate_output("/tmp/.lliurex_up_log")
382                        self.populate_packages_tv()     
383                        self.get_update_info()
384                        self.pbar.hide()
385                        self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
386                        self.stack.set_visible_child_name("update")     
387                        self.cancel_button_box.show()
388
389                return self.t.is_alive()       
390
391               
392        def populate_packages_tv(self):
393               
394                for package in self.package_list:
395                        print package
396                        self.packages_store.append((package.icon,"<span font='Roboto'><b>"+package.name+"</b></span>\n"+"<span font='Roboto' size='small'>"+package.version+"</span>","<span font='Roboto' size='large'><b>"+package.size+"</b></span>"))
397                       
398                       
399                print len(self.packages_store) 
400        #def populate_packages_tv
401       
402        def parse_simulate_output(self,test_file=None):
403               
404                if test_file!=None:
405                        f=open(test_file,"r")
406                       
407                        for line in f:
408                                if line.find("#")==0:
409                                        pass
410                                else:
411                                        tmp=line.split(";")
412                                        if len(tmp)>4:
413                                                package=Package(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4])
414                                                self.package_list.append(package)
415
416                       
417                else:
418                        #to be done later
419                        pass   
420
421
422        def package_clicked(self,x,y):
423               
424                selection=self.packages_tv.get_selection()
425                model,iter=selection.get_selected()
426                name=self.packages_store.get_value(iter,1)
427                name=name[name.find("<b>")+3:name.find("</b>")]
428                               
429                for package in self.package_list:
430                       
431                        if package.name==name:
432                                self.changelog_textview.get_buffer().set_text("".join(package.changelog))
433                               
434                                break
435                               
436
437        def execute(self):
438               
439                self.vterminal.spawn_sync(
440                        Vte.PtyFlags.DEFAULT,
441                        os.environ['HOME'],
442                        ["/usr/sbin/dpkg-reconfigure", "xdm"],
443                        [],
444                        GLib.SpawnFlags.DO_NOT_REAP_CHILD,
445                        None,
446                        None,
447                )
448
449                               
450        def install_packages(self,widget, event=None):
451                self.t=threading.Thread(target=self.execute,args=())
452                self.t.daemon=True
453                self.t.start()
454                GLib.timeout_add(100,self.pulsate_pbar)
455                self.pbar.show()
456                self.viewport.show()
457                self.terminal_scrolled.show()
458                self.terminal_label.show()
459                msg_terminal=_("Update process details")
460                self.terminal_label.set_markup(msg_terminal)
461                               
462       
463        def get_update_info(self):
464                self.version_available="16.160916"
465                self.version_update="16.160915"
466                self.number_pkg="15"
467                self.size_update="100 Mb"
468               
469                msg_version_available=_("Version available: ")+"<span foreground='#3366cc'><b>"+self.version_available+"</b></span>"
470                msg_version_update=_("Version to update: ")+"<span foreground='#3366cc'><b>"+self.version_update+"</b></span>"
471
472                msg_number=_("Number packages: ")+"<span foreground='#3366cc'><b>"+self.number_pkg+"</b></span>"
473                msg_size=_("Size of update: ")+"<span foreground='#3366cc'><b>"+self.size_update+"</b></span>"
474               
475                self.version_available_label.set_markup(msg_version_available)
476                self.version_update_label.set_markup(msg_version_update)
477                self.number_packages_label.set_markup(msg_number)
478                self.size_update_label.set_markup(msg_size)
479               
480
481        def pulsate_pbar(self):
482                if not self.t.is_alive():
483                        self.pbar.pulse()
484                else:
485                        self.pbar.hide()
486
487                       
488        def view_packages_clicked(self,widget,event):
489                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_LEFT)
490                self.stack.set_visible_child_name("packages")
491
492
493        def no_button_clicked(self,widget,event):
494               
495                self.response=1 
496
497        def arrow_clicked(self,widget,event):
498                self.stack.set_transition_type(Gtk.StackTransitionType.SLIDE_RIGHT)
499                self.stack.set_visible_child_name("update")     
500       
501
502        def quit(self,widget,event=None):
503               
504                Gtk.main_quit() 
505
506#class LliurexMirror
507
508at=LliurexUp()         
Note: See TracBrowser for help on using the repository browser.