From 1b96094fc866d0bcd7eaba601e171170a5b1147e Mon Sep 17 00:00:00 2001 From: Giovanni Gherdovich Date: Wed, 15 Sep 2010 12:13:44 +0200 Subject: [PATCH 01/16] removed the dummy root 'xml' tag from rspec view --- sface/screens/rspecscreen.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/sface/screens/rspecscreen.py b/sface/screens/rspecscreen.py index e6a75d1..2354b2a 100644 --- a/sface/screens/rspecscreen.py +++ b/sface/screens/rspecscreen.py @@ -25,6 +25,15 @@ class DomModel(QAbstractItemModel): def __init__(self, document, parent = 0): QAbstractItemModel.__init__(self, parent) self.domDocument = document + # one of the children of the rootItem is the 'xml' thing. + # here I delete it. + childList = document.childNodes() + for i in range(childList.count()): + currElem = childList.item(i) + if (currElem.nodeType() == + QDomNode.ProcessingInstructionNode): + document.removeChild(currElem) + break self.rootItem = DomItem(document, 0); def data(self, index, role): @@ -62,7 +71,8 @@ class DomModel(QAbstractItemModel): elif node.nodeType() == QDomNode.EntityNode: return QString('unsupported node type') elif node.nodeType() == QDomNode.ProcessingInstructionNode: - return node.nodeName() + return QVariant() + #return node.nodeName() elif node.nodeType() == QDomNode.CommentNode: return QString('#').append(node.nodeValue()) elif node.nodeType() == QDomNode.DocumentNode: -- 2.43.0 From e94b101b92ec34a00a40efede30e09df7ff72676 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 12:18:36 +0200 Subject: [PATCH 02/16] manage signals between screens through sfascreen --- sface/screens/configscreen.py | 4 ++++ sface/screens/mainscreen.py | 20 ++++++++++++++------ sface/screens/rspecscreen.py | 3 +++ sface/screens/sfascreen.py | 13 +++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/sface/screens/configscreen.py b/sface/screens/configscreen.py index dbe3909..3f2440e 100644 --- a/sface/screens/configscreen.py +++ b/sface/screens/configscreen.py @@ -59,6 +59,9 @@ class ConfigWidget(QWidget): self.parent().setStatus("Settings loaded for current session", timeout=5000) config.display("after apply") + self.parent().signalAll('configurationChanged') + + def save(self): self.apply() config.save_config() @@ -70,3 +73,4 @@ class ConfigScreen(SfaScreen): widget = ConfigWidget(self) self.init(widget, "Configure", "Configure the OneLab Federation GUI") + diff --git a/sface/screens/mainscreen.py b/sface/screens/mainscreen.py index be67787..5507294 100644 --- a/sface/screens/mainscreen.py +++ b/sface/screens/mainscreen.py @@ -47,7 +47,6 @@ class NodeView(QTreeView): model.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), hostname_index, hostname_index) - class NodeNameDelegate(QStyledItemDelegate): def __init__(self, parent): @@ -99,6 +98,7 @@ class NodeNameDelegate(QStyledItemDelegate): painter.restore() + class TreeItem: def __init__(self, data, parent=None): self.parentItem = parent @@ -267,7 +267,6 @@ class NodeModel(QAbstractItemModel): return ret - class SliceWidget(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) @@ -275,15 +274,16 @@ class SliceWidget(QWidget): self.network_names = [] self.process = SfiProcess(self) - slicename = QLabel ("Slice : %s"%(config.getSlice() or "None"),self) - slicename.setScaledContents(False) + self.slicename = QLabel("", self) + self.updateSliceName() + self.slicename.setScaledContents(False) searchlabel = QLabel ("Search: ", self) searchlabel.setScaledContents(False) searchbox = QLineEdit(self) searchbox.setAttribute(Qt.WA_MacShowFocusRect, 0) toplayout = QHBoxLayout() - toplayout.addWidget(slicename, 0, Qt.AlignLeft) + toplayout.addWidget(self.slicename, 0, Qt.AlignLeft) toplayout.addStretch() toplayout.addWidget(searchlabel, 0, Qt.AlignRight) toplayout.addWidget(searchbox, 0, Qt.AlignRight) @@ -329,6 +329,7 @@ class SliceWidget(QWidget): def refreshFinished(self): self.setStatus("Slice data updated.", timeout=5000) self.updateView() + self.parent().signalAll("rspecUpdated") def readSliceRSpec(self): rspec_file = config.getSliceRSpecFile() @@ -397,7 +398,6 @@ class SliceWidget(QWidget): self.disconnect(self.process, SIGNAL('finished()'), self.submitFinished) self.connect(self.process, SIGNAL('finished()'), self.refreshFinished) - self.connect(self.process, SIGNAL('finished()'), self.parent().rspecUpdated) self.process.getRSpecFromSM() self.setStatus("Updating slice data. This may take some time...") @@ -442,6 +442,9 @@ class SliceWidget(QWidget): self.nodeView.expandAll() self.nodeView.resizeColumnToContents(1) + def updateSliceName(self): + self.slicename.setText("Slice : %s" % (config.getSlice() or "None")) + class MainScreen(SfaScreen): def __init__(self, parent): @@ -449,3 +452,8 @@ class MainScreen(SfaScreen): slice = SliceWidget(self) self.init(slice, "Main Window", "OneLab Federation GUI") + + def configurationChanged(self): + self.widget.updateSliceName() + self.widget.updateView() + diff --git a/sface/screens/rspecscreen.py b/sface/screens/rspecscreen.py index fcaa2bf..37bbc2f 100644 --- a/sface/screens/rspecscreen.py +++ b/sface/screens/rspecscreen.py @@ -165,7 +165,10 @@ class DomItem: class RSpecWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) + + self.view = RSpecView(self) self.updateView() + def updateView(self): document = QDomDocument("RSpec") diff --git a/sface/screens/sfascreen.py b/sface/screens/sfascreen.py index 1b2e12c..e3c584a 100644 --- a/sface/screens/sfascreen.py +++ b/sface/screens/sfascreen.py @@ -4,11 +4,17 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * class SfaScreen(QWidget): + instances = [] + def __init__(self, parent): + SfaScreen.instances.append(self) QWidget.__init__(self, parent) self.mainwin = parent self.name = self.title = self.widget = None + def __del__(self): + SfaScreen.instances.remove(self) + def init(self, widget, name, title): if self.widget: sys.stderr.write("Screen is already initialized\n") @@ -31,5 +37,12 @@ class SfaScreen(QWidget): def setStatus(self, msg, timeout): self.mainwin.setStatus(msg, timeout) + def signalAll(self, action): + for i in SfaScreen.instances: + getattr(i, action)() + def rspecUpdated(self): pass + + def configurationChanged(self): + pass -- 2.43.0 From 4d584eb55a030137a18fd1cf2761fc40698745ba Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 12:44:04 +0200 Subject: [PATCH 03/16] simplify string operations. expand only first level in rspecscreen --- sface/screens/rspecscreen.py | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/sface/screens/rspecscreen.py b/sface/screens/rspecscreen.py index 772f4cb..e7edb47 100644 --- a/sface/screens/rspecscreen.py +++ b/sface/screens/rspecscreen.py @@ -30,8 +30,7 @@ class DomModel(QAbstractItemModel): childList = document.childNodes() for i in range(childList.count()): currElem = childList.item(i) - if (currElem.nodeType() == - QDomNode.ProcessingInstructionNode): + if (currElem.nodeType() == QDomNode.ProcessingInstructionNode): document.removeChild(currElem) break self.rootItem = DomItem(document, 0); @@ -50,16 +49,9 @@ class DomModel(QAbstractItemModel): qslist = QStringList() for i in range(attributeMap.count()): attr = attributeMap.item(i) - elem = (attr.nodeName() - .append(QString('="')) - .append(attr.nodeValue()) - .append(QString('"'))) + elem = '%s="%s"' % (attr.nodeName(), attr.nodeValue()) qslist.append(elem) - return (QString('<'). - append(node.nodeName()). - append(' '). - append(qslist.join(' ')). - append('>')) + return QString("<%s %s>" % (node.nodeName(), qslist.join(' '))) elif node.nodeType() == QDomNode.AttributeNode: return QString('Whozat?!') elif node.nodeType() == QDomNode.TextNode: @@ -95,14 +87,13 @@ class DomModel(QAbstractItemModel): def flags(self, index): if not index.isValid(): return Qt.ItemIsEnabled - # does this `|` thing hold? return Qt.ItemIsEnabled | Qt.ItemIsSelectable def headerData(self, section, orientation, role): return QVariant() - def index(self, row, column, parent): - if not parent.isValid(): + def index(self, row, column, parent=None): + if not parent or not parent.isValid(): parentItem = self.rootItem else: parentItem = parent.internalPointer() @@ -133,16 +124,14 @@ class DomModel(QAbstractItemModel): return parentItem.node().childNodes().count() def columnCount(self, parent): - # just one column - # we'll print tag name (and attributes) - # or the tag content + # just one column we'll print tag name (and attributes) or the + # tag content return 1 class DomItem: - # wrapper around PyQt4.QtXml.QDomNode - # it keeps an hash of childrens for - # performance reasons + # wrapper around PyQt4.QtXml.QDomNode it keeps an hash of + # childrens for performance reasons def __init__(self, node, row, parent = 0): # node is of type PyQt4.QtXml.QDomNode @@ -171,7 +160,6 @@ class DomItem: return self.rowNumber - class RSpecWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) @@ -179,7 +167,6 @@ class RSpecWidget(QWidget): self.view = RSpecView(self) self.updateView() - def updateView(self): document = QDomDocument("RSpec") rspec_file = config.getSliceRSpecFile() @@ -191,8 +178,7 @@ class RSpecWidget(QWidget): view = RSpecView(self) view.setModel(model) -# too slow! -# view.expandAll() + view.expand(model.index(0, 0)) #expand first level only layout = QVBoxLayout() layout.addWidget(view) -- 2.43.0 From ca78de771ab13fa96d56305cdeafb4ab68ba8e88 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 12:44:41 +0200 Subject: [PATCH 04/16] run in background --- sface.bin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sface.bin b/sface.bin index abc484c..5e7eb2e 100755 --- a/sface.bin +++ b/sface.bin @@ -7,4 +7,4 @@ PYTHONPATH=/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/pytho PYTHONPATH=$HOME/stree/sfa/trunk:$PYTHONPATH export PYTHONPATH -exec python sface.py "$@" +exec python sface.py "$@" & -- 2.43.0 From 654a48a3138958f039b4ab8b214fe7c1ab2235d8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 12:50:27 +0200 Subject: [PATCH 05/16] update rspecview properly --- sface/screens/rspecscreen.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/sface/screens/rspecscreen.py b/sface/screens/rspecscreen.py index e7edb47..75be23a 100644 --- a/sface/screens/rspecscreen.py +++ b/sface/screens/rspecscreen.py @@ -164,25 +164,32 @@ class RSpecWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) + self.document = None + self.model = None + self.view = RSpecView(self) + layout = QVBoxLayout() + layout.addWidget(self.view) + self.setLayout(layout) + self.updateView() def updateView(self): - document = QDomDocument("RSpec") + del self.document + del self.model + self.document = None + self.model = None + rspec_file = config.getSliceRSpecFile() if not os.path.exists(rspec_file): return - document.setContent(open(rspec_file,'r').read()) - model = DomModel(document, self) + self.document = QDomDocument("RSpec") + self.document.setContent(open(rspec_file,'r').read()) + self.model = DomModel(self.document, self) - view = RSpecView(self) - view.setModel(model) - view.expand(model.index(0, 0)) #expand first level only - - layout = QVBoxLayout() - layout.addWidget(view) - self.setLayout(layout) + self.view.setModel(self.model) + self.view.expand(self.model.index(0, 0)) #expand first level only class RSpecScreen(SfaScreen): @@ -194,3 +201,6 @@ class RSpecScreen(SfaScreen): def rspecUpdated(self): self.widget.updateView() + + def configurationChanged(self): + self.widget.updateView() -- 2.43.0 From 4afda5e76d8fabd8615ca0f18302337edeae1d36 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 12:57:16 +0200 Subject: [PATCH 06/16] a little better navigation --- sface/mainwindow.py | 48 +++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/sface/mainwindow.py b/sface/mainwindow.py index 689707f..140a6ff 100644 --- a/sface/mainwindow.py +++ b/sface/mainwindow.py @@ -17,26 +17,31 @@ class Nav(QWidget): QWidget.__init__(self, parent) self.title = QLabel("", self) - self.link1 = QLabel("", self) - self.link1.setAlignment(Qt.AlignRight) + self.main = QLabel("", self) + self.main.setAlignment(Qt.AlignRight) - self.link2 = QLabel("", self) - self.link2.setAlignment(Qt.AlignRight) + self.rspec = QLabel("", self) + self.rspec.setAlignment(Qt.AlignRight) + + self.config = QLabel("", self) + self.config.setAlignment(Qt.AlignRight) hlayout = QHBoxLayout() hlayout.addWidget(self.title) hlayout.addStretch() hlayout.addWidget(QLabel("Go to: ", self)) - hlayout.addWidget(self.link1) - hlayout.addWidget(self.link2) + hlayout.addWidget(self.main) + hlayout.addWidget(self.rspec) + hlayout.addWidget(self.config) self.setLayout(hlayout) def setTitle(self, title): self.title.setText(title) - def setLinks(self, link1, link2): - self.link1.setText(link1) - self.link2.setText(link2) + def setLinks(self, main, rspec, config): + self.main.setText(main) + self.rspec.setText(rspec) + self.config.setText(config) class Status(QLabel): @@ -82,7 +87,9 @@ class MainWindow(QWidget): self.nav = Nav(self) self.nav.setTitle(self.main_screen.getTitleText()) - self.nav.setLinks(self.rspec_screen.getLinkText(), self.config_screen.getLinkText()) + self.nav.setLinks(self.main_screen.getLinkText(), + self.rspec_screen.getLinkText(), + self.config_screen.getLinkText()) self.status = Status(self) self.log = QLabel("Show Log", self) @@ -99,10 +106,10 @@ class MainWindow(QWidget): self.setLayout(layout) self.resize(800, 600) - self.connect(self.nav.link1, SIGNAL('linkActivated(QString)'), - self.animateToScreen) - self.connect(self.nav.link2, SIGNAL('linkActivated(QString)'), - self.animateToScreen) + for link in (self.nav.main, self.nav.rspec, self.nav.config): + self.connect(link, SIGNAL('linkActivated(QString)'), + self.animateToScreen) + self.connect(self.log, SIGNAL('linkActivated(QString)'), self.showLogWindow) @@ -125,9 +132,15 @@ class MainWindow(QWidget): self.next_screen = self.main_screen elif link == self.rspec_screen.name: self.next_screen = self.rspec_screen - + + curr_screen = self.screens.currentWidget() + + if self.next_screen == curr_screen: + self.setStatus("Already showing %s" % curr_screen.getTitleText(), timeout=1000) + return + pixmap = QPixmap(self.screens.size()) - self.screens.currentWidget().render(pixmap) + curr_screen.render(pixmap) self.screens.setCurrentWidget(self.pix) self.pix.setPixmap(pixmap) @@ -148,17 +161,14 @@ class MainWindow(QWidget): def toConfigScreen(self): self.screens.setCurrentWidget(self.config_screen) - self.nav.setLinks(self.main_screen.getLinkText(), self.rspec_screen.getLinkText()) self.nav.setTitle(self.config_screen.getTitleText()) def toMainScreen(self): self.screens.setCurrentWidget(self.main_screen) - self.nav.setLinks(self.rspec_screen.getLinkText(), self.config_screen.getLinkText()) self.nav.setTitle(self.main_screen.getTitleText()) def toRSpecScreen(self): self.screens.setCurrentWidget(self.rspec_screen) - self.nav.setLinks(self.main_screen.getLinkText(), self.config_screen.getLinkText()) self.nav.setTitle(self.rspec_screen.getTitleText()) def setStatus(self, msg, timeout): -- 2.43.0 From 56eeddf9de82bfb79a5cced82e448809eefe9352 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 14:01:58 +0200 Subject: [PATCH 07/16] it _will_ take a long time to interact with sfa --- sface/screens/mainscreen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sface/screens/mainscreen.py b/sface/screens/mainscreen.py index 5507294..a47ba3c 100644 --- a/sface/screens/mainscreen.py +++ b/sface/screens/mainscreen.py @@ -384,7 +384,7 @@ class SliceWidget(QWidget): self.connect(self.process, SIGNAL('finished()'), self.submitFinished) self.process.applyRSpec(rspec) - self.setStatus("Sending slice data (RSpec). This may take some time...") + self.setStatus("Sending slice data (RSpec). This will take some time...") def refresh(self): @@ -400,7 +400,7 @@ class SliceWidget(QWidget): self.connect(self.process, SIGNAL('finished()'), self.refreshFinished) self.process.getRSpecFromSM() - self.setStatus("Updating slice data. This may take some time...") + self.setStatus("Updating slice data. This will take some time...") def updateView(self): global already_in_nodes -- 2.43.0 From 6aa68f810c351faa9107b915c2422c1c55cac0ac Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 15:42:05 +0200 Subject: [PATCH 08/16] use a simple QObject and StringIO for log window --- sface.py | 2 +- sface/logwindow.py | 33 +++++++++++++++++++-------------- sface/mainwindow.py | 2 +- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/sface.py b/sface.py index 256c8be..a66d739 100644 --- a/sface.py +++ b/sface.py @@ -37,7 +37,7 @@ QLabel { win = MainWindow() -# win.redirectOutputToLog() + win.redirectOutputToLog() win.setWindowTitle("Sface: SFA Interface") win.show() win.raise_() diff --git a/sface/logwindow.py b/sface/logwindow.py index 3368185..a77eab2 100644 --- a/sface/logwindow.py +++ b/sface/logwindow.py @@ -1,10 +1,23 @@ import sys +from cStringIO import StringIO from PyQt4.QtCore import * from PyQt4.QtGui import * from sface.config import config +class LogIO(QObject): + def __init__(self, parent, old_stdout): + QObject.__init__(self, parent) + self.io = StringIO() + self.old_stdout = old_stdout + + def write(self, txt): + self.io.write(txt) + self.parent().update() + + def getText(self): + return self.io.getvalue() class LogWindow(QDialog): def __init__(self, parent=None): @@ -16,25 +29,17 @@ class LogWindow(QDialog): layout.addWidget(self.text) self.setLayout(layout) - # To Baris: from the doc, - # QIODevice is abstract and can not be instantiated - # I am putting QObject just to let the GUI start. - #self.io = QIODevice(self) - self.io = QObject() - self.connect(self.io, SIGNAL('canReadLine()'), self.appendLine) + self.logio = LogIO(self, sys.stdout) def redirectOutput(self): - print "Redirecting all output to Log Window. Please open the log window to see the output" + print "\n\nRedirecting all output to Log Window. Please open the log window to see the output\n" self.old_stdout = sys.stdout self.old_stderr = sys.stderr - sys.stdout = self.io - sys.stderr = self.io - - self.old_stdout.write("test") - self.text.append("io Test\n") + sys.stdout = self.logio + sys.stderr = self.logio - def appendLine(self): - self.text.append(self.io.readLine()) + def update(self): + self.text.setText(self.logio.getText()) diff --git a/sface/mainwindow.py b/sface/mainwindow.py index 140a6ff..b04e638 100644 --- a/sface/mainwindow.py +++ b/sface/mainwindow.py @@ -118,7 +118,7 @@ class MainWindow(QWidget): def showLogWindow(self, link): self.logWindow.show() - self.logWindow.resize(500, 500) + self.logWindow.resize(800, 400) self.logWindow.raise_() self.logWindow.activateWindow() -- 2.43.0 From 32eb5fc79ad9745b7b1c3da1c96f442b0feb965c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 15:47:06 +0200 Subject: [PATCH 09/16] update todo --- TODO | 1 - 1 file changed, 1 deletion(-) diff --git a/TODO b/TODO index b189379..d5ffddd 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,6 @@ * Better error handling in SfiProcess * Support for private keys with passwords -* Log window for SfiProcess * XML syntax highlighting * XML closing tags (low priority) * XML modifiable by the user \ No newline at end of file -- 2.43.0 From dd3e0cf249a536798fcbb3aaf788dca1d674ab26 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 17:29:36 +0200 Subject: [PATCH 10/16] show node in rspecwindow when it's selected --- sface/mainwindow.py | 36 ++++++------- .../rspecscreen.py => rspecwindow.py} | 54 +++++++++++++------ sface/screens/mainscreen.py | 20 +++++-- 3 files changed, 70 insertions(+), 40 deletions(-) rename sface/{screens/rspecscreen.py => rspecwindow.py} (84%) diff --git a/sface/mainwindow.py b/sface/mainwindow.py index b04e638..c1c80b6 100644 --- a/sface/mainwindow.py +++ b/sface/mainwindow.py @@ -8,9 +8,9 @@ from PyQt4.QtGui import * from sface.config import config from sface.logwindow import LogWindow +from sface.rspecwindow import RSpecWindow from sface.screens.configscreen import ConfigScreen from sface.screens.mainscreen import MainScreen -from sface.screens.rspecscreen import RSpecScreen class Nav(QWidget): def __init__(self, parent=None): @@ -20,9 +20,6 @@ class Nav(QWidget): self.main = QLabel("", self) self.main.setAlignment(Qt.AlignRight) - self.rspec = QLabel("", self) - self.rspec.setAlignment(Qt.AlignRight) - self.config = QLabel("", self) self.config.setAlignment(Qt.AlignRight) @@ -31,16 +28,14 @@ class Nav(QWidget): hlayout.addStretch() hlayout.addWidget(QLabel("Go to: ", self)) hlayout.addWidget(self.main) - hlayout.addWidget(self.rspec) hlayout.addWidget(self.config) self.setLayout(hlayout) def setTitle(self, title): self.title.setText(title) - def setLinks(self, main, rspec, config): + def setLinks(self, main, config): self.main.setText(main) - self.rspec.setText(rspec) self.config.setText(config) @@ -72,31 +67,31 @@ class MainWindow(QWidget): QWidget.__init__(self, parent) self.logWindow = LogWindow(self) + self.rspecWindow = RSpecWindow(self) self.pix = QLabel(self) self.config_screen = ConfigScreen(self) self.main_screen = MainScreen(self) - self.rspec_screen = RSpecScreen(self) self.screens = QStackedWidget(self) self.screens.addWidget(self.main_screen) self.screens.addWidget(self.config_screen) - self.screens.addWidget(self.rspec_screen) self.screens.addWidget(self.pix) self.next_screen = None self.nav = Nav(self) self.nav.setTitle(self.main_screen.getTitleText()) self.nav.setLinks(self.main_screen.getLinkText(), - self.rspec_screen.getLinkText(), self.config_screen.getLinkText()) self.status = Status(self) self.log = QLabel("Show Log", self) + self.rspec = QLabel("Show RSpec", self) hlayout = QHBoxLayout() hlayout.addWidget(self.status) hlayout.addStretch() + hlayout.addWidget(self.rspec) hlayout.addWidget(self.log) layout = QVBoxLayout() @@ -106,12 +101,14 @@ class MainWindow(QWidget): self.setLayout(layout) self.resize(800, 600) - for link in (self.nav.main, self.nav.rspec, self.nav.config): + for link in (self.nav.main, self.nav.config): self.connect(link, SIGNAL('linkActivated(QString)'), self.animateToScreen) self.connect(self.log, SIGNAL('linkActivated(QString)'), self.showLogWindow) + self.connect(self.rspec, SIGNAL('linkActivated(QString)'), + self.showRSpecWindow) def redirectOutputToLog(self): self.logWindow.redirectOutput() @@ -122,6 +119,13 @@ class MainWindow(QWidget): self.logWindow.raise_() self.logWindow.activateWindow() + def showRSpecWindow(self, link): + self.rspecWindow.show() + self.rspecWindow.resize(500, 640) + self.rspecWindow.raise_() + self.rspecWindow.activateWindow() + + def animatePixmap(self, y): self.pix.move(0, y) @@ -130,8 +134,6 @@ class MainWindow(QWidget): self.next_screen = self.config_screen elif link == self.main_screen.name: self.next_screen = self.main_screen - elif link == self.rspec_screen.name: - self.next_screen = self.rspec_screen curr_screen = self.screens.currentWidget() @@ -156,8 +158,6 @@ class MainWindow(QWidget): self.toConfigScreen() elif self.next_screen == self.main_screen: self.toMainScreen() - elif self.next_screen == self.rspec_screen: - self.toRSpecScreen() def toConfigScreen(self): self.screens.setCurrentWidget(self.config_screen) @@ -167,10 +167,8 @@ class MainWindow(QWidget): self.screens.setCurrentWidget(self.main_screen) self.nav.setTitle(self.main_screen.getTitleText()) - def toRSpecScreen(self): - self.screens.setCurrentWidget(self.rspec_screen) - self.nav.setTitle(self.rspec_screen.getTitleText()) - def setStatus(self, msg, timeout): self.status.set(msg, timeout) + def nodeSelectionChanged(self, hostname): + self.rspecWindow.showNode(hostname) diff --git a/sface/screens/rspecscreen.py b/sface/rspecwindow.py similarity index 84% rename from sface/screens/rspecscreen.py rename to sface/rspecwindow.py index 75be23a..17bef6a 100644 --- a/sface/screens/rspecscreen.py +++ b/sface/rspecwindow.py @@ -20,6 +20,32 @@ class RSpecView(QTreeView): self.setAttribute(Qt.WA_MacShowFocusRect, 0) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + def expandMatchingText(self, txt): + self.collapseAll() + self.expandToDepth(0) + + def recursiveExpand(index): + parent = index.parent() + if parent and parent.isValid(): + recursiveExpand(parent) + self.expand(index) + + def search(index): + if index.data().toString() == txt: + recursiveExpand(index) + self.scrollTo(index, self.PositionAtCenter) + + rows = model.rowCount(index) + for r in range(rows): + child_index = index.child(r, 0) + search(child_index) + + model = self.model() + root_rows = model.rowCount() + for r in range(root_rows): + index = model.index(r, 0) + search(index) + class DomModel(QAbstractItemModel): def __init__(self, document, parent = 0): @@ -115,8 +141,8 @@ class DomModel(QAbstractItemModel): return QModelIndex() return self.createIndex(parentItem.row(), 0, parentItem) - def rowCount(self, parent): - if not parent.isValid(): + def rowCount(self, parent=None): + if not parent or not parent.isValid(): parentItem = self.rootItem else: parentItem = parent.internalPointer() @@ -160,9 +186,10 @@ class DomItem: return self.rowNumber -class RSpecWidget(QWidget): +class RSpecWindow(QDialog): def __init__(self, parent=None): - QWidget.__init__(self, parent) + QDialog.__init__(self, parent) + self.setWindowTitle("RSPec View") self.document = None self.model = None @@ -173,7 +200,14 @@ class RSpecWidget(QWidget): self.setLayout(layout) self.updateView() + + def show(self): + self.updateView() + QDialog.show(self) + def showNode(self, hostname): + self.view.expandMatchingText(hostname) + def updateView(self): del self.document del self.model @@ -192,15 +226,3 @@ class RSpecWidget(QWidget): self.view.expand(self.model.index(0, 0)) #expand first level only -class RSpecScreen(SfaScreen): - def __init__(self, parent): - SfaScreen.__init__(self, parent) - - widget = RSpecWidget(self) - self.init(widget, "RSpec Window", "RSPec View") - - def rspecUpdated(self): - self.widget.updateView() - - def configurationChanged(self): - self.widget.updateView() diff --git a/sface/screens/mainscreen.py b/sface/screens/mainscreen.py index a47ba3c..d56bca5 100644 --- a/sface/screens/mainscreen.py +++ b/sface/screens/mainscreen.py @@ -46,6 +46,15 @@ class NodeView(QTreeView): else: model.setData(status_index, QString(node_status['out'])) model.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), hostname_index, hostname_index) + + def mouseReleaseEvent(self, event): + index = self.currentIndex() + model = index.model() + hostname_index = model.index(index.row(), 1, index.parent()) + hostname_data = hostname_index.data().toString() + + self.emit(SIGNAL('hostnameClicked(QString)'), hostname_data) + class NodeNameDelegate(QStyledItemDelegate): @@ -314,14 +323,11 @@ class SliceWidget(QWidget): self.connect(refresh, SIGNAL('clicked()'), self.refresh) self.connect(submit, SIGNAL('clicked()'), self.submit) self.connect(searchbox, SIGNAL('textChanged(QString)'), self.filter) - self.connect(self.process, SIGNAL('readyReadStandardOutput()'), self.processOutputReady) - self.connect(self.process, SIGNAL('readyReadStandardError()'), self.processOutputReady) + self.connect(self.nodeView, SIGNAL('hostnameClicked(QString)'), + self.nodeSelectionChanged) self.updateView() - def processOutputReady(self): - self.parent().logWindow.setText(self.process.readOutput()) - def submitFinished(self): self.setStatus("Slice data submitted.") QTimer.singleShot(1000, self.refresh) @@ -445,6 +451,8 @@ class SliceWidget(QWidget): def updateSliceName(self): self.slicename.setText("Slice : %s" % (config.getSlice() or "None")) + def nodeSelectionChanged(self, hostname): + self.parent().nodeSelectionChanged(hostname) class MainScreen(SfaScreen): def __init__(self, parent): @@ -457,3 +465,5 @@ class MainScreen(SfaScreen): self.widget.updateSliceName() self.widget.updateView() + def nodeSelectionChanged(self, hostname): + self.mainwin.nodeSelectionChanged(hostname) -- 2.43.0 From 875c4f3aa289cba9ed73de07e4e1fab1770ae9ec Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 18:02:18 +0200 Subject: [PATCH 11/16] use currentChanged slot instead of mouseReleaseEvent --- sface/mainwindow.py | 1 + sface/screens/mainscreen.py | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sface/mainwindow.py b/sface/mainwindow.py index c1c80b6..fde8ad8 100644 --- a/sface/mainwindow.py +++ b/sface/mainwindow.py @@ -62,6 +62,7 @@ class Status(QLabel): self.setText("") QTimer.singleShot(1500, self.sliceUpdateDate) + class MainWindow(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) diff --git a/sface/screens/mainscreen.py b/sface/screens/mainscreen.py index d56bca5..96b5728 100644 --- a/sface/screens/mainscreen.py +++ b/sface/screens/mainscreen.py @@ -47,12 +47,10 @@ class NodeView(QTreeView): model.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), hostname_index, hostname_index) - def mouseReleaseEvent(self, event): - index = self.currentIndex() - model = index.model() - hostname_index = model.index(index.row(), 1, index.parent()) + def currentChanged(self, current, previous): + model = current.model() + hostname_index = model.index(current.row(), 1, current.parent()) hostname_data = hostname_index.data().toString() - self.emit(SIGNAL('hostnameClicked(QString)'), hostname_data) -- 2.43.0 From a0f7de62e4b4bd1fc2dccf7fa30b07ca1de0ef5b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 22:08:18 +0200 Subject: [PATCH 12/16] fix for empty sfi_config --- sface/screens/configscreen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sface/screens/configscreen.py b/sface/screens/configscreen.py index 3f2440e..80105a4 100644 --- a/sface/screens/configscreen.py +++ b/sface/screens/configscreen.py @@ -19,7 +19,7 @@ class ConfigWidget(QWidget): if config.is_true(config.get(field)): edit.setCheckState(Qt.Checked) else: - edit=QLineEdit(config.get(field), self) + edit=QLineEdit(config.get(field) or "", self) edit.setAttribute(Qt.WA_MacShowFocusRect, 0) setattr(self,field,edit) -- 2.43.0 From 743e1ca6dc5c9d1aa98197e4fb5dfe40d13fb513 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Wed, 15 Sep 2010 22:14:22 +0200 Subject: [PATCH 13/16] define model before nested functions --- sface/rspecwindow.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sface/rspecwindow.py b/sface/rspecwindow.py index 17bef6a..45c2508 100644 --- a/sface/rspecwindow.py +++ b/sface/rspecwindow.py @@ -24,6 +24,8 @@ class RSpecView(QTreeView): self.collapseAll() self.expandToDepth(0) + model = self.model() + def recursiveExpand(index): parent = index.parent() if parent and parent.isValid(): @@ -40,7 +42,6 @@ class RSpecView(QTreeView): child_index = index.child(r, 0) search(child_index) - model = self.model() root_rows = model.rowCount() for r in range(root_rows): index = model.index(r, 0) -- 2.43.0 From 79c80b005f7b28c8a357f7b99a4ac11f3a55e3f7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Thu, 16 Sep 2010 00:29:04 +0200 Subject: [PATCH 14/16] update for win --- INSTALL | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/INSTALL b/INSTALL index 80f6901..2c77fe8 100644 --- a/INSTALL +++ b/INSTALL @@ -1,15 +1,27 @@ -(1) Install SFA command line tools (sfi.py): http://svn.planet-lab.org/wiki/SFAInstallationGuide +(1) Install SFA command line tools (sfi.py): + +Please find the installation instructions at http://svn.planet-lab.org/wiki/SFAInstallationGuide + + (2) Install PyQt4 For Linux: +---------- You can use the package manager to install PyQt4 For Mac: +-------- You'll need to download and install Qt, PyQt and Sip from the following links: http://qt.nokia.com/downloads http://www.riverbankcomputing.co.uk/software/sip/download -http://www.riverbankcomputing.co.uk/software/pyqt/download \ No newline at end of file +http://www.riverbankcomputing.co.uk/software/pyqt/download + +For Windows: +------------ +Install ActivePython from ActiveState: http://www.activestate.com/activepython/downloads +Install PyQt4 binaries: http://www.riverbankcomputing.co.uk/software/pyqt/download + -- 2.43.0 From 672e6b28e8add32a359a41dcf954bad6b17e2991 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Thu, 16 Sep 2010 00:47:10 +0200 Subject: [PATCH 15/16] update rspec view on change --- sface/screens/mainscreen.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sface/screens/mainscreen.py b/sface/screens/mainscreen.py index 96b5728..6ffd7e0 100644 --- a/sface/screens/mainscreen.py +++ b/sface/screens/mainscreen.py @@ -459,9 +459,13 @@ class MainScreen(SfaScreen): slice = SliceWidget(self) self.init(slice, "Main Window", "OneLab Federation GUI") + def rspecUpdated(self): + self.mainwin.rspecWindow.updateView() + def configurationChanged(self): self.widget.updateSliceName() self.widget.updateView() + self.mainwin.rspecWindow.updateView() def nodeSelectionChanged(self, hostname): self.mainwin.nodeSelectionChanged(hostname) -- 2.43.0 From d8f6e859b7f01a688b631dc5a67a0c43b0f83341 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bar=C4=B1=C5=9F=20Metin?= Date: Fri, 17 Sep 2010 10:24:01 +0200 Subject: [PATCH 16/16] expand node in rpsecwindow only if it's visible --- sface/mainwindow.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sface/mainwindow.py b/sface/mainwindow.py index fde8ad8..fa19a43 100644 --- a/sface/mainwindow.py +++ b/sface/mainwindow.py @@ -172,4 +172,5 @@ class MainWindow(QWidget): self.status.set(msg, timeout) def nodeSelectionChanged(self, hostname): - self.rspecWindow.showNode(hostname) + if self.rspecWindow.isVisible(): + self.rspecWindow.showNode(hostname) -- 2.43.0