Support multiple Qt versions (PyQt4. PyQt5, PySide2, PySide) support via qtpy#11
Support multiple Qt versions (PyQt4. PyQt5, PySide2, PySide) support via qtpy#11borupdaniel merged 16 commits intogpilab:qt5from
Conversation
This requires changing the code to use PyQt5 convenetions where QtWidgets has split off from QtGui Supported backends are PyQt4, PyQt5, PySide, PySide2
of QGraphicsItemAnimation. Nodes now also inherit from QGraphicsObject so their properties can be animated additional API updates
This new way also works in PyQt4
Make QWebView import compatible with PyQt5 and PySide2 as well.
|
Thanks @grlee77! I've been hoping to find time to update the code to support Qt5 with PyQT, but I was unaware of qtpy. I also thought the PySide project had gone stagnant, but it's good to see that included as well. I think qtpy is a reasonable additional dependency for this additional flexibility. This LGTM but I'll test the code before merging and then we can create a new conda package. @nckz, any thoughts? Maybe you can also comment on the |
Apparently, it is going to be officially supported going forward, but is now being called "Qt for Python". I suspect given the official support, it may become more dominant going forward, so we should test against it too. There is a release available at the link below, but I haven't had a chance to try it yet. It looks like it is still imported under the name |
|
Thanks @grlee77 this looks good. I'm eager to move forward to Qt5 as well. The FauxMenu class was made to deal with rendering the menu as the user typed characters into the node-search. It was made for some idiosyncrasies in the first version of Qt4. -if it works now without, thats even better :). I'd like to play around with this branch a little more before pulling. |
|
I have this working and will try using it as my "daily driver" for a bit to shake out any bugs. The only bug I see so far is upon quitting GPI I get the "Do you want to quit without saving?" dialog twice. This is kind of a separate issue that should be solved by keeping track of if/when a tab has been saved. |
|
Great. Thanks for the quick review. By all means, please test more thoroughly to make sure there aren't other issues I may have missed. I think as maintainers you two will have the necessary permissions to push additional commits directly to my branch if you want to make revisions. |
|
I think I'm experiencing the problem the When searching in the node menu, focus is stolen from the text field as soon as the results pop up. This makes it so you have to click the text field to resume typing after each letter is entered. I agree not using the |
Yes, I see this now too. I'm not sure why I didn't notice it previously, but it is pretty annoying. It looks like we may have to work out how to update the FauxWindow code for Qt5 compatibility. I have not seen the other issue you reported about "Do you want to quit without saving?" appearing twice. |
|
This is on my list. |
|
I've also been testing this branch with still very few issues so far. Hopefully next week I will have some time to capture some of the minor issues I've been having. I also modified FauxMenu to work without reverting to the raster version. I think I can push that up to this branch somehow... |
|
Glad to hear that this has been working on your end for the most part.
Yes, any members with write permissions to |
This reverts commit 880632e.
|
OK, thanks. That was a little confusing but it looks like I got it. Please test if my new |
|
Another problem I found was in the code for dragging/dropping widgets to/from Layout windows (see In PyQt5 In the same function, there also seems to be a bug in handling passing of the object id as a |
|
I'm giving this a test run on a fairly large node network and it seems to be working pretty well. @aganders3, I'm not having any issues with the FauxMenu — it seems to respond with no delay in PyQt4. I tried using both PyQt4 and PyQt5 (did not try PySide yet). A couple of things popped up (mostly node-related): PyQt4
PyQt5 (5.6.0)
Other things:
|
|
Thanks @borupdaniel - this is good stuff. Have you noticed the double-confirmation on quitting or is that a quirk of my system somehow? I'll try to make the requirements changes for Matplotlib ASAP and push new builds to Anaconda.org. Hopefully I can get around to this tomorrow at least for macOS. |
|
I would not prioritize testing with PySide at this point. I think it's a nice-to-have but that's a pretty big change for us and can wait. I think relaxing the PyQt requirement even to just >4, <5.6 is great progress. |
|
I do get the same issue with double-confirmation on quitting, but only with QtPy5. With 4.11.4 it behaves normally; with 5.6.0 I get the normal confirmation with the canvas open, then an extra one by itself after the canvas has disappeared. |
This doesn't seem like a showstopper but I'd rather not let it through if we can fix it. Super weird to me that it only happens with 5. Ultimately GPI needs to be more document-based so we can including auto-saving and get rid of this dialog if the network on disk is up-to-date. This may work around the issue in the long run but I'd love to see this PR merged sooner than later. |
|
I agree it would be nice to fix. I'm happy to look into it more in the next day or two to help me get some more experience with the framework. |
|
EDIT: okay, I would have sworn this worked yesterday afternoon, but now it makes no difference, so I'm not sure what's up... ORIGINAL POST: A quick two-liner fix to canvasGraphy.py is the following. A new import statement: from PyQt5.QtCore import pyqtSlotand later, adding this @ statement .just before closeGraphWithDialog is specified. @pyqtSlot()
def closeGraphWithDialog(self):The import statement is obviously not flexible with different PyQt versions, but I think the info at this link should be enough to point me in the right direction to finish this fix. |
|
The fix you propose seems OK to me. Maybe we need to try/except the import and assign a dummy decorator if it fails? I'm not sure if that or an But I think this is actually two problems. I am getting |
|
Ah, this explains things — the issue doesn't happen if you close from the button at top left of the window. So, my fix above doesn't make any difference, I just happened to be testing it by clicking the button instead of command-Q. |
|
This seems to work in Qt 5.6 but it's a bit ugly. |
|
I have the following, similarly ugly but functional. |
|
@aganders3, is there a way to specify a specific build for a package? The issue with qtpy 5.9.2 doesn't show up with an earlier build, so it would be nice to say something like "use pyqt 4 or 5, but for 5.9.2, don't use build py36h655552a_2", or something. This would improve compatibility downstream, although it's a bit more complicated on our end. Here's the change in conda that addresses this issue: |
|
I think we're probably ready to merge this unless you want to do any additional testing, @aganders3. I think we can specify PyQt <= 5.6 for the build and keep an eye on the 5.9.2 bug separately. What do you think — should we go ahead with this? |
|
I think yes but will allow others to chime in if there are any protestations. We can merge without doing a release as well for now. Let's discuss this week about building/uploading a release, but actually doing this should probably wait until after the ISMRM demo. |
|
I've created a new "qt5" branch and am going to go ahead with this pull request. We're thinking to make this GPI v1.1.0 and wanted to hold off on putting it in the main development branch while we get a v1.0.6 built as we work to getting GPI on conda forge. Thanks @grlee77 for your work on this — great addition to the project! |
Following up on this, you can use |
|
@aganders3 is there anything you still want to do with v1.0.6? If not I'll go ahead and merge this into the develop branch preparing for 1.1.0. |
|
I don't think so...I merged and tagged 1.0.6 in master so I think we're OK to merge this into develop even though we don't have 1.0.6 packages yet. We should do this in the core nodes repo as well, and then we can create conda packages from the develop branches for final testing. |
|
I went ahead and merged this into develop, as well as in the core nodes repo. I'm going to switch over to a new issue for preparing the v1.1.0 release on conda-forge. |
|
Thanks @borupdaniel - I'm working on release candidate builds for 1.0.6 as I update the build recipes to...actually work again. |
|
Sounds good. Future reference: see #22 for the new discussion. |
This PR uses qtpy to add support for Qt 5 via either PyQt5 or PySide2 and Qt 4 support via PySide. The previously existing PyQt4 support has been maintained. qtpy is a small python package that is easily installable via pip or conda and is used by the Spyder IDE and other projects to support multiple Qt variants.
Adding PySide support also provides the benefit of supporting an LGPL-licensed Qt backend (PyQt instead uses a GPLv3 license).
I have tested this code on the provided examples in pyqt 4.11.4 (Qt 4.8.7), pyqt 5.6.0 (Qt 5.6.2), pyqt 5.9.2 (Qt 5.9.4) and PySide2 (Qt 5.6.2).
The biggest share of changes are the move of widgets out of the
QtGuimodule into their ownQtWidgetsmodule. Here the Qt5 API is used andqtpytakes care of making pyqt4 and pyside work with the Qt 5 API conventions. There are a couple other places where object attributes changed between Qt 4 and 5. For these atry/except AttributeErrorwas used where needed to support both versions. These cases would not be necessary if it is desired to just drop Qt 4 support going forward.There are only a couple areas that were a bit tricky to convert.
1.)
QGraphicsItemAnimationas used by the "Macro Node" is no longer available in recent Qt. It has been replaced with equivalent code usingQPropertyAnimationinstead.2.) The library node search results pop-up window was modified in 6d6f298 so that it also works in Qt 5. I wasn't entirely clear on the purpose of the
FauxWindowclass, but for some reason it would not display properly in Qt 5 (it was ending up hidden under the main canvas and the buttons were not functional). The new approach is simpler and works on Qt 4 and 5, but perhaps there is some subtle difference?3.)
QtWebKitis deprecated, but is still present in PyQt5 and PySide2. It was just necessary to import it fromQtWebKitWidgetsinstead.Finally, commit e7e444a here changes a font name from "times" to "Times New Roman". In
PyQt5, I got very poorly rendered text with "times", which is fixed by changing the name. The buttons look fine for either name inPyQt4.before:

after:

If this is going to be merged, there is a smaller companion PR to
core-nodesso that those also support Qt 5 and are compatible with the changes made here.TODO: