07-06-2014, 03:48 AM | #1 |
creator of calibre
Posts: 44,356
Karma: 23661992
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
Attn plugin developers: calibre moving to Qt 5
Hi all,
calibre will soon be moving to using Qt 5 in place of Qt 4 as its GUI library. If you have created plugins that use the GUI (User Interface plugins) then you will need to do a little porting to have your plugins work with both Qt 4 and Qt 5. The porting work is mostly mechanical search and replace, unless you happen to use some obscure corners of Qt. In the next post of this thread, I will add a guide to cover the most common porting tasks. Beta builds of calibre with Qt 5 are available here: http://download.calibre-ebook.com/betas/ The betas are fully compatible with current stable calibre releases, in that you can use them on the same library/configuration folder with no problems (indeed my family and I have been running the Qt 5 based calibre code base for almost two months). However, if you want to be doubly cautious, use the portable install with a special test library. I encourage you to port your plugins as soon as possible so that when calibre 2.0 is released, which will use Qt 5, your plugins will continue to work. I am happy to help you with any issues you encounter during porting. Feel free to post in this thread with questions, and I will answer them to the best of my ability. Finally, these are beta builds, and because of the large numbers of OSes that calibre supports I haven't been able to test them on everything, so if you notice any bugs feel free to let me know. The status of the plugin porting effort can be monitored here: http://plugins.calibre-ebook.com/porting.html Last edited by kovidgoyal; 07-18-2014 at 03:19 AM. |
07-06-2014, 03:48 AM | #2 |
creator of calibre
Posts: 44,356
Karma: 23661992
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
Guide for porting plugin code to Qt 5
Last edited by kovidgoyal; 08-15-2014 at 04:45 AM. |
Advert | |
|
07-06-2014, 09:11 PM | #3 |
Grand Sorcerer
Posts: 24,905
Karma: 47303822
Join Date: Jul 2011
Location: Sydney, Australia
Device: Kobo:Touch,Glo, AuraH2O, GloHD,AuraONE, ClaraHD, Libra H2O; tolinoepos
|
That looks easy enough. And, yes, I know I will regret that statement sometime in the next few days
Is there anything extra we need to do to run from source? I did just see an error: Code:
calibre, version 1.200.0 ERROR: Unhandled exception: <b>TypeError</b>:QAbstractTableModel.flags(QModelIndex): first argument of unbound method must have type 'QAbstractTableModel' calibre 1.200 isfrozen: True is64bit: False Windows-7-6.1.7601-SP1 Windows ('32bit', 'WindowsPE') ('Windows', '7', '6.1.7601') Python 2.7.8 Windows: ('7', '6.1.7601', 'SP1', 'Multiprocessor Free') Successfully initialized third party plugins: DeDRM && FanFictionDownLoader && EpubMerge && Count Pages && Search The Internet && Open With && Fantastic Fiction && Webscription && Annotations && Goodreads && && Favourites Menu && Find Duplicates && KoboTouchBeta && Ebook Cleaner && Quality Check && Resize Cover && Modify ePub && Generate Cover && User Category && KoboBooks && Hyphenate This! && Reading List && Clipboard Search && KoboTouchTOCUpdate && KePub Output && FictionDB && KoboTouchExtended && EpubSplit && Copy Cover To Device && View Manager && KindleUnpack - The Plugin && Walk Search History && Temp Marker && Kobo Utilities && Kindle 2, 3, 4, Touch, PaperWhite Device Interface MBP Update Mod && Goodreads Sync && SmartEject && Manage Series Traceback (most recent call last): File "site-packages\calibre\gui2\preferences\metadata_sources.py", line 199, in flags TypeError: QAbstractTableModel.flags(QModelIndex): first argument of unbound method must have type 'QAbstractTableModel' |
07-06-2014, 10:26 PM | #4 |
creator of calibre
Posts: 44,356
Karma: 23661992
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
If you are running from source you have to switch to the qt5 branch as the master branch will only work with qt 4.
Thanks, that bug is fixed: https://github.com/kovidgoyal/calibr...b37aaf6fef6d03 Last edited by kovidgoyal; 07-06-2014 at 10:29 PM. |
07-07-2014, 12:54 AM | #5 |
Grand Sorcerer
Posts: 24,905
Karma: 47303822
Join Date: Jul 2011
Location: Sydney, Australia
Device: Kobo:Touch,Glo, AuraH2O, GloHD,AuraONE, ClaraHD, Libra H2O; tolinoepos
|
|
Advert | |
|
07-07-2014, 12:55 AM | #6 |
Grand Sorcerer
Posts: 24,905
Karma: 47303822
Join Date: Jul 2011
Location: Sydney, Australia
Device: Kobo:Touch,Glo, AuraH2O, GloHD,AuraONE, ClaraHD, Libra H2O; tolinoepos
|
Some things I have found so far...
I had an error with: Code:
from calibre.gui2.complete import MultiCompleteComboBox I also have: Code:
from PyQt4 import QtGui Code:
from PyQt5 import QtWidgets as QtGui Both of the above are in code I have stolen from kiwidudes plugins. And are appearing in most of the plugins. |
07-07-2014, 01:29 AM | #7 |
creator of calibre
Posts: 44,356
Karma: 23661992
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
I have edited the guide to describe how to deal with direct use of QtGui or QtCore and EditWithComplete
|
07-07-2014, 06:08 PM | #8 |
Grand Sorcerer
Posts: 27,903
Karma: 198500000
Join Date: Jan 2010
Device: Nexus 7, Kindle Fire HD
|
Thanks for the advance notice, and the porting tips! Things have gone pretty smoothly for the little bit I've tried.
I did run into a bit of a snag with QListWidget in the move from PyQt4 to PyQt5. It might not affect too many, but I thought I'd share just in case. I'm iterating the items of a QListWidget that allows multiple selections (to get a list of the indices of the items than are selected) and have found that the QListWidget.isItemSelected(QListWidgetItem * item) method no longer exists in PyQt5. So the method I was using (that works in PyQt4): Code:
book_indices = [] for index in xrange(qlist_widget.count()): qlist_widget_item = qlist_widget.item(index) if qlist_widget.isItemSelected(qlist_widget_item): book_indices.append(index) The method that will work in both is: Code:
book_indices = [] for index in xrange(qlist_widget.count()): qlist_widget_item = qlist_widget.item(index) if qlist_widget_item.isSelected(): book_indices.append(index) Anyway ... if anyone runs into issues with QListWidget while porting, keep in mind that the isItemSelected method has gone away in Qt5. |
07-08-2014, 08:42 AM | #9 |
Grand Sorcerer
Posts: 6,216
Karma: 16534894
Join Date: Sep 2009
Location: UK
Device: Kobo: KA1, ClaraHD, Forma, Libra2, Clara2E. PocketBook: TouchHD3
|
What is the best way to deal with the change to the QFileDialog.getOpenFileName method?
PyQt4 used to return a single filepath but PyQt5 returns 2 strings (filepath, filter). I don't need the filter part of the result so I've temporarily solved it like this: Code:
fd = QFileDialog() if hasattr(fd, 'getOpenFileNameAndFilter'): # PyQt4 ans = fd.getOpenFileNameAndFilter(self, mycaption, mydir, myfilter) else: # PyQt5 ans = fd.getOpenFileName(self, mycaption, mydir, myfilter) selfile = unicode(ans[0]) I have quite a few other questions (mainly to do with SIGNAL) but ... one thing at a time. |
07-08-2014, 09:57 AM | #10 |
Grand Sorcerer
Posts: 24,905
Karma: 47303822
Join Date: Jul 2011
Location: Sydney, Australia
Device: Kobo:Touch,Glo, AuraH2O, GloHD,AuraONE, ClaraHD, Libra H2O; tolinoepos
|
While running from source, I received:
Code:
calibre, version 1.200.0 ERROR: Unhandled exception: <b>ValueError</b>:invalid literal for int() with base 10: '' calibre 1.200* isfrozen: True is64bit: False Windows-7-6.1.7601-SP1 Windows ('32bit', 'WindowsPE') ('Windows', '7', '6.1.7601') Python 2.7.8 Windows: ('7', '6.1.7601', 'SP1', 'Multiprocessor Free') Successfully initialized third party plugins: ... Traceback (most recent call last): File "D:\Development\GitHub\calibre-qt5\src\calibre\gui2\preferences\metadata_sources.py", line 102, in setData ValueError: invalid literal for int() with base 10: '' I checked this with the Qt4 version and there is another bug in both. When the editing of the cover priority field is started, the field is emptied. That is annoying as you don't know what the current value is. |
07-08-2014, 10:34 AM | #11 | |
Grand Sorcerer
Posts: 24,905
Karma: 47303822
Join Date: Jul 2011
Location: Sydney, Australia
Device: Kobo:Touch,Glo, AuraH2O, GloHD,AuraONE, ClaraHD, Libra H2O; tolinoepos
|
Quote:
But, I think I have mine done now. Plus some others because I am impatient and I hadn't seen kiwidude around for a while. I have briefly talked to kiwidude about this and, as he is busy with work, he's happy for the help. I'm not quite ready to post them publicly, but a couple of extra testers would be good. The plugins I have done are: Annotations, Count Pages, Kobo Utilities, Open With, Reading List, Smart Eject. And the metadata source plugins: Fantastic Fiction, Goodreads and (brand new) KoboBooks. If someone wants to test these, send me a PM and I'll send a link back tomorrow. And if anyone wants to add to collection, I'll put them up as well. |
|
07-08-2014, 10:42 AM | #12 |
Grand Sorcerer
Posts: 6,216
Karma: 16534894
Join Date: Sep 2009
Location: UK
Device: Kobo: KA1, ClaraHD, Forma, Libra2, Clara2E. PocketBook: TouchHD3
|
My next question ... I need to create a right-click context menu on a single QTextBrowser widget, which is part of a busy QDialog.
This simplified code worked OK in PyQt4 but not PyQt5. I think the problem is in the red bits. Code:
from PyQt4.Qt import SIGNAL class MyDlg(QDialog): def __init__(self, epub, parent=None): QDialog.__init__(self) ... ... self.browser = QTextBrowser() self.browser.setContextMenuPolicy(Qt.CustomContextMenu) self.browser.customContextMenuRequested.connect(self.showSnippetMenu) self.create_context_menu() def showSnippetMenu(self, pos): self.snipmenu.popup(self.browser.mapToGlobal(pos)) def create_context_menu(self): self.snipmenu = QMenu(self.browser) self.myAction1 = self.createAction('Menu item label', self.myMethod1) self.addActions(self.snipmenu, (self.myAction1, ...)) def createAction(self, text, slot=None): action = QAction(text, self) if slot is not None: self.connect(action, SIGNAL("triggered()"), slot) return action def myMethod1(self): ... blah blah ... Last edited by jackie_w; 07-08-2014 at 10:45 AM. |
07-08-2014, 10:43 AM | #13 |
Grand Sorcerer
Posts: 6,216
Karma: 16534894
Join Date: Sep 2009
Location: UK
Device: Kobo: KA1, ClaraHD, Forma, Libra2, Clara2E. PocketBook: TouchHD3
|
@davidfor,
Oops, posted just before I saw your PM. Could be in for a l-o-n-g night. ETA: ... or maybe not Thank you, David It seems removing the first red line and changing the second to Code:
action.triggered.connect(slot)
Ah, the perils of having only a tenuous grasp on the whole concept of signals and slots and hoping for the best when blindly copying code from other people. Last edited by jackie_w; 07-08-2014 at 11:23 AM. |
07-08-2014, 11:27 AM | #14 | |
Plugin Developer
Posts: 6,537
Karma: 4277329
Join Date: Dec 2011
Location: Midwest USA
Device: Kindle Paperwhite(10th)
|
Quote:
Code:
- self.connect(self.horizontalHeader(), - SIGNAL('sectionClicked(int)'), - self.on_headersection_clicked) + self.horizontalHeader().sectionClicked.connect(self.on_headersection_clicked) |
|
07-08-2014, 11:58 AM | #15 | |
Plugin Developer
Posts: 6,537
Karma: 4277329
Join Date: Dec 2011
Location: Midwest USA
Device: Kindle Paperwhite(10th)
|
Quote:
I use several of kiwidude's other plugins regularly that I'll be willing to look at, time permitting. |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
calibre-plugins.com: A resource for plugin developers | GRiker | Development | 2 | 11-19-2014 03:52 PM |
Thank you to Calibre Developers | Happy_Reader | Calibre | 1 | 12-17-2013 10:18 PM |
Thanks Calibre Developers! | TechniSol | Kobo Reader | 3 | 11-19-2012 08:34 PM |
Calibre in a Python 3.2 world, attn: Kovid | Kevin McAleavey | Calibre | 8 | 01-09-2012 05:49 PM |
What device do most calibre developers use? | barium | Calibre | 5 | 01-05-2011 07:23 AM |