diff options
-rw-r--r-- | doc/Changelog | 2 | ||||
-rw-r--r-- | doc/TODO | 19 | ||||
-rw-r--r-- | plugins/etc_proposals.xml | 1 | ||||
-rw-r--r-- | portato/config_parser.py | 2 | ||||
-rw-r--r-- | portato/gui/gtk/windows.py | 2 | ||||
-rw-r--r-- | portato/gui/gui_helper.py | 6 | ||||
-rw-r--r-- | portato/gui/qt/helper.py | 13 | ||||
-rw-r--r-- | portato/gui/qt/highlighter.py | 74 | ||||
-rw-r--r-- | portato/gui/qt/terminal.py | 71 | ||||
-rw-r--r-- | portato/gui/qt/ui/AboutDialog.ui | 105 | ||||
-rw-r--r-- | portato/gui/qt/ui/MainWindow.ui | 12 | ||||
-rw-r--r-- | portato/gui/qt/windows.py | 67 | ||||
-rw-r--r-- | portato/helper.py | 9 | ||||
-rw-r--r-- | portato/plugin.py | 41 | ||||
-rw-r--r-- | portato/plugins/etc_proposals.py | 8 |
15 files changed, 351 insertions, 81 deletions
diff --git a/doc/Changelog b/doc/Changelog index 72b4d53..305d009 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,4 +1,4 @@ -next: +0.7.0: - showed difference between unmasked and masked but unmasked by yourself - added Qt-Frontend @@ -1,18 +1,29 @@ +Documentation: +============== + +- document the structure of plugin-XMLs + Backend: ======== -- bugs in update world -- fix for flag handling, when reverting flags +- bugs in update world (Necoro, 04/20/07: are there any more bugs?) +- fix for flag handling, when reverting flags (Necoro, 04/20/07: what did i mean by this?) + - save/restore queue on exit/start +- only remove already merged packages from queue +- make sure, a package being removed from the queue is not needed as a dependency by another package GUI: -===== +==== - ICON!!! - Systray -- only remove already merged packages from queue GTK: ---- - make oneshot better - better infos in queue for "newuse" + +Qt: +--- +- find a way to use markup in CheckBoxes, Lists etc. diff --git a/plugins/etc_proposals.xml b/plugins/etc_proposals.xml index e4569e1..8686072 100644 --- a/plugins/etc_proposals.xml +++ b/plugins/etc_proposals.xml @@ -3,7 +3,6 @@ author="RenĂ© 'Necoro' Neumann" name="Etc-proposals plugin"> <import>portato.plugins.etc_proposals</import> - <frontend>gtk</frontend> <hook hook = "after_emerge" diff --git a/portato/config_parser.py b/portato/config_parser.py index 8418a6a..30873e7 100644 --- a/portato/config_parser.py +++ b/portato/config_parser.py @@ -164,7 +164,7 @@ class ConfigParser: self.vars[section][key] = Value(val, count, bool = bool) self.pos[count] = match.span(2) else: # neither comment nor empty nor expression nor section => error - debug("Unrecognized line:",line) + debug("Unrecognized line in configuration:", line, error = 1) def get (self, key, section = "MAIN"): """Returns the value of a given key in a section. diff --git a/portato/gui/gtk/windows.py b/portato/gui/gtk/windows.py index d2151ab..5aeceed 100644 --- a/portato/gui/gtk/windows.py +++ b/portato/gui/gtk/windows.py @@ -757,7 +757,7 @@ class MainWindow (Window): self.cfg.modify_external_configs() # set plugins and plugin-menu - plugin.load_plugins() + plugin.load_plugins("gtk") menus = plugin.get_plugins().get_plugin_menus() if menus: self.tree.get_widget("pluginMenuItem").set_no_show_all(False) diff --git a/portato/gui/gui_helper.py b/portato/gui/gui_helper.py index e52b3f3..5cc2ee6 100644 --- a/portato/gui/gui_helper.py +++ b/portato/gui/gui_helper.py @@ -30,7 +30,7 @@ import time import os import signal -class Config: +class Config: # XXX: This needs to be replaced - the const-dict is just messy """Wrapper around a ConfigParser and for additional local configurations.""" const = { "main_sec" : "Main", @@ -263,7 +263,9 @@ class EmergeQueue: @param console: Output is shown here. @type console: Console @param db: A database instance. - @type db: Database""" + @type db: Database + @param title_update: A function, which will be called whenever there is a title update. + @type title_update: function(string)""" # the different queues self.mergequeue = [] # for emerge diff --git a/portato/gui/qt/helper.py b/portato/gui/qt/helper.py index 1b7dbdc..fa1576a 100644 --- a/portato/gui/qt/helper.py +++ b/portato/gui/qt/helper.py @@ -13,10 +13,23 @@ from PyQt4 import Qt def qCheck (check): + """Maps True or False to Qt.Checked or Qt.Unchecked. + + @param check: boolean value + @type check: bool + @returns: CheckState-Constant + @rtype: int""" + if check: return Qt.Qt.Checked else: return Qt.Qt.Unchecked def qIsChecked (check): + """Maps Qt.Checked and Qt.Unchecked to True and False. + + @param check: CheckState-Constant + @type check: int + @returns: appropriate boolean value + @rtype: bool""" return check == Qt.Qt.Checked diff --git a/portato/gui/qt/highlighter.py b/portato/gui/qt/highlighter.py index 5572930..74d9ac9 100644 --- a/portato/gui/qt/highlighter.py +++ b/portato/gui/qt/highlighter.py @@ -19,30 +19,59 @@ from portato.helper import debug import re # prefer Python-Module over Qt-one class EbuildHighlighter (Qt.QSyntaxHighlighter): + """A QSyntaxHighlighter implementation for the use with ebuild-syntax.""" NORMAL_STATE = 0 STRING_STATE = 1 def __init__ (self, edit): + """Constructor. + + @param edit: the EditWidget to use the highlighter with + @type edit: Qt.QTextEdit""" + Qt.QSyntaxHighlighter.__init__(self, edit) + # + # the regular expressions ... *muahahaha* + # + + # comments self.comment = self.__create(r'#.*', color = "steelblue", italic = True) + + # bash variables self.bashVar = self.__create(r'(\$\{.+?\})|(\$\w+)', color = "green") + # a string + self.string = self.__create(r'(?<!\\)"', color = "fuchsia") + + # the syntax elements, which are checked in a loop self.syntax = {} + + # bash syntax self.syntax["bashSyn"] = self.__create(r'\b(case|do|done|elif|else|esac|exit|fi|for|function|if|in|local|read|return|select|shift|then|time|until|while)\b', color = "navy", underline = True) + # special bash commands self.syntax["bashCmd"] = self.__create(r'\b(make|awk|cat|cd|chmod|chown|cp|echo|env|export|grep|head|let|ln|mkdir|mv|rm|sed|set|tail|tar|touch|unset)\b', color = "navy", bold = True) + # portage variables self.syntax["portVar"] = self.__create(r'\b((ARCH|HOMEPAGE|DESCRIPTION|IUSE|SRC_URI|LICENSE|SLOT|KEYWORDS|FILESDIR|WORKDIR|(P|R)?DEPEND|PROVIDE|DISTDIR|RESTRICT|USERLAND)|(S|D|T|PV|PF|P|PN|A)|C(XX)?FLAGS|LDFLAGS|C(HOST|TARGET|BUILD))\b', color = "saddlebrown", bold = True) + # portage commands self.syntax["portCmd"] = self.__create(r'\b(e(begin|end|conf|install|make|warn|infon?|error|patch)|die|built_with_use|use(_(with|enable))?|inherit|hasq?|(has|best)_version|unpack|(do|new)(ins|s?bin|doc|lib(|\.so|\.a)|man|info|exe|initd|confd|envd|pam|menu|icon)|do(python|sed|dir|hard|sym|html|jar|mo)|keepdir|prepall(|docs|info|man|strip)|prep(info|lib|lib\.(so|a)|man|strip)|(|doc|ins|exe)into|f(owners|perms)|(exe|ins|dir)opts)\b', color = "saddlebrown", bold = True) + # portage functions, i.e. the functions implemented by the ebuild self.syntax["portFunc"] = self.__create(r'^(src_(unpack|compile|install|test)|pkg_(config|nofetch|setup|(pre|post)(inst|rm)))', color = "green") - self.string = self.__create(r'(?<!\\)"', color = "fuchsia") - def do_reg_exp (self, syntaxTuple, string): + """Tries to match a regular expression and if this succeeds, + sets the text format. + + @param syntaxTuple: tuple holding regexp and format + @type sytaxTuple: (RE-object, Qt.QTextCharFormat) + @param string: the string to look in + @type string: string""" + regexp, format = syntaxTuple match = regexp.search(string) @@ -55,19 +84,27 @@ class EbuildHighlighter (Qt.QSyntaxHighlighter): match = regexp.search(string, span[1]) def highlightBlock (self, string): + """This function is called, whenever the edit want to have some text checked. + + @param string: the text to check + @type string: Qt.QString""" + string = str(string) # we got a QString here + # check the normal syntax elements for t in self.syntax.values(): self.do_reg_exp(t, string) + # reset to normal state :) self.setCurrentBlockState(self.NORMAL_STATE) # look for strings prevStart = 0 foundEnd = False stringMatch = self.string[0].search(string) - if self.previousBlockState() == self.STRING_STATE: - if stringMatch is None: + + if self.previousBlockState() == self.STRING_STATE: # we were in a string last time + if stringMatch is None: # and there is no end of string in this line self.setFormat(0, len(string), self.string[1]) self.setCurrentBlockState(self.STRING_STATE) else: @@ -75,17 +112,22 @@ class EbuildHighlighter (Qt.QSyntaxHighlighter): while stringMatch is not None: - if foundEnd: + if foundEnd: # we know that the string will end in this block self.setCurrentBlockState(self.NORMAL_STATE) self.setFormat(prevStart, stringMatch.end() - prevStart, self.string[1]) + + # look for a possible start of another string stringMatch = self.string[0].search(string, stringMatch.end()) foundEnd = False - else: + + else: # we have entered a new string + prevStart = stringMatch.start() - stringMatch = self.string[0].search(string, stringMatch.end()) + stringMatch = self.string[0].search(string, stringMatch.end()) # the end of string + if stringMatch is not None: foundEnd = True - else: + else: # no string end: mark the rest of the line as string self.setCurrentBlockState(self.STRING_STATE) self.setFormat(prevStart, len(string) - prevStart, self.string[1]) @@ -93,6 +135,22 @@ class EbuildHighlighter (Qt.QSyntaxHighlighter): self.do_reg_exp(self.comment, string) # do comments last def __create (self, regexp, color = None, italic = False, bold = False, underline = False): + """This creates a syntax tuple. + + @param regexp: the regular expression + @type regexp: string + @param color: the color to take; if None, take standard color + @type color: string + @param italic: italic-flag + @type italic: bool + @param bold: bold-flag + @type bold: bool + @param underline: underline-flag + @type underline: bool + + @returns: the created syntax-tuple + @rtype: (RE-object, Qt.QTextCharFormat) + """ compRe = re.compile(regexp) format = Qt.QTextCharFormat() diff --git a/portato/gui/qt/terminal.py b/portato/gui/qt/terminal.py index 2734aaf..85bea0e 100644 --- a/portato/gui/qt/terminal.py +++ b/portato/gui/qt/terminal.py @@ -46,6 +46,7 @@ backspace = 8 title_seq = ("\x1b", "]") title_end = "\x07" +# the attributes attr = {} attr[0] = None # normal attr[1] = BoldFormat() # bold @@ -61,8 +62,15 @@ attr[37] = ColorFormat("white") attr[39] = None # default class QtConsole (Console, Qt.QTextEdit): + """Self implemented emulation of a terminal emulation. + This only supports a subset of instructions known to normal terminals.""" def __init__ (self, parent): + """Constructor. + + @param parent: parent widget + @type parent: Qt.QWidget""" + Qt.QTextEdit.__init__(self, parent) self.pty = None @@ -74,14 +82,23 @@ class QtConsole (Console, Qt.QTextEdit): self.setReadOnly(True) + # we need these two signals, as threads are not allowed to access the GUI + # solution: thread sends signal, which is handled by the main loop Qt.QObject.connect(self, Qt.SIGNAL("doSomeWriting"), self._write) Qt.QObject.connect(self, Qt.SIGNAL("deletePrevChar()"), self._deletePrev) def _deletePrev (self): + """Deletes the previous character.""" self.textCursor().deletePreviousChar() def _write (self, text): - if text == esc_seq[0]: + """Writes some text. A text of "\\x1b" signals _write() to reload + the current char format. + + @param text: the text to print + @type text: string""" + + if text == esc_seq[0]: # \x1b -> reload format self.setCurrentCharFormat(self.get_format()) else: @@ -97,13 +114,16 @@ class QtConsole (Console, Qt.QTextEdit): self.ensureCursorVisible() def write(self, text): + """Convenience function for emitting the writing signal.""" self.emit(Qt.SIGNAL("doSomeWriting"), text) def start_new_thread (self): - self.run = True - self.current = Thread(target=self.__run, name="QtTerminal Listener") - self.current.setDaemon(True) # close application even if this thread is running - self.current.start() + """Starts a new thread, which will listen for some input. + @see: QtTerminal.__run()""" + self.run = True + self.current = Thread(target=self.__run, name="QtTerminal Listener") + self.current.setDaemon(True) # close application even if this thread is running + self.current.start() def set_pty (self, pty): if not self.running: @@ -111,21 +131,22 @@ class QtConsole (Console, Qt.QTextEdit): self.start_new_thread() self.running = True - else: - # quit current thread + else: # quit current thread self.run = False - # self.current.join() self.clear() self.pty = pty # set this after clearing to lose no chars :) self.start_new_thread() def __run (self): + """This function is mainly a loop, which looks for some new input at the terminal, + and parses it for text attributes.""" + while self.run: s = read(self.pty, 1) - if s == "": break + if s == "": break # nothing read -> finish - if ord(s) == backspace: + if ord(s) == backspace: # BS self.emit(Qt.SIGNAL("deletePrevChar()")) continue @@ -154,9 +175,16 @@ class QtConsole (Console, Qt.QTextEdit): self.write(s) def parse_seq (self, seq): - global attr + """Parses a sequence of bytes. + If a new attribute has been encountered, a new format is created and added + to the internal format queue. + + @param seq: sequence to parse + @type seq: string""" + + global attr # the dict of attributes - format = self.virgin_format() + format = self.virgin_format() if seq != reset_seq: # resettet -> done seq = seq.split(seq_sep) @@ -178,10 +206,9 @@ class QtConsole (Console, Qt.QTextEdit): break self.add_format(format) - self.write(esc_seq[0]) + self.write(esc_seq[0]) # write \x1b to signal the occurence of a new format def parse_title (self, seq): - if not seq.startswith("0;"): return @@ -191,15 +218,31 @@ class QtConsole (Console, Qt.QTextEdit): return self.title def add_format (self, format): + """Adds a format to the queue. + We have to take a queue, because the write-signals might occur asynchronus, + so we set a format for the wrong characters. + + @param format: the format to add + @type format: Qt.QTextCharFormat""" + self.formatLock.acquire() self.formatQueue.append(format) self.formatLock.release() def get_format (self): + """Returns a format from the queue. + We have to take a queue, because the write-signals might occur asynchronus, + so we set a format for the wrong characters. + + @returns: the popped format + @rtype: Qt.QTextCharFormat""" + self.formatLock.acquire() f = self.formatQueue.pop(0) self.formatLock.release() return f def virgin_format (self): + """The normal standard format. It is necessary to create it as a new one for some + dubious reasons ... only Qt.QGod knows why.""" return Qt.QTextCharFormat(self.stdFormat) diff --git a/portato/gui/qt/ui/AboutDialog.ui b/portato/gui/qt/ui/AboutDialog.ui index 5ed35e2..1424270 100644 --- a/portato/gui/qt/ui/AboutDialog.ui +++ b/portato/gui/qt/ui/AboutDialog.ui @@ -9,7 +9,7 @@ <x>0</x> <y>0</y> <width>369</width> - <height>279</height> + <height>270</height> </rect> </property> <property name="windowTitle" > @@ -23,32 +23,91 @@ <number>6</number> </property> <item> - <widget class="QLabel" name="label" > - <property name="text" > - <string>TextLabel</string> - </property> - <property name="alignment" > - <set>Qt::AlignCenter</set> - </property> - <property name="wordWrap" > - <bool>true</bool> + <widget class="QTabWidget" name="tabWidget" > + <property name="currentIndex" > + <number>0</number> </property> + <widget class="QWidget" name="tab" > + <attribute name="title" > + <string>About</string> + </attribute> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QLabel" name="label" > + <property name="text" > + <string>TextLabel</string> + </property> + <property name="alignment" > + <set>Qt::AlignCenter</set> + </property> + <property name="wordWrap" > + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer> + <property name="orientation" > + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" > + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QWidget" name="tab_2" > + <attribute name="title" > + <string>Plugins</string> + </attribute> + <layout class="QVBoxLayout" > + <property name="margin" > + <number>9</number> + </property> + <property name="spacing" > + <number>6</number> + </property> + <item> + <widget class="QTreeWidget" name="pluginList" > + <property name="editTriggers" > + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="showDropIndicator" stdset="0" > + <bool>false</bool> + </property> + <property name="rootIsDecorated" > + <bool>false</bool> + </property> + <property name="columnCount" > + <number>2</number> + </property> + <column> + <property name="text" > + <string>1</string> + </property> + </column> + <column> + <property name="text" > + <string>1</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> </widget> </item> <item> - <spacer> - <property name="orientation" > - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" > - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item> <widget class="QDialogButtonBox" name="buttonBox" > <property name="orientation" > <enum>Qt::Horizontal</enum> diff --git a/portato/gui/qt/ui/MainWindow.ui b/portato/gui/qt/ui/MainWindow.ui index 80c5c12..5b8d0d9 100644 --- a/portato/gui/qt/ui/MainWindow.ui +++ b/portato/gui/qt/ui/MainWindow.ui @@ -403,7 +403,7 @@ p, li { white-space: pre-wrap; } <height>27</height> </rect> </property> - <widget class="QMenu" name="menuFile" > + <widget class="QMenu" name="fileMenu" > <property name="title" > <string>&File</string> </property> @@ -412,13 +412,13 @@ p, li { white-space: pre-wrap; } <addaction name="separator" /> <addaction name="quitAction" /> </widget> - <widget class="QMenu" name="menuHelp" > + <widget class="QMenu" name="helpMenu" > <property name="title" > <string>&?</string> </property> <addaction name="aboutAction" /> </widget> - <widget class="QMenu" name="menu_Emerge" > + <widget class="QMenu" name="emergeMenu" > <property name="title" > <string>&Emerge</string> </property> @@ -431,9 +431,9 @@ p, li { white-space: pre-wrap; } <addaction name="separator" /> <addaction name="killAction" /> </widget> - <addaction name="menuFile" /> - <addaction name="menu_Emerge" /> - <addaction name="menuHelp" /> + <addaction name="fileMenu" /> + <addaction name="emergeMenu" /> + <addaction name="helpMenu" /> </widget> <widget class="QStatusBar" name="statusbar" > <property name="enabled" > diff --git a/portato/gui/qt/windows.py b/portato/gui/qt/windows.py index f6d5103..3fa93cf 100644 --- a/portato/gui/qt/windows.py +++ b/portato/gui/qt/windows.py @@ -22,6 +22,9 @@ from portato.backend.exceptions import * from portato.gui.gui_helper import Database, Config, EmergeQueue +# plugins +from portato import plugin + # own GUI stuff from terminal import QtConsole from tree import QtTree @@ -34,6 +37,10 @@ import types UI_DIR = DATA_DIR+"ui/" class WindowMeta (sip.wrappertype, type): + """This is the metaclass of all Qt-Windows. It automatically + sets the correct base classes, so they do not have to be set + by the programmer. + @attention: The class has to have the same name as the .ui-file.""" def __new__ (cls, name, bases, dict): new_bases = uic.loadUiType(UI_DIR+name+".ui") @@ -47,6 +54,8 @@ class WindowMeta (sip.wrappertype, type): super(WindowMeta, cls).__init__(name, b+bases, dict) class Window (object): + """Base class of all Qt-Windows. + Sets up the UI and provides the watch_cursor function.""" def __init__(self, parent = None): self._qt_base.__init__(self, parent) @@ -72,7 +81,14 @@ class AboutDialog (Window): """A window showing the "about"-informations.""" __metaclass__ = WindowMeta - def __init__ (self, parent = None): + def __init__ (self, parent = None, plugins = []): + """Constructor. + + @param parent: the parent window + @type parent: Qt.QWidget + @param plugins: The list of plugins (author,name) to show in the "Plugins"-Tab. + @type plugins: (string, string)[]""" + Window.__init__(self, parent) self.label.setText(""" @@ -84,6 +100,13 @@ Copyright (C) 2006-2007 René 'Necoro' Neumann <necoro@necoro.net><b <br> <font size=1>Thanks to Fred for support and ideas :P</font>""" % VERSION) + self.pluginList.setHeaderLabels(["Plugin", "Author"]) + + for p in plugins: + Qt.QTreeWidgetItem(self.pluginList, list(p)) + + self.pluginList.resizeColumnToContents(0) + self.adjustSize() class SearchDialog (Window): @@ -114,10 +137,16 @@ class SearchDialog (Window): self.jumpTo(s) class EbuildDialog (Window): - + """Window showing an ebuild.""" __metaclass__ = WindowMeta def __init__ (self, parent, package): + """Constructor. + + @param parent: parent window + @type parent: Qt.QWidget + @param package: The package to show the ebuild of. + @type package: backend.Package""" Window.__init__(self, parent) @@ -164,11 +193,18 @@ class PreferenceWindow (Window): } def __init__ (self, parent, cfg): + """Constructor. + + @param parent: parent window + @type parent: Qt.QWidget + @param cfg: the actual configuration + @type cfg: Config""" Window.__init__(self, parent) self.cfg = cfg + # set hintLabel background palette = self.hintLabel.palette() palette.setColor(Qt.QPalette.Active, Qt.QPalette.Window, Qt.QColor(Qt.Qt.yellow)) self.hintLabel.setPalette(palette) @@ -213,6 +249,7 @@ class PreferenceWindow (Window): io_ex_dialog(self, e) class PackageDetails: + """The tab showing the details of a package.""" def __init__ (self, window): self.window = window @@ -288,6 +325,8 @@ class PackageDetails: self.window.tabWidget.setCurrentIndex(self.window.PKG_PAGE) def set_combo (self): + """Fills the version combo box with the right items and selects the correct one.""" + self.window.versCombo.clear() self.window.versCombo.addItems([x.get_version() for x in self.packages]) @@ -305,6 +344,7 @@ class PackageDetails: self.window.versCombo.setCurrentIndex(0) def build_use_list (self): + """Builds the list of use flags.""" self.window.useList.clear() self.window.useList.setHeaderLabels(["Enabled","Flag","Description"]) @@ -461,6 +501,10 @@ class PackageDetails: def cb_combo_changed (self): """Callback for the changed ComboBox. It then rebuilds the useList and the checkboxes.""" + + # + # ATTENTION: BIG'n'DIRTY :) + # # build new self.build_use_list() @@ -522,6 +566,7 @@ class PackageDetails: self.window.pkgUnmergeBtn.setEnabled(True) class MainWindow (Window): + """The application's main window.""" __metaclass__ = WindowMeta @@ -552,6 +597,16 @@ class MainWindow (Window): self.cfg.modify_external_configs() + # set plugins and plugin-menu + plugin.load_plugins("qt") + menus = plugin.get_plugins().get_plugin_menus() + if menus: + self.pluginMenu = Qt.QMenu("&Plugins") + self.menubar.insertMenu(self.helpMenu.menuAction(), self.pluginMenu) + for m in menus: + action = self.pluginMenu.addAction(m.label.replace("_","&")) + Qt.QObject.connect(action, Qt.SIGNAL("triggered()"), m.call) + # the two lists self.build_cat_list() Qt.QObject.connect(self.selCatListModel, Qt.SIGNAL("currentChanged(QModelIndex, QModelIndex)"), self.cb_cat_list_selected) @@ -624,7 +679,13 @@ class MainWindow (Window): @Qt.pyqtSignature("") def on_aboutAction_triggered (self): - AboutDialog(self).exec_() + queue = plugin.get_plugins() + if queue is None: + queue = [] + else: + queue = queue.get_plugin_data() + + AboutDialog(self, queue).exec_() @Qt.pyqtSignature("") def on_prefAction_triggered (self): diff --git a/portato/helper.py b/portato/helper.py index cef3537..537d631 100644 --- a/portato/helper.py +++ b/portato/helper.py @@ -13,7 +13,6 @@ import traceback, os.path, sys from itertools import chain - DEBUG = True def set_debug (d): @@ -32,7 +31,13 @@ def debug(*args, **kwargs): If debug(obj0, obj1, obj2) is called, the text part of the output looks like the output from print obj0, obj1, obj2. - If you pass the optional keyword-argument "name", it is used for the function-name instead of the original one.""" + Keywords which can be used: + - name: Use the given name instead the correct function name. + - file: output file to use + - minus: The value given is the amount of frames to ignore in the stack to return the correct function call. + This should be used if you are wrapping the debug call. + - warn: Prints the message as a warning. Value of DEBUG is ignored. + - error: Prints the message as an error. Value of DEBUG is ignored.""" if not DEBUG and not ("warn" in kwargs or "error" in kwargs): return diff --git a/portato/plugin.py b/portato/plugin.py index c6e3288..4c5070e 100644 --- a/portato/plugin.py +++ b/portato/plugin.py @@ -239,12 +239,15 @@ class Plugin: class PluginQueue: """Class managing and loading the plugins.""" - def __init__ (self, load = True): + def __init__ (self, frontend, load = True): """Constructor. - + + @param frontend: the frontend used + @type frontend: string @param load: if False nothing is loaded @type load: bool""" + self.frontend = frontend self.list = [] self.hooks = {} if load: @@ -343,12 +346,30 @@ class PluginQueue: elem = list[0] - plugin = Plugin(p, elem.getAttribute("name"), elem.getAttribute("author")) - plugin.parse_hooks(elem.getElementsByTagName("hook")) - plugin.set_import(elem.getElementsByTagName("import")) - plugin.parse_menus(elem.getElementsByTagName("menu")) + frontendOK = None + for f in elem.getElementsByTagName("frontend"): + if f.hasChildNodes(): + nodes = f.childNodes + if len(nodes) > 1: + raise ParseException, "Malformed frontend" + + if nodes[0].nodeType != nodes[0].TEXT_NODE: + raise ParseException, "Malformed frontend" + + fValue = nodes[0].nodeValue.strip() + if fValue == self.frontend: + frontendOK = True # one positive is enough + break + elif frontendOK is None: # do not make negative if we already have a positive + frontendOK = False + + if frontendOK is None or frontendOK == True: + plugin = Plugin(p, elem.getAttribute("name"), elem.getAttribute("author")) + plugin.parse_hooks(elem.getElementsByTagName("hook")) + plugin.set_import(elem.getElementsByTagName("import")) + plugin.parse_menus(elem.getElementsByTagName("menu")) - self.list.append(plugin) + self.list.append(plugin) except ParseException, e: error(e[0],p) @@ -435,10 +456,10 @@ class PluginQueue: __plugins = None -def load_plugins(): +def load_plugins(frontend): global __plugins - if __plugins is None: - __plugins = PluginQueue() + if __plugins is None or __plugins.frontend != frontend: + __plugins = PluginQueue(frontend) def get_plugins(): return __plugins diff --git a/portato/plugins/etc_proposals.py b/portato/plugins/etc_proposals.py index cdf0a87..a064fff 100644 --- a/portato/plugins/etc_proposals.py +++ b/portato/plugins/etc_proposals.py @@ -13,8 +13,6 @@ from portato.helper import debug, am_i_root from portato.backend import system -from portato.gui.gtk.dialogs import not_root_dialog - from subprocess import Popen from etcproposals.etcproposals_lib import EtcProposals, __version__ @@ -41,10 +39,10 @@ def etc_prop (*args, **kwargs): Popen(["etc-proposals", "--frontend", "gtk", "--fastexit"]) def etc_prop_menu (*args, **kwargs): - if not am_i_root(): - not_root_dialog() - else: + if am_i_root(): if float(__version__) < 1.1: Popen("etc-proposals") else: Popen(["etc-proposals", "--frontend", "gtk"]) + else: + debug("Cannot start etc-proposals. Not root!", error = 1) |