diff --git a/pype/tools/pyblish_pype/app.css b/pype/tools/pyblish_pype/app.css
index b52d9efec8..3a2c05c1f3 100644
--- a/pype/tools/pyblish_pype/app.css
+++ b/pype/tools/pyblish_pype/app.css
@@ -491,3 +491,24 @@ QToolButton {
#TerminalFilerBtn[type="log_critical"]:checked {color: rgb(255, 79, 117);}
#TerminalFilerBtn[type="log_critical"] {color: rgba(255, 79, 117, 63);}
+
+#SuspendLogsBtn {
+ background: #444;
+ border: none;
+ border-top-right-radius: 7px;
+ border-bottom-right-radius: 7px;
+ border-top-left-radius: 0px;
+ border-bottom-left-radius: 0px;
+ font-family: "FontAwesome";
+ font-size: 11pt;
+ color: white;
+ padding: 0px;
+}
+
+#SuspendLogsBtn:hover {
+ background: #333;
+}
+
+#SuspendLogsBtn:disabled {
+ background: #4c4c4c;
+}
diff --git a/pype/tools/pyblish_pype/control.py b/pype/tools/pyblish_pype/control.py
index a078f0146d..5138b5cc4c 100644
--- a/pype/tools/pyblish_pype/control.py
+++ b/pype/tools/pyblish_pype/control.py
@@ -86,7 +86,6 @@ class Controller(QtCore.QObject):
# - passing collectors order disables plugin/instance toggle
self.collectors_order = None
self.collect_state = 0
- self.collected = False
# - passing validators order disables validate button and gives ability
# to know when to stop on validate button press
diff --git a/pype/tools/pyblish_pype/model.py b/pype/tools/pyblish_pype/model.py
index 2c2661b5ec..b9257bfeea 100644
--- a/pype/tools/pyblish_pype/model.py
+++ b/pype/tools/pyblish_pype/model.py
@@ -32,7 +32,6 @@ from .awesome import tags as awesome
import Qt
from Qt import QtCore, QtGui
from six import text_type
-from six.moves import queue
from .vendor import qtawesome
from .constants import PluginStates, InstanceStates, GroupStates, Roles
@@ -49,6 +48,7 @@ TerminalDetailType = QtGui.QStandardItem.UserType + 4
class QAwesomeTextIconFactory:
icons = {}
+
@classmethod
def icon(cls, icon_name):
if icon_name not in cls.icons:
@@ -58,6 +58,7 @@ class QAwesomeTextIconFactory:
class QAwesomeIconFactory:
icons = {}
+
@classmethod
def icon(cls, icon_name, icon_color):
if icon_name not in cls.icons:
@@ -1009,7 +1010,7 @@ class ArtistProxy(QtCore.QAbstractProxyModel):
return QtCore.QModelIndex()
-class TerminalModel(QtGui.QStandardItemModel):
+class TerminalDetailItem(QtGui.QStandardItem):
key_label_record_map = (
("instance", "Instance"),
("msg", "Message"),
@@ -1022,6 +1023,57 @@ class TerminalModel(QtGui.QStandardItemModel):
("msecs", "Millis")
)
+ def __init__(self, record_item):
+ self.record_item = record_item
+ self.msg = None
+ msg = record_item.get("msg")
+ if msg is None:
+ msg = record_item["label"].split("\n")[0]
+
+ super(TerminalDetailItem, self).__init__(msg)
+
+ def data(self, role=QtCore.Qt.DisplayRole):
+ if role in (QtCore.Qt.DisplayRole, QtCore.Qt.EditRole):
+ if self.msg is None:
+ self.msg = self.compute_detail_text(self.record_item)
+ return self.msg
+ return super(TerminalDetailItem, self).data(role)
+
+ def compute_detail_text(self, item_data):
+ if item_data["type"] == "info":
+ return item_data["label"]
+
+ html_text = ""
+ for key, title in self.key_label_record_map:
+ if key not in item_data:
+ continue
+ value = item_data[key]
+ text = (
+ str(value)
+ .replace("<", "<")
+ .replace(">", ">")
+ .replace('\n', '
')
+ .replace(' ', ' ')
+ )
+
+ title_tag = (
+ '{}: '
+ ' color:#fff;\" >{}: '
+ ).format(title)
+
+ html_text += (
+ '
| {} |
'
+ '| {} |
'
+ ).format(title_tag, text)
+
+ html_text = ''.format(
+ html_text
+ )
+ return html_text
+
+
+class TerminalModel(QtGui.QStandardItemModel):
item_icon_name = {
"info": "fa.info",
"record": "fa.circle",
@@ -1053,38 +1105,38 @@ class TerminalModel(QtGui.QStandardItemModel):
self.reset()
def reset(self):
- self.items_to_set_widget = queue.Queue()
self.clear()
- def prepare_records(self, result):
+ def prepare_records(self, result, suspend_logs):
prepared_records = []
instance_name = None
instance = result["instance"]
if instance is not None:
instance_name = instance.data["name"]
- for record in result.get("records") or []:
- if isinstance(record, dict):
- record_item = record
- else:
- record_item = {
- "label": text_type(record.msg),
- "type": "record",
- "levelno": record.levelno,
- "threadName": record.threadName,
- "name": record.name,
- "filename": record.filename,
- "pathname": record.pathname,
- "lineno": record.lineno,
- "msg": text_type(record.msg),
- "msecs": record.msecs,
- "levelname": record.levelname
- }
+ if not suspend_logs:
+ for record in result.get("records") or []:
+ if isinstance(record, dict):
+ record_item = record
+ else:
+ record_item = {
+ "label": text_type(record.msg),
+ "type": "record",
+ "levelno": record.levelno,
+ "threadName": record.threadName,
+ "name": record.name,
+ "filename": record.filename,
+ "pathname": record.pathname,
+ "lineno": record.lineno,
+ "msg": text_type(record.msg),
+ "msecs": record.msecs,
+ "levelname": record.levelname
+ }
- if instance_name is not None:
- record_item["instance"] = instance_name
+ if instance_name is not None:
+ record_item["instance"] = instance_name
- prepared_records.append(record_item)
+ prepared_records.append(record_item)
error = result.get("error")
if error:
@@ -1140,49 +1192,14 @@ class TerminalModel(QtGui.QStandardItemModel):
self.appendRow(top_item)
- detail_text = self.prepare_detail_text(record_item)
- detail_item = QtGui.QStandardItem(detail_text)
+ detail_item = TerminalDetailItem(record_item)
detail_item.setData(TerminalDetailType, Roles.TypeRole)
top_item.appendRow(detail_item)
- self.items_to_set_widget.put(detail_item)
def update_with_result(self, result):
for record in result["records"]:
self.append(record)
- def prepare_detail_text(self, item_data):
- if item_data["type"] == "info":
- return item_data["label"]
-
- html_text = ""
- for key, title in self.key_label_record_map:
- if key not in item_data:
- continue
- value = item_data[key]
- text = (
- str(value)
- .replace("<", "<")
- .replace(">", ">")
- .replace('\n', '
')
- .replace(' ', ' ')
- )
-
- title_tag = (
- '{}: '
- ' color:#fff;\" >{}: '
- ).format(title)
-
- html_text += (
- '| {} |
'
- '| {} |
'
- ).format(title_tag, text)
-
- html_text = ''.format(
- html_text
- )
- return html_text
-
class TerminalProxy(QtCore.QSortFilterProxyModel):
filter_buttons_checks = {
diff --git a/pype/tools/pyblish_pype/view.py b/pype/tools/pyblish_pype/view.py
index ada19bc7d9..03509604bb 100644
--- a/pype/tools/pyblish_pype/view.py
+++ b/pype/tools/pyblish_pype/view.py
@@ -1,5 +1,6 @@
from Qt import QtCore, QtWidgets
from . import model
+from . import widgets
from .constants import Roles
@@ -190,6 +191,23 @@ class TerminalView(QtWidgets.QTreeView):
self.updateGeometry()
self.scrollToBottom()
+ def expand(self, index):
+ """Wrapper to set widget for expanded index."""
+ model = index.model()
+ row_count = model.rowCount(index)
+ is_new = False
+ for child_idx in range(row_count):
+ child_index = model.index(child_idx, index.column(), index)
+ widget = self.indexWidget(child_index)
+ if widget is None:
+ is_new = True
+ msg = child_index.data(QtCore.Qt.DisplayRole)
+ widget = widgets.TerminalDetail(msg)
+ self.setIndexWidget(child_index, widget)
+ super(TerminalView, self).expand(index)
+ if is_new:
+ self.updateGeometries()
+
def resizeEvent(self, event):
super(self.__class__, self).resizeEvent(event)
self.model().layoutChanged.emit()
diff --git a/pype/tools/pyblish_pype/widgets.py b/pype/tools/pyblish_pype/widgets.py
index e81633f7a3..880d4755ad 100644
--- a/pype/tools/pyblish_pype/widgets.py
+++ b/pype/tools/pyblish_pype/widgets.py
@@ -321,11 +321,6 @@ class PerspectiveWidget(QtWidgets.QWidget):
data = {"records": records}
self.terminal_model.reset()
self.terminal_model.update_with_result(data)
- while not self.terminal_model.items_to_set_widget.empty():
- item = self.terminal_model.items_to_set_widget.get()
- widget = TerminalDetail(item.data(QtCore.Qt.DisplayRole))
- index = self.terminal_proxy.mapFromSource(item.index())
- self.terminal_view.setIndexWidget(index, widget)
self.records.button_toggle_text.setText(
"{} ({})".format(self.l_rec, len_records)
diff --git a/pype/tools/pyblish_pype/window.py b/pype/tools/pyblish_pype/window.py
index 5d22e5ac8f..9aa77a57a8 100644
--- a/pype/tools/pyblish_pype/window.py
+++ b/pype/tools/pyblish_pype/window.py
@@ -54,6 +54,7 @@ class Window(QtWidgets.QDialog):
def __init__(self, controller, parent=None):
super(Window, self).__init__(parent=parent)
+ self._suspend_logs = False
# Use plastique style for specific ocations
# TODO set style name via environment variable
low_keys = {
@@ -95,6 +96,18 @@ class Window(QtWidgets.QDialog):
header_tab_terminal = QtWidgets.QRadioButton(header_tab_widget)
header_spacer = QtWidgets.QWidget(header_tab_widget)
+ button_suspend_logs_widget = QtWidgets.QWidget()
+ button_suspend_logs_widget_layout = QtWidgets.QHBoxLayout(
+ button_suspend_logs_widget
+ )
+ button_suspend_logs_widget_layout.setContentsMargins(0, 10, 0, 10)
+ button_suspend_logs = QtWidgets.QPushButton(header_widget)
+ button_suspend_logs.setFixedWidth(7)
+ button_suspend_logs.setSizePolicy(
+ QtWidgets.QSizePolicy.Preferred,
+ QtWidgets.QSizePolicy.Expanding
+ )
+ button_suspend_logs_widget_layout.addWidget(button_suspend_logs)
header_aditional_btns = QtWidgets.QWidget(header_tab_widget)
aditional_btns_layout = QtWidgets.QHBoxLayout(header_aditional_btns)
@@ -109,9 +122,11 @@ class Window(QtWidgets.QDialog):
layout_tab.addWidget(header_tab_artist, 0)
layout_tab.addWidget(header_tab_overview, 0)
layout_tab.addWidget(header_tab_terminal, 0)
+ layout_tab.addWidget(button_suspend_logs_widget, 0)
+
# Compress items to the left
layout_tab.addWidget(header_spacer, 1)
- layout_tab.addWidget(header_aditional_btns, 1)
+ layout_tab.addWidget(header_aditional_btns, 0)
layout = QtWidgets.QHBoxLayout(header_widget)
layout.setContentsMargins(0, 0, 0, 0)
@@ -226,6 +241,10 @@ class Window(QtWidgets.QDialog):
footer_info = QtWidgets.QLabel(footer_widget)
footer_spacer = QtWidgets.QWidget(footer_widget)
+
+ footer_button_stop = QtWidgets.QPushButton(
+ awesome["stop"], footer_widget
+ )
footer_button_reset = QtWidgets.QPushButton(
awesome["refresh"], footer_widget
)
@@ -235,14 +254,12 @@ class Window(QtWidgets.QDialog):
footer_button_play = QtWidgets.QPushButton(
awesome["play"], footer_widget
)
- footer_button_stop = QtWidgets.QPushButton(
- awesome["stop"], footer_widget
- )
layout = QtWidgets.QHBoxLayout()
layout.setContentsMargins(5, 5, 5, 5)
layout.addWidget(footer_info, 0)
layout.addWidget(footer_spacer, 1)
+
layout.addWidget(footer_button_stop, 0)
layout.addWidget(footer_button_reset, 0)
layout.addWidget(footer_button_validate, 0)
@@ -342,10 +359,11 @@ class Window(QtWidgets.QDialog):
"TerminalView": terminal_view,
# Buttons
- "Play": footer_button_play,
- "Validate": footer_button_validate,
- "Reset": footer_button_reset,
+ "SuspendLogsBtn": button_suspend_logs,
"Stop": footer_button_stop,
+ "Reset": footer_button_reset,
+ "Validate": footer_button_validate,
+ "Play": footer_button_play,
# Misc
"HeaderSpacer": header_spacer,
@@ -370,10 +388,11 @@ class Window(QtWidgets.QDialog):
overview_page,
terminal_page,
footer_widget,
- footer_button_play,
- footer_button_validate,
+ button_suspend_logs,
footer_button_stop,
footer_button_reset,
+ footer_button_validate,
+ footer_button_play,
footer_spacer,
closing_placeholder
):
@@ -419,6 +438,7 @@ class Window(QtWidgets.QDialog):
overview_instance_view.toggled.connect(self.on_instance_toggle)
overview_plugin_view.toggled.connect(self.on_plugin_toggle)
+ button_suspend_logs.clicked.connect(self.on_suspend_clicked)
footer_button_stop.clicked.connect(self.on_stop_clicked)
footer_button_reset.clicked.connect(self.on_reset_clicked)
footer_button_validate.clicked.connect(self.on_validate_clicked)
@@ -442,10 +462,11 @@ class Window(QtWidgets.QDialog):
self.terminal_filters_widget = terminal_filters_widget
self.footer_widget = footer_widget
+ self.button_suspend_logs = button_suspend_logs
+ self.footer_button_stop = footer_button_stop
self.footer_button_reset = footer_button_reset
self.footer_button_validate = footer_button_validate
self.footer_button_play = footer_button_play
- self.footer_button_stop = footer_button_stop
self.overview_instance_view = overview_instance_view
self.overview_plugin_view = overview_plugin_view
@@ -612,6 +633,13 @@ class Window(QtWidgets.QDialog):
self.footer_button_play.setEnabled(False)
self.footer_button_stop.setEnabled(False)
+ def on_suspend_clicked(self):
+ self._suspend_logs = not self._suspend_logs
+ if self.state["current_page"] == "terminal":
+ self.on_tab_changed("overview")
+
+ self.tabs["terminal"].setVisible(not self._suspend_logs)
+
def on_comment_entered(self):
"""The user has typed a comment."""
self.controller.context.data["comment"] = self.comment_box.text()
@@ -726,6 +754,8 @@ class Window(QtWidgets.QDialog):
self.on_tab_changed(self.state["current_page"])
self.update_compatibility()
+ self.button_suspend_logs.setEnabled(False)
+
self.footer_button_validate.setEnabled(True)
self.footer_button_reset.setEnabled(True)
self.footer_button_stop.setEnabled(False)
@@ -775,6 +805,12 @@ class Window(QtWidgets.QDialog):
self.footer_widget.setProperty("success", 0)
self.footer_widget.style().polish(self.footer_widget)
+ suspend_log_bool = (
+ self.controller.collect_state == 1
+ and not self.controller.stopped
+ )
+ self.button_suspend_logs.setEnabled(suspend_log_bool)
+
def on_was_skipped(self, plugin):
plugin_item = self.plugin_model.plugin_items[plugin.id]
plugin_item.setData(
@@ -834,17 +870,15 @@ class Window(QtWidgets.QDialog):
if self.tabs["artist"].isChecked():
self.tabs["overview"].toggle()
- result["records"] = self.terminal_model.prepare_records(result)
+ result["records"] = self.terminal_model.prepare_records(
+ result,
+ self._suspend_logs
+ )
plugin_item = self.plugin_model.update_with_result(result)
instance_item = self.instance_model.update_with_result(result)
self.terminal_model.update_with_result(result)
- while not self.terminal_model.items_to_set_widget.empty():
- item = self.terminal_model.items_to_set_widget.get()
- widget = widgets.TerminalDetail(item.data(QtCore.Qt.DisplayRole))
- index = self.terminal_proxy.mapFromSource(item.index())
- self.terminal_view.setIndexWidget(index, widget)
self.update_compatibility()
@@ -897,16 +931,19 @@ class Window(QtWidgets.QDialog):
self.footer_button_validate.setEnabled(False)
self.footer_button_play.setEnabled(False)
+ self.button_suspend_logs.setEnabled(False)
+
util.defer(5, self.controller.validate)
def publish(self):
self.info(self.tr("Preparing publish.."))
-
self.footer_button_stop.setEnabled(True)
self.footer_button_reset.setEnabled(False)
self.footer_button_validate.setEnabled(False)
self.footer_button_play.setEnabled(False)
+ self.button_suspend_logs.setEnabled(False)
+
util.defer(5, self.controller.publish)
def act(self, plugin_item, action):
@@ -938,7 +975,10 @@ class Window(QtWidgets.QDialog):
plugin_item = self.plugin_model.plugin_items[result["plugin"].id]
action_state = plugin_item.data(Roles.PluginActionProgressRole)
action_state |= PluginActionStates.HasFinished
- result["records"] = self.terminal_model.prepare_records(result)
+ result["records"] = self.terminal_model.prepare_records(
+ result,
+ self._suspend_logs
+ )
error = result.get("error")
if error: