root/trunk/src/kitInstaller.py @ 78

Revision 78, 22.0 KB (checked in by pcabido, 5 years ago)
Line 
1# -*- coding: utf-8 -*-
2from repositoryhandler import repHandler
3
4import warnings
5warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
6
7import pygtk
8pygtk.require('2.0')
9import gtk
10import gtk.glade
11
12import os
13import sys
14import gobject
15import copy
16#import threading
17
18from util import util, aptutil, xmlutil
19from util import SearchWidget
20from PackageWorker import PackageWorker
21
22from gettext import textdomain, gettext as _
23
24__title__ = _("Kits Installer")
25__version__ = "0.0.1"
26__comments__ = _("GTK frontend for Kits Installer.")
27__authors__= ["Paulo Cabido <paulo.cabido@gmail.com>"]
28__copyright__ = "Paulo Cabido"
29__license__ = _("GNU GPL v3")
30
31#gtk.gdk.threads_init()
32
33class kitInstallerGTK:#(threading.Thread):
34   
35    def delete(self, widget, event, data=None):
36        """
37        Exits gtk.
38        """
39        gtk.main_quit()
40        return False
41   
42    def errorDialog(self, header, msg):
43         """
44         Shows a error message.
45         """
46
47         dialog = gtk.MessageDialog(parent=self.window,
48                               flags=gtk.DIALOG_MODAL,
49                               type=gtk.MESSAGE_ERROR,
50                               buttons=gtk.BUTTONS_CLOSE)
51         dialog.set_title("")
52         dialog.set_markup("<big><b>%s</b></big>\n\n%s" % (header, msg))
53         dialog.realize()
54         #dialog.window.set_functions(gtk.gdk.FUNC_MOVE)
55         dialog.run()
56         dialog.destroy()
57   
58    def sucessDialog(self, header, msg):
59        """
60        Shows a sucess/info message.
61        """
62
63        dialog = gtk.MessageDialog(parent=self.window,
64                               flags=gtk.DIALOG_MODAL,
65                               type=gtk.MESSAGE_INFO,
66                               buttons=gtk.BUTTONS_CLOSE)
67        dialog.set_title("")
68        dialog.set_markup("<big><b>%s</b></big>\n\n%s" % (header, msg))
69        dialog.realize()
70        #dialog.window.set_functions(gtk.gdk.FUNC_MOVE)
71        dialog.run()
72        dialog.destroy()
73   
74    def choiceDialog(self, header, msg):
75        """
76        Shows a choice dialog (yes/no) message.
77        """
78        dialog = gtk.MessageDialog(parent=self.window,
79                               flags=gtk.DIALOG_MODAL,
80                               type=gtk.MESSAGE_QUESTION,
81                               buttons=gtk.BUTTONS_YES_NO)
82        dialog.set_title("")
83        dialog.set_markup("<big><b>%s</b></big>\n\n%s" % (header, msg))
84        #cdialog.window.set_functions(gtk.gdk.FUNC_MOVE)
85        response = dialog.run()
86   
87        if response == gtk.RESPONSE_YES:
88            dialog.destroy()
89            return True
90        else:
91            dialog.destroy()
92            return False
93           
94       
95    #
96    # aboutdialog
97    #
98    def closeAbout(self, widget, data=None):
99        """
100        Closes the about dialog.
101        """
102        self.aboutDialog.hide()
103        return True
104   
105    def showAbout(self, widget, data=None):
106        """
107        Create the about dialog.
108        @param widget: Current widget
109        @type widget: gtk widget
110        """
111       
112        #self.aboutDialogIcon = gtk.gdk.pixbuf_new_from_file("pixmaps/kitsalinex.svg")
113        self.aboutDialog = self.wTree.get_widget("aboutdialogKitInstaller")
114        self.aboutDialog.set_name(__title__)
115        self.aboutDialog.set_version(__version__)
116        self.aboutDialog.set_comments(__comments__)
117        self.aboutDialog.set_copyright(__copyright__)
118        self.aboutDialog.set_authors(__authors__)
119        self.aboutDialog.set_license(__license__)
120        #self.aboutDialog.set_logo(self.aboutDialogIcon)
121       
122        self.aboutDialog.connect("destroy", self.closeAbout)
123        self.aboutDialog.connect("delete_event", self.closeAbout)
124        self.aboutDialog.connect("response", self.closeAbout)
125        self.aboutDialog.show()
126        return True
127   
128    #
129    #views
130    #
131    def rowCickedPackages(self, treeview):
132        """
133        Shows the kits info
134        """
135       
136        path = treeview.get_cursor()[0]
137        iter = treeview.get_model().get_iter(path)
138
139        (mark, name, version, sdesc) = treeview.get_model()[iter]
140        sdesc = aptutil.shortDescFromDic(self.packageList, name, version)
141        ldesc = aptutil.longDescFromDic(self.packageList, name, version).replace(".\n","\n")
142        self.textPackagesLDesc.get_buffer().set_text(sdesc + "\n" + ldesc )
143        return
144   
145    def rowSection(self, treeview):
146        """
147        Shows the kits that are in the selected (row) section
148        """
149       
150        path = treeview.get_cursor()[0]
151        if path:
152            model = treeview.get_model()
153            iter = treeview.get_model().get_iter(path)
154            section = model.get_value(iter,0)
155        else:
156            section = _("All packages")
157       
158        #mostrar apenas os pacotes da section caso nao seja o all
159        self.storePackages.clear()
160        if section != _("All packages"):
161            self.selectedSection = util.dicKey(self.parseSection.getSections(), section)
162        else:
163            self.selectedSection = "all"
164       
165        if self.selectedSection != "all" :
166            if self.setSearch:
167                self.sectionPackageList = aptutil.getSectionPackages(util.dicKey(self.parseSection.getSections(), section), self.searchPackageList)
168            else:
169                self.sectionPackageList = aptutil.getSectionPackages(util.dicKey(self.parseSection.getSections(), section), self.packageList)
170           
171            for pkg in self.sectionPackageList:
172                self.storePackages.append([pkg['Installed'], pkg['Package'], pkg['Version'], pkg['ShortDesc']])
173            self.treeviewPackages.set_model(self.storePackages)
174            self.treeviewPackages.set_search_column(1)
175        else:
176            if self.setSearch:
177                pkgList = self.searchPackageList
178            else:
179                pkgList = self.packageList
180               
181            for pkg in pkgList:
182                self.storePackages.append([pkg['Installed'], pkg['Package'], pkg['Version'], pkg['ShortDesc']])
183            self.treeviewPackages.set_model(self.storePackages)
184            self.treeviewPackages.set_search_column(1)
185        return
186   
187    def searchPackagesList(self, widget, query):
188        """
189        Searches the packages lists and sets the Treeviews with the results.
190        """
191       
192        if query:
193            self.searchPackageList = []
194            self.setSearch = True
195            for val in self.packageList:
196                if (query in val['Package']) or (query in val['Version']) or (query in val['ShortDesc']) \
197                or (query in val['LongDesc']) or (query in val['Maintainer']):
198                    self.searchPackageList.append(val)
199            self.rowSection(self.treeviewSections)   
200        else:
201            self.setSearch = False
202            self.rowSection(self.treeviewSections)
203           
204        return True
205         
206    def colToggledClicked( self, cell, path, model ):
207        """
208        Changes the toggle value in the treeview
209        """
210       
211        model[path][0] = not model[path][0]
212       
213        for pkg in self.packageList:
214            if pkg['Package'] == model[path][1] and pkg['Version'] == model[path][2]:
215                pkg['Installed'] = model[path][0]
216   
217    def setupPackagesView(self):
218        """
219        Defines the columns in the treeview
220        """
221       
222        self.rendererToggle = gtk.CellRendererToggle()
223        self.rendererToggle.set_property('activatable', True)
224        self.rendererToggle.connect('toggled', self.colToggledClicked, self.storePackages)
225       
226        self.colToggle = gtk.TreeViewColumn("", self.rendererToggle )
227        self.colToggle.add_attribute(self.rendererToggle, "active", 0)
228       
229        self.colPacote = gtk.TreeViewColumn(_("Kit"), self.rendererText, text=1)
230        self.colPacote.set_resizable(True)
231        self.colPacote.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
232        self.colPacote.set_fixed_width( 160 )
233        self.colPacote.set_sort_column_id(1)
234       
235        self.colVersion = gtk.TreeViewColumn(_("Version"), self.rendererText, text=2)
236        self.colVersion.set_resizable(True)
237        self.colVersion.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
238        self.colVersion.set_fixed_width( 150 )
239        #self.colVersion.set_sort_column_id(2)
240       
241        self.colDesc = gtk.TreeViewColumn(_("Description"), self.rendererText, text=3)
242        self.colDesc.set_resizable(True)
243        self.colDesc.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
244        self.colDesc.set_fixed_width( 350 )
245        #self.colDesc.set_sort_column_id(3)
246       
247        self.treeviewPackages.append_column(self.colToggle)
248        self.treeviewPackages.append_column(self.colPacote)
249        self.treeviewPackages.append_column(self.colVersion)
250        self.treeviewPackages.append_column(self.colDesc)
251        return
252       
253    def setupPackageList(self, deleteFiles=False):
254        """
255        Builds the package list
256        """
257       
258        self.dialogProgress.realize()
259        self.dialogProgress.set_transient_for(self.window)
260        self.pbar.set_fraction(0)
261        self.dialogProgress.window.set_functions(gtk.gdk.FUNC_MOVE)
262        self.dialogProgress.show()
263       
264        self.window.set_sensitive(False)
265        while gtk.events_pending():
266                    gtk.main_iteration()
267       
268        self.pbar.set_fraction(0.1)
269        while gtk.events_pending():
270                    gtk.main_iteration()
271       
272        if deleteFiles:
273            result = self.rep.update(True)
274        else:
275            result = self.rep.update()
276       
277        if not result:
278            self.errorDialog(_("Error"),
279                             _("The package list download failed."))
280            self.dialogProgress.hide()
281            self.window.set_sensitive(True)
282            return False
283       
284        self.pbar.set_fraction(0.5)
285        while gtk.events_pending():
286                    gtk.main_iteration()
287        result = self.rep.loadPackages()
288                   
289        if not result:
290            self.dialogProgress.hide()
291            self.window.set_sensitive(True)
292            return False
293       
294        self.pbar.set_fraction(0.7)
295        while gtk.events_pending():
296                    gtk.main_iteration()
297                   
298        self.rep.checkInstalled()
299       
300        while gtk.events_pending():
301                    gtk.main_iteration()
302        self.pbar.set_fraction(0.8)
303        self.packageList = self.rep.getPackages()   
304        self.storePackages.clear() 
305        for pkg in self.packageList:
306            self.storePackages.append([pkg['Installed'], pkg['Package'], pkg['Version'], pkg['ShortDesc']])
307           
308                   
309        self.treeviewPackages.set_model(self.storePackages)
310        self.treeviewPackages.set_search_column(1)       
311       
312        while gtk.events_pending():
313                    gtk.main_iteration()
314        self.pbar.set_fraction(0.95)
315       
316        self.sections = self.rep.getSections()
317        self.storeSections.clear()
318        for stn in self.sections:
319            if stn == "all":
320                self.storeSections.append([_("All packages")])
321            else:
322                self.storeSections.append([self.parseSection.getSections()[stn]])
323           
324        self.treeviewSections.set_model(self.storeSections)
325        self.treeviewSections.set_search_column(0)
326
327        self.origPkgList = copy.deepcopy(self.packageList)
328           
329        #gtk.gdk.threads_leave()
330        #self.cpbar.close()
331        self.dialogProgress.hide()
332        self.window.set_sensitive(True)
333       
334        return True
335   
336    def updateRepository(self, widget, data=None):
337        """
338        Forces a repository update
339        """
340        self.rep.clean()
341        self.setupPackageList(True)
342       
343   
344    def doInstallRemove(self, widget, data=None):
345        """
346        Installs or removes the selected packages
347        """
348       
349        pkgs_add = []
350        pkgs_rm = []
351        cache = ""
352       
353        for pkg in self.packageList:
354            for opkg in self.origPkgList:
355                if pkg['Package'] == opkg['Package'] and pkg['Version'] == opkg['Version'] and pkg['Installed'] != opkg['Installed']:
356                    if pkg["Installed"]:
357                         pkgs_add.append(pkg['Package'])
358                    else:
359                        pkgs_rm.append(pkg['Package'])
360       
361        result = self.packageWorker.perform_action(self.window,
362                                                   cache,
363                                                   None,
364                                                   None,
365                                                   1)
366       
367        result = self.packageWorker.perform_action(self.window,
368                                                   cache,
369                                                   pkgs_add,
370                                                   pkgs_rm)
371       
372        erroInst = ""
373        for pkg in pkgs_add:
374            if not aptutil.isInstalled(pkg, False):
375                if not erroInst:
376                    erroInst += pkg
377                else:
378                    erroInst += ", " + pkg
379                   
380                for val in self.packageList:
381                    if val['Package'] == pkg:
382                        val['Installed'] = False
383                        break
384                   
385                item = self.storePackages.get_iter_first()
386                while ( item != None ):
387                    if self.storePackages.get_value(item, 1,) == pkg:
388                        self.storePackages.set_value(item, 0, False)
389                        break
390                    item = self.storePackages.iter_next(item)
391            else:
392                for val in self.origPkgList:
393                    if val['Package'] == pkg:
394                        val['Installed'] = True
395                        break
396       
397       
398        erroRm = ""
399        for pkg in pkgs_rm:
400            if aptutil.isInstalled(pkg, False):
401                if not erroRm:
402                    erroRm += pkg
403                else:
404                    erroRm += ", " + pkg
405               
406                for val in self.packageList:
407                    if val['Package'] == pkg:
408                        val['Installed'] = True
409                        break
410                   
411                item = self.storePackages.get_iter_first()
412                while ( item != None ):
413                    if self.storePackages.get_value(item, 1,) == pkg:
414                        self.storePackages.set_value(item, 0, True)
415                        break
416                    item = self.storePackages.iter_next(item)
417            else:
418                for val in self.origPkgList:
419                    if val['Package'] == pkg:
420                        val['Installed'] = False
421                        break
422               
423               
424        if erroInst and erroRm:
425            self.errorDialog(_("Error"),
426                             (_("Error while installing the following kits <b>%s</b> and while removing <b>%s</b>.") % (erroInst, erroRm)))
427        elif erroInst:
428            self.errorDialog(_("Error"),
429                             _("Error while installing the following kits <b>%s</b>.") % erroInst)
430        elif erroRm:
431            self.errorDialog(_("Error"),
432                             _("Error while removing the following kits <b>%s</b>.") % erroRm)
433        else:
434            self.sucessDialog(_("Success"),
435                              _("All kits where installed/removed with success."))
436       
437        return True 
438       
439       
440    def openKit(self, widget, data=None):
441        pkgs_add = []
442        pkgs_rm = []
443        dialog = gtk.FileChooserDialog(_("Open Kit"),
444                               None,
445                               gtk.FILE_CHOOSER_ACTION_OPEN,
446                               (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
447                                gtk.STOCK_OPEN, gtk.RESPONSE_OK))
448       
449        dialog.set_default_response(gtk.RESPONSE_OK)
450       
451        filter = gtk.FileFilter()
452        filter.set_name("Kits")
453        filter.add_pattern("*.deb")
454        dialog.add_filter(filter)
455       
456        response = dialog.run()
457        kitType = ""
458        if response == gtk.RESPONSE_OK:
459            kitFile = dialog.get_filename()
460            tmpKitFile = os.path.splitext(kitFile)
461           
462            if tmpKitFile[1] != "":
463                if tmpKitFile[1] == ".deb":
464                    kitType = "deb"
465                else:
466                    print "error"
467        else:
468            dialog.destroy()
469            return
470       
471        dialog.destroy()
472       
473        filename = (tmpKitFile[0] +  tmpKitFile[1])
474       
475        if aptutil.isInstalled(filename):
476            if aptutil.upgradable(filename):
477                upgrade = self.choiceDialog(_("Update Kit"),
478                                            _("<b>%s</b> is already installed, but this version is newer.\nDo you wish to update?")
479                                            % aptutil.pkgInfo(filename, "Package"))
480               
481                if upgrade:
482                    result = aptutil.install(filename)
483               
484                    if result:
485                        self.sucessDialog(_("Update Kit"),
486                                          _("<b>%s</b> was successfully updated.") % aptutil.pkgInfo(filename, "Package"))
487                        return True
488                    else:
489                        self.errorDialog(_("Error"),
490                                         _("Error while updating <b>%s</b>.") % aptutil.pkgInfo(filename, "Package"))
491                        return False
492            else:
493                self.sucessDialog(_("Update Kit"),
494                                  _("The <b>%s</b> Kit is already updated.") % aptutil.pkgInfo(filename, "Package"))
495                return True
496        else:
497            install = self.choiceDialog(_("Install Kit"),
498                                        _("Do you wish to install <b>%s</b>?") % aptutil.pkgInfo(filename, "Package"))
499            if install:
500                result = aptutil.install(filename)
501                if result:
502                    self.sucessDialog(_("Kit installed"),
503                                      _("Kit <b>%s</b> was installed with success.") % aptutil.pkgInfo(filename, "Package"))
504                    return True
505                else:
506                    self.errorDialog(_("Error"),
507                                     _("Error while installing <b>%s</b>.") % aptutil.pkgInfo(filename, "Package"))
508                    return False
509    #
510    # __init__
511    #
512   
513    def __init__(self):
514        self.localPath = os.path.realpath(os.path.dirname(sys.argv[0]))
515       
516        self.tmpDir = "/tmp/kitsalinex/sourcelist"
517        self.localDir = os.getenv('HOME')
518        self.sourcelist = self.localPath + "/data/sources.list"
519       
520        self.packageList = []
521       
522        self.sectionPackageList = []
523        self.sectionsFile = self.localPath + "/data/sections.xml"
524        self.parseSection = xmlutil.parseSection(self.sectionsFile)
525        self.parseSection.run()
526       
527        self.sections = []
528        self.selectedSection = "all"
529       
530        self.setSearch = False
531        self.searchPackageList = []
532       
533        self.rep = repHandler.rephandle(self.sourcelist, self.tmpDir)
534       
535        self.gladefile = self.localPath + "/data/kitInstaller.glade"
536        self.wTree = gtk.glade.XML(self.gladefile)
537       
538        self.notebook = self.wTree.get_widget("notebook")
539       
540        self.quitMenu = self.wTree.get_widget("quitMenu")
541        self.aboutMenu = self.wTree.get_widget("aboutMenu")
542        self.openMenu = self.wTree.get_widget("openMenu")
543        self.updateRepMenu = self.wTree.get_widget("updateRepMenu")
544       
545        self.buttonAplicar = self.wTree.get_widget("buttonAplicar")
546       
547        self.vboxSearch = self.wTree.get_widget("vboxSearch")
548        self.entrySearchbox = SearchWidget.SearchEntry(gtk.icon_theme_get_default())
549        self.vboxSearch.add(self.entrySearchbox)
550        self.entrySearchbox.connect("terms-changed", self.searchPackagesList)
551        self.entrySearchbox.show()
552       
553        self.treeviewSections = self.wTree.get_widget("treeviewSection")
554        self.treeviewPackages = self.wTree.get_widget("treeviewPackages")
555        self.textPackagesLDesc = self.wTree.get_widget("textPackagesLDesc")
556       
557        self.storeSections = gtk.ListStore(str)
558        self.storePackages = gtk.ListStore(gobject.TYPE_BOOLEAN, str, str, str)
559       
560        #renderer's
561        self.rendererText = gtk.CellRendererText()
562       
563        #sections
564        self.colSection = gtk.TreeViewColumn(_("Section"), self.rendererText, text=0)
565        self.colSection.set_resizable(True)
566        self.colSection.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
567        self.colSection.set_fixed_width( 210 )
568        self.treeviewSections.append_column(self.colSection)
569       
570        #package lists
571        self.setupPackagesView()
572       
573        #Progress dialog   
574        self.dialogProgress = self.wTree.get_widget("dialogProgress")
575        self.pbar = self.wTree.get_widget("pbarCache")
576       
577        self.window = self.wTree.get_widget("window_installkits")
578        if (self.window):
579            self.window.set_title(__title__)
580            self.window.connect("destroy", gtk.main_quit)
581            self.window.connect("delete_event", self.delete)
582           
583            self.buttonAplicar.connect('clicked', self.doInstallRemove, None)
584               
585            #menubar
586            self.quitMenu.connect('activate', gtk.main_quit)
587            self.aboutMenu.connect('activate', self.showAbout)
588            self.openMenu.connect('activate', self.openKit)
589            self.updateRepMenu.connect('activate', self.updateRepository)
590           
591            self.treeviewPackages.connect("cursor-changed", self.rowCickedPackages)
592            self.treeviewSections.connect("cursor-changed", self.rowSection)
593           
594            self.setupPackageList()
595            self.packageWorker = PackageWorker()
596           
597           
598def main():
599    hwg = kitInstallerGTK()
600    gtk.main()
601    return 0
602
603#if __name__ == "__main__":
604#    hwg = KitInstallerGTK()
605#    main()
606   
Note: See TracBrowser for help on using the browser.