# -*- coding: utf-8 -*-
# **************************************************************************
# *
# * Authors: Pablo Conesa [1]
# *
# * [1] Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
# *
# * This program is free software: you can redistribute it and/or modify
# * it under the terms of the GNU General Public License as published by
# * the Free Software Foundation, either version 3 of the License, or
# * (at your option) any later version.
# *
# * This program is distributed in the hope that it will be useful,
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# * GNU General Public License for more details.
# *
# * You should have received a copy of the GNU General Public License
# * along with this program. If not, see <https://www.gnu.org/licenses/>.
# *
# * All comments concerning this program package may be sent to the
# * e-mail address 'scipion@cnb.csic.es'
# *
# **************************************************************************
""" This modules hosts gui code to visualize steps"""
import json
import tkinter as tk
import pyworkflow.protocol as pwprot
import pyworkflow.gui as pwgui
import pyworkflow.utils as pwutils
from pyworkflow import TK
from pyworkflow.utils import Icon
[docs]class StepsTreeProvider(pwgui.tree.TreeProvider):
"""Create the tree elements for a Protocol run"""
def __init__(self, stepsList):
for i, s in enumerate(stepsList):
if not s._index:
s._index = i + 1
self._stepsList = stepsList
self.getColumns = lambda: [('Index', 50), ('Step', 200), ('Status', 150),
('Time', 150), ('Class', 100)]
self._parentDict = {}
[docs] def getObjects(self):
return self._stepsList
[docs] @staticmethod
def getObjectInfo(obj):
info = {'key': obj._index,
'values': (str(obj), obj.getStatus(), pwutils.prettyDelta(obj.getElapsedTime()),
obj.getClassName())}
return info
[docs] @staticmethod
def getObjectPreview(obj: pwprot.Step):
args = json.loads(obj.argsStr.get())
msg = "*Prerequisites*: %s \n" % str(obj._prerequisites)
msg += ("*Arguments*:\n")
for arg in args:
msg += " %s\n" % arg
msg += "*Needs GPU*: %s" % obj.needsGPU()
if hasattr(obj, 'resultFiles'):
results = json.loads(obj.resultFiles.get())
if len(results):
msg += "\n*Result files:* " + '\n '.join(results)
return None, msg
[docs]class StepsWindow(pwgui.browser.BrowserWindow):
def __init__(self, title, parentWindow, protocol, **args):
self._protocol = protocol
provider = StepsTreeProvider(protocol.loadSteps())
pwgui.browser.BrowserWindow.__init__(self, title, parentWindow,
weight=False, **args)
# Create buttons toolbar
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(1, weight=1)
self.fillToolBar()
# Create and set browser
browser = pwgui.browser.ObjectBrowser(self.root, provider,
showPreviewTop=False)
self.setBrowser(browser, row=1, column=0)
def _setStepStatus(self, status):
item = self.browser._lastSelected
if item is not None:
objId = item.getObjId()
self._protocol._updateSteps(lambda step: step.setStatus(status), where="id='%s'" % objId)
item.setStatus(status)
self.browser.tree.update()
def _resetStep(self, e=None):
self._setStepStatus(pwprot.STATUS_NEW)
def _finishStep(self, e=None):
self._setStepStatus(pwprot.STATUS_FINISHED)
# noinspection PyUnusedLocal
def _showTree(self, e=None):
g = self._protocol.getStepsGraph()
w = pwgui.Window("Protocol steps", self, minsize=(800, 600))
root = w.root
canvas = pwgui.Canvas(root, width=600, height=500,
tooltipCallback=self._stepTooltip,)
canvas.grid(row=0, column=0, sticky='nsew')
canvas.drawGraph(g, pwgui.LevelTreeLayout())
w.show()
def _stepTooltip(self, tw, item):
""" Create the contents of the tooltip to be displayed
for the given step.
Params:
tw: a tk.TopLevel instance (ToolTipWindow)
item: the selected step.
"""
if not hasattr(item.node, 'step'):
return
step = item.node.step
tm = str(step.funcName)
if not hasattr(tw, 'tooltipText'):
frame = tk.Frame(tw)
frame.grid(row=0, column=0)
tw.tooltipText = pwgui.dialog.createMessageBody(
frame, tm, None, textPad=0, textBg=pwutils.Color.ALT_COLOR_2)
tw.tooltipText.config(bd=1, relief=tk.RAISED)
else:
pwgui.dialog.fillMessageText(tw.tooltipText, tm)