Skip to content

Commit

Permalink
Merge pull request #354 from davidlatwe/Qt5
Browse files Browse the repository at this point in the history
Opt-in PySide2 via Qt5.py
  • Loading branch information
davidlatwe authored Feb 9, 2020
2 parents c8fea9c + 4b1cdd6 commit e0a9015
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 101 deletions.
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ MAINTAINER [email protected]
RUN apt-get update && apt-get install -y \
build-essential \
git \
python3-pyqt5 \
python3-pyqt5.qtquick \
python3-pyqt5* \
python3-pip \
python3-nose && \
pip3 install \
Expand Down
32 changes: 14 additions & 18 deletions pyblish_qml/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
import traceback
import threading

# Dependencies
from PyQt5 import QtCore, QtGui, QtQuick, QtTest

# Local libraries
from . import util, compat, control, settings, ipc
from .vendor.Qt5 import QtCore, QtGui, QtQuick

MODULE_DIR = os.path.dirname(__file__)
QML_IMPORT_DIR = os.path.join(MODULE_DIR, "qml")
Expand Down Expand Up @@ -64,17 +62,17 @@ class Application(QtGui.QGuiApplication):
"""

shown = QtCore.pyqtSignal(QtCore.QVariant)
hidden = QtCore.pyqtSignal()
quitted = QtCore.pyqtSignal()
published = QtCore.pyqtSignal()
validated = QtCore.pyqtSignal()
shown = QtCore.Signal("QVariant")
hidden = QtCore.Signal()
quitted = QtCore.Signal()
published = QtCore.Signal()
validated = QtCore.Signal()

targeted = QtCore.pyqtSignal(QtCore.QVariant)
targeted = QtCore.Signal("QVariant")

risen = QtCore.pyqtSignal()
inFocused = QtCore.pyqtSignal()
outFocused = QtCore.pyqtSignal()
risen = QtCore.Signal()
inFocused = QtCore.Signal()
outFocused = QtCore.Signal()

def __init__(self, source, targets=[]):
super(Application, self).__init__(sys.argv)
Expand All @@ -88,7 +86,7 @@ def __init__(self, source, targets=[]):
engine.addImportPath(QML_IMPORT_DIR)

host = ipc.client.Proxy()
controller = control.Controller(host, targets=targets)
controller = control.Controller(host, targets=targets, parent=window)
controller.finished.connect(lambda: window.alert(0))

context = engine.rootContext()
Expand Down Expand Up @@ -176,11 +174,7 @@ def show(self, client_settings=None):
for state in ["ready", "finished"]):
util.timer("ready")

ready = QtTest.QSignalSpy(self.controller.ready)

count = len(ready)
ready.wait(1000)
if len(ready) != count + 1:
if not self.controller.is_ready():
print("Warning: Could not enter ready state")

util.timer_end("ready", "Awaited statemachine for %.2f ms")
Expand Down Expand Up @@ -214,12 +208,14 @@ def inFocus(self):
previous_flags = self.window.flags()
self.window.setFlags(previous_flags |
QtCore.Qt.WindowStaysOnTopHint)
self.window.setFlags(previous_flags)

def outFocus(self):
"""Remove GUI on-top flag"""
previous_flags = self.window.flags()
self.window.setFlags(previous_flags ^
QtCore.Qt.WindowStaysOnTopHint)
self.window.setFlags(previous_flags)

def publish(self):
"""Fire up the publish sequence"""
Expand Down
104 changes: 57 additions & 47 deletions pyblish_qml/control.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,52 @@
import collections

# Dependencies
from PyQt5 import QtCore
import pyblish.logic

# Local libraries
from . import util, models, version, settings
from .vendor.Qt5 import QtCore

qtproperty = util.pyqtConstantProperty
qtproperty = util.qtConstantProperty


class Controller(QtCore.QObject):
"""Communicate with QML"""

# PyQt Signals
info = QtCore.pyqtSignal(str, arguments=["message"])
error = QtCore.pyqtSignal(str, arguments=["message"])
# Signals
info = QtCore.Signal(str, arguments=["message"])
error = QtCore.Signal(str, arguments=["message"])

show = QtCore.pyqtSignal()
hide = QtCore.pyqtSignal()
show = QtCore.Signal()
hide = QtCore.Signal()

firstRun = QtCore.pyqtSignal()
firstRun = QtCore.Signal()

collecting = QtCore.pyqtSignal()
validating = QtCore.pyqtSignal()
extracting = QtCore.pyqtSignal()
integrating = QtCore.pyqtSignal()
collecting = QtCore.Signal()
validating = QtCore.Signal()
extracting = QtCore.Signal()
integrating = QtCore.Signal()

repairing = QtCore.pyqtSignal()
stopping = QtCore.pyqtSignal()
saving = QtCore.pyqtSignal()
initialising = QtCore.pyqtSignal()
acting = QtCore.pyqtSignal()
acted = QtCore.pyqtSignal()
repairing = QtCore.Signal()
stopping = QtCore.Signal()
saving = QtCore.Signal()
initialising = QtCore.Signal()
acting = QtCore.Signal()
acted = QtCore.Signal()

# A plug-in/instance pair is about to be processed
about_to_process = QtCore.pyqtSignal(object, object)
about_to_process = QtCore.Signal(object, object)

changed = QtCore.pyqtSignal()
changed = QtCore.Signal()

ready = QtCore.pyqtSignal()
saved = QtCore.pyqtSignal()
finished = QtCore.pyqtSignal()
initialised = QtCore.pyqtSignal()
commented = QtCore.pyqtSignal()
commenting = QtCore.pyqtSignal(str, arguments=["comment"])
ready = QtCore.Signal()
saved = QtCore.Signal()
finished = QtCore.Signal()
initialised = QtCore.Signal()
commented = QtCore.Signal()
commenting = QtCore.Signal(str, arguments=["comment"])

state_changed = QtCore.pyqtSignal(str, arguments=["state"])
state_changed = QtCore.Signal(str, arguments=["state"])

# Statically expose these members to the QML run-time.
itemModel = qtproperty(lambda self: self.data["models"]["item"])
Expand Down Expand Up @@ -107,6 +107,7 @@ def __init__(self, host, parent=None, targets=[]):
},
"state": {
"is_running": False,
"readyCount": 0,
"current": None,
"all": list(),

Expand All @@ -125,6 +126,7 @@ def __init__(self, host, parent=None, targets=[]):
self.info.connect(self.on_info)
self.error.connect(self.on_error)
self.finished.connect(self.on_finished)
self.ready.connect(self.on_ready)
self.show.connect(self.on_show)

# NOTE: Listeners to this signal are run in the main thread
Expand Down Expand Up @@ -291,28 +293,28 @@ def setup_statemachine(self):
machine.start()
return machine

@QtCore.pyqtSlot(result=str)
@QtCore.Slot(result=str)
def comment(self):
"""Return first line of comment"""
return self.data["comment"]

@QtCore.pyqtProperty(str, notify=state_changed)
@QtCore.Property(str, notify=state_changed)
def state(self):
return self.data["state"]["current"]

@QtCore.pyqtProperty(bool, notify=commented)
@QtCore.Property(bool, notify=commented)
def hasComment(self):
return True if self.data["comment"] else False

@QtCore.pyqtProperty(bool, constant=True)
@QtCore.Property(bool, constant=True)
def commentEnabled(self):
return "comment" in self.host.cached_context.data

@property
def states(self):
return self.data["state"]["all"]

@QtCore.pyqtSlot(result=float)
@QtCore.Slot(result=float)
def time(self):
return time.time()

Expand Down Expand Up @@ -377,7 +379,7 @@ def iterator(self, plugins, context):

yield result

@QtCore.pyqtSlot(int, result=QtCore.QVariant)
@QtCore.Slot(int, result="QVariant")
def getPluginActions(self, index):
"""Return actions from plug-in at `index`
Expand Down Expand Up @@ -439,7 +441,7 @@ def getPluginActions(self, index):

return remaining_actions

@QtCore.pyqtSlot(str)
@QtCore.Slot(str)
def runPluginAction(self, action):
if "acting" in self.states:
return self.error.emit("Busy")
Expand Down Expand Up @@ -491,7 +493,7 @@ def on_finished(result):

util.defer(run, callback=on_finished)

@QtCore.pyqtSlot(int)
@QtCore.Slot(int)
def toggleInstance(self, index):
models = self.data["models"]
proxies = self.data["proxies"]
Expand All @@ -506,7 +508,7 @@ def toggleInstance(self, index):
else:
self.error.emit("Cannot toggle")

@QtCore.pyqtSlot(bool, str)
@QtCore.Slot(bool, str)
def toggleSection(self, checkState, sectionLabel):
model = self.data["models"]["item"]

Expand Down Expand Up @@ -535,7 +537,7 @@ def toggleSection(self, checkState, sectionLabel):
if item.isToggled != checkState and item.optional:
self.__toggle_item(model, model.items.index(item))

@QtCore.pyqtSlot(bool, str)
@QtCore.Slot(bool, str)
def hideSection(self, hideState, sectionLabel):
model = self.data["models"]["item"]

Expand All @@ -549,7 +551,7 @@ def hideSection(self, hideState, sectionLabel):
if item.itemType == "section" and item.name == sectionLabel:
self.__hide_item(model, model.items.index(item), hideState)

@QtCore.pyqtSlot(int, result=QtCore.QVariant)
@QtCore.Slot(int, result="QVariant")
def pluginData(self, index):
models = self.data["models"]
proxies = self.data["proxies"]
Expand All @@ -559,7 +561,7 @@ def pluginData(self, index):
source_index = source_qindex.row()
return self.__item_data(models["item"], source_index)

@QtCore.pyqtSlot(int, result=QtCore.QVariant)
@QtCore.Slot(int, result="QVariant")
def instanceData(self, index):
models = self.data["models"]
proxies = self.data["proxies"]
Expand All @@ -569,7 +571,7 @@ def instanceData(self, index):
source_index = source_qindex.row()
return self.__item_data(models["item"], source_index)

@QtCore.pyqtSlot(int)
@QtCore.Slot(int)
def togglePlugin(self, index):
models = self.data["models"]
proxies = self.data["proxies"]
Expand All @@ -584,7 +586,7 @@ def togglePlugin(self, index):
else:
self.error.emit("Cannot toggle")

@QtCore.pyqtSlot(str, str, str, str)
@QtCore.Slot(str, str, str, str)
def exclude(self, target, operation, role, value):
"""Exclude a `role` of `value` at `target`
Expand All @@ -609,7 +611,7 @@ def exclude(self, target, operation, role, value):
else:
raise TypeError("operation must be either `add` or `remove`")

@QtCore.pyqtSlot()
@QtCore.Slot()
def save(self):
# Deprecated
return
Expand Down Expand Up @@ -664,6 +666,11 @@ def comment_sync(self, comment):
self.host.update(key="comment", value=comment)
self.host.emit("commented", comment=comment)

def is_ready(self):
count = self.data["state"]["readyCount"]
util.wait(self.ready, 1000)
return self.data["state"]["readyCount"] == count + 1

# Event handlers

def on_commenting(self, comment):
Expand Down Expand Up @@ -712,6 +719,9 @@ def on_state_changed(self, state):
s.name for s in self.machine.configuration()
)

def on_ready(self):
self.data["state"]["readyCount"] += 1

def on_finished(self):
self.data["models"]["item"].reset_status()

Expand All @@ -733,12 +743,12 @@ def on_info(self, message):

# Slots

@QtCore.pyqtSlot()
@QtCore.Slot()
def stop(self):
self.data["state"]["is_running"] = False
self.stopping.emit()

@QtCore.pyqtSlot()
@QtCore.Slot()
def reset(self):
"""Request that host re-discovers plug-ins and re-processes selectors
Expand Down Expand Up @@ -885,7 +895,7 @@ def on_reset():

util.defer(self.host.reset, callback=on_reset)

@QtCore.pyqtSlot()
@QtCore.Slot()
def publish(self):
"""Start asynchonous publishing
Expand Down Expand Up @@ -942,7 +952,7 @@ def on_finished():

util.defer(get_data, callback=on_data_received)

@QtCore.pyqtSlot()
@QtCore.Slot()
def validate(self):
"""Start asynchonous validation
Expand Down Expand Up @@ -1102,7 +1112,7 @@ def on_finished(message=None):
iterator = self.iterator(plugins, context)
util.defer(lambda: next(iterator), callback=on_next)

@QtCore.pyqtSlot(int)
@QtCore.Slot(int)
def repairPlugin(self, index):
"""
Expand Down
Loading

0 comments on commit e0a9015

Please sign in to comment.