summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/Changelog1
-rw-r--r--doc/TODO5
-rw-r--r--portato/gui/gtk/dialogs.py2
-rw-r--r--portato/gui/gtk/windows.py8
-rw-r--r--portato/gui/gtk/wrapper.py32
-rw-r--r--portato/gui/qt/dialogs.py38
-rw-r--r--portato/gui/qt/tree.py99
-rw-r--r--portato/gui/qt/ui/MainWindow.ui51
-rw-r--r--portato/gui/qt/ui/SearchDialog.ui78
-rw-r--r--portato/gui/qt/windows.py218
-rw-r--r--portato/gui/wrapper.py19
11 files changed, 463 insertions, 88 deletions
diff --git a/doc/Changelog b/doc/Changelog
index 1dbfb98..72b4d53 100644
--- a/doc/Changelog
+++ b/doc/Changelog
@@ -1,5 +1,6 @@
next:
- showed difference between unmasked and masked but unmasked by yourself
+- added Qt-Frontend
0.6.1:
- first plugin support
diff --git a/doc/TODO b/doc/TODO
index c019509..2dd6fed 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -3,10 +3,15 @@ Backend:
- bugs in update world
- fix for flag handling, when reverting flags
+- save/restore queue on exit/start
GUI:
=====
+- ICON!!!
+- Systray
+- only remove already merged packages from queue
+
GTK:
----
- make oneshot better
diff --git a/portato/gui/gtk/dialogs.py b/portato/gui/gtk/dialogs.py
index 68cd629..f6573ef 100644
--- a/portato/gui/gtk/dialogs.py
+++ b/portato/gui/gtk/dialogs.py
@@ -35,7 +35,7 @@ def not_root_dialog ():
return ret
def unmask_dialog (cpv):
- dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, cpv+" seems to be masked.\nDo you want to unmask it and its dependencies?.\n")
+ dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, cpv+" seems to be masked.\nDo you want to unmask it and its dependencies?")
ret = dialog.run()
dialog.destroy()
return ret
diff --git a/portato/gui/gtk/windows.py b/portato/gui/gtk/windows.py
index 5b89aba..3fa39a8 100644
--- a/portato/gui/gtk/windows.py
+++ b/portato/gui/gtk/windows.py
@@ -32,9 +32,6 @@ from dialogs import *
from wrapper import GtkTree, GtkConsole
from usetips import UseTips
-# for the terminal
-import vte
-
# other
import types
@@ -712,7 +709,6 @@ class MainWindow (Window):
# booleans
self.doUpdate = False
- self.packageInit = True
# installed pixbuf
self.instPixbuf = self.window.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_MENU)
@@ -758,7 +754,7 @@ class MainWindow (Window):
self.build_queue_list()
# the terminal
- self.console = vte.Terminal()
+ self.console = GtkConsole()
self.termHB = self.tree.get_widget("termHB")
self.build_terminal()
@@ -776,7 +772,7 @@ class MainWindow (Window):
# set emerge queue
self.queueTree = GtkTree(self.queueList.get_model())
- self.queue = EmergeQueue(console = GtkConsole(self.console), tree = self.queueTree, db = self.db, title_update = self.title_update)
+ self.queue = EmergeQueue(console = self.console, tree = self.queueTree, db = self.db, title_update = self.title_update)
def show_package (self, *args, **kwargs):
self.packageTable.update(*args, **kwargs)
diff --git a/portato/gui/gtk/wrapper.py b/portato/gui/gtk/wrapper.py
index 95d8afa..bce4e07 100644
--- a/portato/gui/gtk/wrapper.py
+++ b/portato/gui/gtk/wrapper.py
@@ -11,6 +11,7 @@
# Written by René 'Necoro' Neumann <necoro@necoro.net>
from portato.gui.wrapper import Tree, Console
+import vte
class GtkTree (Tree):
"""The implementation of the abstract tree."""
@@ -37,7 +38,7 @@ class GtkTree (Tree):
if update:
string += "<i>updating</i>"
- if version != None:
+ if version is not None:
string += "<i> from version %s</i>" % version
return [cpv, string]
@@ -49,10 +50,10 @@ class GtkTree (Tree):
return self.unmergeIt
def is_in_emerge (self, it):
- return self.get_path_from_iter(it).split(":")[0] == self.get_path_from_iter(self.emergeIt)
+ return self.tree.get_string_from_iter(it).split(":")[0] == self.tree.get_string_from_iter(self.emergeIt)
def is_in_unmerge (self, it):
- return self.get_path_from_iter(it).split(":")[0] == self.get_path_from_iter(self.unmergeIt)
+ return self.tree.get_string_from_iter(it).split(":")[0] == self.tree.get_string_from_iter(self.unmergeIt)
def iter_has_parent (self, it):
return (self.tree.iter_parent(it) != None)
@@ -72,14 +73,11 @@ class GtkTree (Tree):
def get_value (self, it, column):
return self.tree.get_value(it, column)
- def get_path_from_iter (self, it):
- return self.tree.get_string_from_iter(it)
-
def append (self, parent = None, values = None):
return self.tree.append(parent, values)
def remove (self, it):
- return self.tree.remove(it)
+ self.tree.remove(it)
def get_original (self):
return self.tree
@@ -87,22 +85,6 @@ class GtkTree (Tree):
def get_cpv_column (self):
return self.cpv_col
-class GtkConsole (Console):
+class GtkConsole (vte.Terminal, Console):
"""The implementation of the abstract Console for GTK."""
-
- def __init__ (self, console):
- """Constructor.
-
- @param console: the original console
- @type console: vte.Terminal"""
-
- self.console = console
-
- def get_window_title(self):
- return self.console.get_window_title()
-
- def set_pty (self, pty):
- self.console.set_pty(pty)
-
- def get_original (self):
- return self.console
+ pass
diff --git a/portato/gui/qt/dialogs.py b/portato/gui/qt/dialogs.py
new file mode 100644
index 0000000..cf32439
--- /dev/null
+++ b/portato/gui/qt/dialogs.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/gui/qt/dialogs.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2007 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from PyQt4.QtGui import QMessageBox
+
+def io_ex_dialog (parent, ex):
+ string = ex.strerror
+ if ex.filename:
+ string = string+": "+ex.filename
+
+ return QMessageBox.critical(parent, "Portato", string, QMessageBox.Ok)
+
+def nothing_found_dialog (parent):
+ return QMessageBox.information(parent, "Portato", "No packages found.", QMessageBox.Ok)
+
+def not_root_dialog (parent):
+ return QMessageBox.warning(parent, "Portato", "You are not root!", QMessageBox.Ok)
+
+def unmask_dialog (parent, cpv):
+ return QMessageBox.question(parent, "Portato", cpv+" seems to be masked.\nDo you want to unmask it and its dependencies?", QMessageBox.Yes | QMessageBox.No)
+
+def blocked_dialog (parent, blocked, blocks):
+ return QMessageBox.warning(parent, "Portato", blocked+" is blocked by "+blocks+".\nPlease unmerge the blocking package.", QMessageBox.Ok)
+
+def remove_deps_dialog (parent):
+ return QMessageBox.information(parent, "Portato", "You cannot remove dependencies. :)", QMessageBox.Ok)
+
+def remove_queue_dialog (parent):
+ return QMessageBox.question(parent, "Portato", "Do you really want to clear the whole queue?", QMessageBox.Yes | QMessageBox.No)
diff --git a/portato/gui/qt/tree.py b/portato/gui/qt/tree.py
new file mode 100644
index 0000000..3e64f09
--- /dev/null
+++ b/portato/gui/qt/tree.py
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+#
+# File: portato/gui/qt/tree.py
+# This file is part of the Portato-Project, a graphical portage-frontend.
+#
+# Copyright (C) 2007 René 'Necoro' Neumann
+# This is free software. You may redistribute copies of it under the terms of
+# the GNU General Public License version 2.
+# There is NO WARRANTY, to the extent permitted by law.
+#
+# Written by René 'Necoro' Neumann <necoro@necoro.net>
+
+from PyQt4 import QtGui, QtCore
+from portato.gui.wrapper import Tree
+
+class QtTree (Tree):
+
+ def __init__ (self, treeWidget, col = 0):
+
+ self.tree = treeWidget
+ self.col = col
+
+ self.emergeIt = QtGui.QTreeWidgetItem(self.tree, ["Emerge", ""])
+ self.unmergeIt = QtGui.QTreeWidgetItem(self.tree, ["Unmerge", ""])
+
+ def build_append_value (self, cpv, oneshot = False, update = False, version = None):
+ string = ""
+
+ if oneshot:
+ string += "(oneshot)"
+ if update: string += "; "
+
+ if update:
+ string += "(updating"
+ if version is not None:
+ string += "from version %s" % version
+ string += ")"
+
+ return [cpv, string]
+
+ def get_emerge_it (self):
+ return self.emergeIt
+
+ def get_unmerge_it (self):
+ return self.unmergeIt
+
+ def is_in_emerge (self, it):
+ while self.iter_has_parent(it):
+ it = self.parent_iter(it)
+ return (it == self.emergeIt)
+
+ def is_in_unmerge (self, it):
+ return not self.is_in_emerge(it)
+
+ def iter_has_parent (self, it):
+ return (it.parent() != None)
+
+ def parent_iter (self, it):
+ return it.parent()
+
+ def first_child_iter (self, it):
+ return it.child(0)
+
+ def iter_has_children (self, it):
+ return (it.childCount() > 0)
+
+ def next_iter (self, it):
+ iter = QtGui.QTreeWidgetItemIterator(it)
+ iter += 1 # next iter ...
+ return iter.value()
+
+ def get_value (self, it, column):
+ return str(it.text(column))
+
+ def append (self, parent = None, values = None):
+ if values is None:
+ values = ["",""]
+ else:
+ for i in range(len(values)):
+ if values[i] is None:
+ values[i] = ""
+
+ if parent is None:
+ parent = self.tree
+
+ return QtGui.QTreeWidgetItem(parent, values)
+
+ def remove (self, it):
+ # a somehow strange approach ;) - go to the parent and delete the child
+ parent = it.parent()
+ index = parent.indexOfChild(it)
+ parent.takeChild(index)
+
+ def get_original (self):
+ return self.tree
+
+ def get_cpv_column (self):
+ return self.col
+
diff --git a/portato/gui/qt/ui/MainWindow.ui b/portato/gui/qt/ui/MainWindow.ui
index c7a5549..5a8f950 100644
--- a/portato/gui/qt/ui/MainWindow.ui
+++ b/portato/gui/qt/ui/MainWindow.ui
@@ -64,16 +64,23 @@
<property name="frameShadow" >
<enum>QFrame::Sunken</enum>
</property>
+ <property name="editTriggers" >
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
</widget>
</item>
<item>
- <widget class="QListView" name="pkgList" />
+ <widget class="QListView" name="pkgList" >
+ <property name="editTriggers" >
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ </widget>
</item>
</layout>
</widget>
<widget class="QTabWidget" name="tabWidget" >
<property name="currentIndex" >
- <number>2</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="pkgTab" >
<attribute name="title" >
@@ -214,6 +221,9 @@ p, li { white-space: pre-wrap; }
<property name="horizontalScrollBarPolicy" >
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
+ <property name="editTriggers" >
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
<property name="rootIsDecorated" >
<bool>true</bool>
</property>
@@ -295,7 +305,24 @@ p, li { white-space: pre-wrap; }
<number>6</number>
</property>
<item>
- <widget class="QTreeView" name="treeView" />
+ <widget class="QTreeWidget" name="queueList" >
+ <property name="editTriggers" >
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </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>
<item>
<layout class="QHBoxLayout" >
@@ -316,7 +343,7 @@ p, li { white-space: pre-wrap; }
</sizepolicy>
</property>
<property name="text" >
- <string>&amp;Emerge</string>
+ <string>E&amp;merge</string>
</property>
</widget>
</item>
@@ -419,5 +446,21 @@ p, li { white-space: pre-wrap; }
</hint>
</hints>
</connection>
+ <connection>
+ <sender>searchEdit</sender>
+ <signal>returnPressed()</signal>
+ <receiver>searchBtn</receiver>
+ <slot>click()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>287</x>
+ <y>49</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>400</x>
+ <y>55</y>
+ </hint>
+ </hints>
+ </connection>
</connections>
</ui>
diff --git a/portato/gui/qt/ui/SearchDialog.ui b/portato/gui/qt/ui/SearchDialog.ui
new file mode 100644
index 0000000..02c62ff
--- /dev/null
+++ b/portato/gui/qt/ui/SearchDialog.ui
@@ -0,0 +1,78 @@
+<ui version="4.0" >
+ <class>SearchDialog</class>
+ <widget class="QDialog" name="SearchDialog" >
+ <property name="windowModality" >
+ <enum>Qt::ApplicationModal</enum>
+ </property>
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>246</width>
+ <height>97</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Search...</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>9</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QComboBox" name="comboBox" />
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox" >
+ <property name="orientation" >
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons" >
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
+ </property>
+ <property name="centerButtons" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>SearchDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>164</x>
+ <y>112</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>157</x>
+ <y>70</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>SearchDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>164</x>
+ <y>112</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>173</x>
+ <y>70</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/portato/gui/qt/windows.py b/portato/gui/qt/windows.py
index 16152ec..e6fc7bc 100644
--- a/portato/gui/qt/windows.py
+++ b/portato/gui/qt/windows.py
@@ -10,6 +10,7 @@
#
# Written by René 'Necoro' Neumann <necoro@necoro.net>
+# qt4
from PyQt4 import QtGui, uic, QtCore
import sip
@@ -21,10 +22,14 @@ from portato.backend.exceptions import *
from portato.gui.gui_helper import Database, Config, EmergeQueue
+# own GUI stuff
from terminal import QtConsole
+from tree import QtTree
+from dialogs import *
UI_DIR = DATA_DIR+"ui/"
+#XXX: global variables are bad
app = QtGui.QApplication([])
def qCheck (check):
@@ -48,15 +53,16 @@ class WindowMeta (sip.wrappertype, type):
class Window:
- def __init__(self):
- self._qt_base.__init__(self)
+ def __init__(self, parent = None):
+ self._qt_base.__init__(self, parent)
self.setupUi(self)
class AboutDialog (Window):
+ """A window showing the "about"-informations."""
__metaclass__ = WindowMeta
- def __init__ (self):
- Window.__init__(self)
+ def __init__ (self, parent = None):
+ Window.__init__(self, parent)
self.label.setText("""
<font size=5><b>Portato v.%s</b></font><br><br>
@@ -69,6 +75,33 @@ Copyright (C) 2006-2007 Ren&eacute; 'Necoro' Neumann &lt;necoro@necoro.net&gt;<b
self.adjustSize()
+class SearchDialog (Window):
+ """A window showing the results of a search process."""
+ __metaclass__ = WindowMeta
+
+ def __init__ (self, parent, list, jumpTo):
+ """Constructor.
+
+ @param parent: parent-window
+ @type parent: QtGui.QWidget
+ @param list: list of results to show
+ @type list: string[]
+ @param jump_to: function to call if "OK"-Button is hit
+ @type jump_to: function(string)"""
+
+ Window.__init__(self, parent)
+
+ self.comboBox.addItems(list)
+ self.comboBox.setCurrentIndex(0)
+ self.jumpTo = jumpTo
+
+ QtCore.QObject.connect(self, QtCore.SIGNAL("accepted()"), self.finish)
+
+ def finish (self):
+ s = str(self.comboBox.currentText())
+ self.done(0)
+ self.jumpTo(s)
+
class PackageDetails:
def __init__ (self, window):
@@ -77,10 +110,27 @@ class PackageDetails:
self.window.tabWidget.removeTab(0)
QtCore.QObject.connect(self.window.versCombo, QtCore.SIGNAL("currentIndexChanged(int)"), self.cb_combo_changed)
+ QtCore.QObject.connect(self.window.pkgEmergeBtn, QtCore.SIGNAL("clicked()"), self.cb_emerge_clicked)
+
+ def update (self, cp, queue = None, version = None, doEmerge = True, instantChange = False):
+ """Updates the table to show the contents for the package.
+
+ @param cp: the selected package
+ @type cp: string (cp)
+ @param queue: emerge-queue (if None the emerge-buttons are disabled)
+ @type queue: EmergeQueue
+ @param version: if not None, specifies the version to select
+ @type version: string
+ @param doEmerge: if False, the emerge buttons are disabled
+ @type doEmerge: False
+ @param instantChange: if True the changed keywords are updated instantly
+ @type instantChange: boolean"""
- def update (self, cp, version = None):
self.cp = cp
self.version = version
+ self.queue = queue
+ self.doEmerge = doEmerge
+ self.instantChange = instantChange
# packages and installed packages
self.packages = system.sort_package_list(system.find_packages(cp, masked = True))
@@ -99,13 +149,18 @@ class PackageDetails:
self.window.descLabel.setText(desc)
self.window.nameLabel.setText("<i><u>%s</i></u>" % self.actual_package().get_cp())
+
+ # disable buttons when emerging is not allowed
+ if not self.queue or not self.doEmerge:
+ self.window.pkgEmergeBtn.setEnabled(False)
+ self.window.pkgUnmergeBtn.setEnabled(False)
# first update -> show
if self.window.pkgTab.isHidden():
self.window.tabWidget.insertTab(0, self.window.pkgTab, "Package")
self.window.pkgTab.setHidden(False)
- self.window.tabWidget.setCurrentIndex(0)
+ self.window.tabWidget.setCurrentIndex(self.window.PKG_PAGE)
def set_combo (self):
self.window.versCombo.clear()
@@ -148,6 +203,40 @@ class PackageDetails:
item = QtGui.QTreeWidgetItem(actual_exp_it, ["", use, system.get_use_desc(use, self.cp)])
item.setCheckState(0, qCheck(pkg.is_use_flag_enabled(use)))
+ def _update_keywords (self, emerge, update = False):
+ if emerge:
+ try:
+ try:
+ self.queue.append(self.actual_package().get_cpv(), unmerge = False, update = update)
+ except PackageNotFoundException, e:
+ if unmask_dialog(self.window, e[0]) == QtGui.QMessageBox.Yes :
+ self.queue.append(self.actual_package().get_cpv(), unmerge = False, unmask = True, update = update)
+ except BlockedException, e:
+ blocked_dialog(self.window, e[0], e[1])
+ else:
+ try:
+ self.queue.append(self.actual_package().get_cpv(), unmerge = True)
+ except PackageNotFoundException, e:
+ debug("Package could not be found",e[0], error = 1)
+
+
+ def actual_package (self):
+ """Returns the actual selected package.
+
+ @returns: the actual selected package
+ @rtype: backend.Package"""
+
+ return self.packages[self.window.versCombo.currentIndex()]
+
+ def cb_emerge_clicked (self):
+ """Callback for pressed emerge-button. Adds the package to the EmergeQueue."""
+ if not am_i_root():
+ not_root_dialog(self.window)
+ else:
+ self._update_keywords(True)
+ self.window.tabWidget.setCurrentIndex(self.window.QUEUE_PAGE)
+ return True
+
def cb_combo_changed (self, combo):
"""Callback for the changed ComboBox.
It then rebuilds the useList and the checkboxes."""
@@ -173,15 +262,15 @@ class PackageDetails:
self.window.installedCheck.setSizePolicy(hidden)
self.window.maskedCheck.setSizePolicy(hidden)
self.window.testingCheck.setSizePolicy(hidden)
- #self.window.pkgEmergeBtn.setEnabled(False)
+ self.window.pkgEmergeBtn.setEnabled(False)
else: # normal package
self.window.missingLabel.setSizePolicy(hidden)
self.window.notInSysLabel.setSizePolicy(hidden)
self.window.installedCheck.setSizePolicy(shown)
self.window.maskedCheck.setSizePolicy(shown)
self.window.testingCheck.setSizePolicy(shown)
- #if self.doEmerge:
- # self.emergeBtn.set_sensitive(True)
+ if self.doEmerge:
+ self.window.pkgEmergeBtn.setEnabled(True)
self.window.installedCheck.setCheckState(qCheck(pkg.is_installed()))
if pkg.is_masked(use_changed = False) and not pkg.is_masked(use_changed = True):
@@ -198,26 +287,23 @@ class PackageDetails:
self.window.testingCheck.setCheckState(qCheck(pkg.is_testing(use_keywords = False)))
-# if self.doEmerge:
-# # set emerge-button-label
-# if not self.actual_package().is_installed():
-# self.emergeBtn.set_label("E_merge")
-# self.unmergeBtn.set_sensitive(False)
-# else:
-# self.emergeBtn.set_label("Re_merge")
-# self.unmergeBtn.set_sensitive(True)
-
- def actual_package (self):
- """Returns the actual selected package.
-
- @returns: the actual selected package
- @rtype: backend.Package"""
-
- return self.packages[self.window.versCombo.currentIndex()]
+ if self.doEmerge:
+ # set emerge-button-label
+ if not self.actual_package().is_installed():
+ self.window.pkgEmergeBtn.setText("E&merge")
+ self.window.pkgUnmergeBtn.setEnabled(False)
+ else:
+ self.window.pkgEmergeBtn.setText("Re&merge")
+ self.window.pkgUnmergeBtn.setEnabled(True)
class MainWindow (Window):
__metaclass__ = WindowMeta
+
+ # NOTEBOOK PAGE CONSTANTS
+ PKG_PAGE = 0
+ QUEUE_PAGE = 1
+ CONSOLE_PAGE = 2
def __init__ (self):
Window.__init__(self)
@@ -225,12 +311,22 @@ class MainWindow (Window):
self.setWindowTitle(("Portato (%s)" % VERSION))
self.statusbar.showMessage("Portato - A Portage GUI")
+ self.doUpdate = False
self.pkgDetails = PackageDetails(self)
# package db
self.db = Database()
self.db.populate()
+ # config
+ try:
+ self.cfg = Config(CONFIG_LOCATION)
+ except IOError, e:
+ io_ex_dialog(self, e)
+ raise
+
+ self.cfg.modify_external_configs()
+
# the two lists
self.build_pkg_list()
self.build_cat_list()
@@ -245,19 +341,29 @@ class MainWindow (Window):
self.consoleTab.setLayout(self.consoleLayout)
self.consoleLayout.addWidget(self.console)
- QtCore.QObject.connect(self.aboutAction, QtCore.SIGNAL("triggered()"), self.cb_about_triggered)
-
+ # build queueList
+ self.queueList.setHeaderLabels(["Package", "Additional infos"])
+ self.queueTree = QtTree(self.queueList)
+
+ QtCore.QObject.connect(self, QtCore.SIGNAL("doTitleUpdate"), self._title_update)
+
+ # set emerge queue
+ self.queue = EmergeQueue(console = self.console, tree = self.queueTree, db = self.db, title_update = self.title_update)
+
self.show()
+
+ def title_update (self, title):
+ self.emit(QtCore.SIGNAL("doTitleUpdate"), title)
- def cb_about_triggered (self):
- AboutDialog().exec_()
+ def _title_update (self, title):
+ if title == None: title = "Console"
+ else: title = ("Console (%s)" % title)
- def cb_cat_list_selected (self, index, prev):
- self.selCatName = str(index.data().toString())
- self.fill_pkg_list(self.selCatName)
+ self.tabWidget.setTabText(self.CONSOLE_PAGE, title)
- def cb_pkg_list_selected (self, index, prev):
- self.pkgDetails.update(self.selCatName+"/"+str(index.data().toString()))
+ def jump_to (self, cp):
+ """Is called when we want to jump to a specific package."""
+ self.pkgDetails.update(cp, self.queue)
def fill_pkg_list (self, cat):
self.pkgListModel.setStringList([name for (name,inst) in self.db.get_cat(cat)])
@@ -276,6 +382,50 @@ class MainWindow (Window):
self.catList.setModel(self.catListModel)
self.catList.setSelectionModel(self.selCatListModel)
+ @QtCore.pyqtSignature("")
+ def on_aboutAction_triggered (self):
+ AboutDialog(self).exec_()
+
+ @QtCore.pyqtSignature("")
+ def on_searchBtn_clicked (self):
+ """Do a search."""
+ text = str(self.searchEdit.text())
+ if text != "":
+ packages = system.find_all_packages(text, withVersion = False)
+
+ if packages == []:
+ nothing_found_dialog(self)
+ else:
+ if len(packages) == 1:
+ self.jump_to(packages[0])
+ else:
+ SearchDialog(self, packages, self.jump_to).exec_()
+
+ @QtCore.pyqtSignature("")
+ def on_removeBtn_clicked (self):
+ """Removes a selected item in the (un)emerge-queue if possible."""
+ selected = self.queueList.currentItem()
+
+ if selected:
+ if not selected.parent(): # top-level
+ if self.queueTree.iter_has_children(selected): # and has children which can be removed :)
+ if remove_queue_dialog(self) == QtGui.QMessageBox.Yes :
+ self.queue.remove_children(selected)
+ self.doUpdate = False
+
+ elif selected.parent().parent(): # this is in the 3rd level => dependency
+ remove_deps_dialog(self)
+ else:
+ self.queue.remove_with_children(selected)
+ self.doUpdate = False
+
+ def cb_cat_list_selected (self, index, prev):
+ self.selCatName = str(index.data().toString())
+ self.fill_pkg_list(self.selCatName)
+
+ def cb_pkg_list_selected (self, index, prev):
+ self.pkgDetails.update(self.selCatName+"/"+str(index.data().toString()), self.queue)
+
def main (self):
app.exec_()
diff --git a/portato/gui/wrapper.py b/portato/gui/wrapper.py
index 86f4efe..12e4a71 100644
--- a/portato/gui/wrapper.py
+++ b/portato/gui/wrapper.py
@@ -55,7 +55,7 @@ class Tree:
@param it: the iterator
@type it: Iterator
- @returns: Nex iterator or None if the current iter is the last one.
+ @returns: Next iterator or None if the current iter is the last one.
@rtype: Iterator; None"""
raise NotImplementedError
@@ -70,16 +70,6 @@ class Tree:
@rtype: anything"""
raise NotImplementedError
- def get_path_from_iter(self, it):
- """Returns a string defining the path to the given iterator. In this path all nodes are divided by a colon ':'.
- For example: 2:4:5 could mean the 6th child of the 5th child of the 3rd element. It might also mean the 5th child of the 4th child of the 2nd element. It does not matter, where counting starts as long as it is consistent.
-
- @param it: the iterator
- @type it: Iterator
- @returns: the path string
- @rtype: string"""
- raise NotImplementedError
-
def append (self, parent = None, values = None):
"""Appends some values right after the given parent. If parent is None, it is appended as the first element.
@@ -181,10 +171,3 @@ class Console:
@returns: title of the console or None"""
raise NotImplementedError
-
- def get_original(self):
- """Returns the original console-object.
-
- @returns: original console-object
- @rtype: console-object"""
- raise NotImplementedError