Fix usage of QApplication for PyQt 4.6, since in 4.6 the global application instance is garbage collected, we need to store it in a global variable

This commit is contained in:
Kovid Goyal 2009-10-29 13:12:34 -06:00
parent ef6e9a9abc
commit a28079ff17
11 changed files with 60 additions and 52 deletions

View File

@ -87,4 +87,6 @@ class Economist(BasicNewsRecipe):
feeds[key].append(article) feeds[key].append(article)
ans = [(key, feeds[key]) for key in ans if feeds.has_key(key)] ans = [(key, feeds[key]) for key in ans if feeds.has_key(key)]
if not ans:
raise Exception('Could not find any articles. Has your subscription expired?')
return ans return ans

View File

@ -11,16 +11,15 @@ from PyQt4.Qt import QUrl, QApplication, QSize, QEventLoop, \
SIGNAL, QPainter, QImage, QObject, Qt SIGNAL, QPainter, QImage, QObject, Qt
from PyQt4.QtWebKit import QWebPage from PyQt4.QtWebKit import QWebPage
class HTMLTableRenderer(QObject): class HTMLTableRenderer(QObject):
def __init__(self, html, base_dir, width, height, dpi, factor): def __init__(self, html, base_dir, width, height, dpi, factor):
''' '''
`width, height`: page width and height in pixels `width, height`: page width and height in pixels
`base_dir`: The directory in which the HTML file that contains the table resides `base_dir`: The directory in which the HTML file that contains the table resides
''' '''
QObject.__init__(self) QObject.__init__(self)
self.app = None self.app = None
self.width, self.height, self.dpi = width, height, dpi self.width, self.height, self.dpi = width, height, dpi
self.base_dir = base_dir self.base_dir = base_dir
@ -30,10 +29,10 @@ class HTMLTableRenderer(QObject):
self.page = QWebPage() self.page = QWebPage()
self.connect(self.page, SIGNAL('loadFinished(bool)'), self.render_html) self.connect(self.page, SIGNAL('loadFinished(bool)'), self.render_html)
self.page.mainFrame().setTextSizeMultiplier(factor) self.page.mainFrame().setTextSizeMultiplier(factor)
self.page.mainFrame().setHtml(html, self.page.mainFrame().setHtml(html,
QUrl('file:'+os.path.abspath(self.base_dir))) QUrl('file:'+os.path.abspath(self.base_dir)))
def render_html(self, ok): def render_html(self, ok):
try: try:
if not ok: if not ok:
@ -61,7 +60,7 @@ class HTMLTableRenderer(QObject):
self.images.append((f, img.width(), img.height())) self.images.append((f, img.width(), img.height()))
finally: finally:
QApplication.quit() QApplication.quit()
def render_table(soup, table, css, base_dir, width, height, dpi, factor=1.0): def render_table(soup, table, css, base_dir, width, height, dpi, factor=1.0):
head = '' head = ''
for e in soup.findAll(['link', 'style']): for e in soup.findAll(['link', 'style']):
@ -85,10 +84,11 @@ def render_table(soup, table, css, base_dir, width, height, dpi, factor=1.0):
images, tdir = do_render(html, base_dir, width, height, dpi, factor) images, tdir = do_render(html, base_dir, width, height, dpi, factor)
atexit.register(shutil.rmtree, tdir) atexit.register(shutil.rmtree, tdir)
return images return images
def do_render(html, base_dir, width, height, dpi, factor): def do_render(html, base_dir, width, height, dpi, factor):
if QApplication.instance() is None: from calibre.gui2 import is_ok_to_use_qt
QApplication([]) if not is_ok_to_use_qt():
raise Exception('Not OK to use Qt')
tr = HTMLTableRenderer(html, base_dir, width, height, dpi, factor) tr = HTMLTableRenderer(html, base_dir, width, height, dpi, factor)
tr.loop.exec_() tr.loop.exec_()
return tr.images, tr.tdir return tr.images, tr.tdir

View File

@ -18,7 +18,6 @@ from PyQt4.QtGui import QColor
from PyQt4.QtGui import QImage from PyQt4.QtGui import QImage
from PyQt4.QtGui import QPainter from PyQt4.QtGui import QPainter
from PyQt4.QtSvg import QSvgRenderer from PyQt4.QtSvg import QSvgRenderer
from PyQt4.QtGui import QApplication
from calibre.ebooks.oeb.base import XHTML, XLINK from calibre.ebooks.oeb.base import XHTML, XLINK
from calibre.ebooks.oeb.base import SVG_MIME, PNG_MIME from calibre.ebooks.oeb.base import SVG_MIME, PNG_MIME
from calibre.ebooks.oeb.base import xml2str, xpath from calibre.ebooks.oeb.base import xml2str, xpath
@ -30,8 +29,9 @@ KEEP_ATTRS = set(['class', 'style', 'width', 'height', 'align'])
class SVGRasterizer(object): class SVGRasterizer(object):
def __init__(self): def __init__(self):
if QApplication.instance() is None: from calibre.gui2 import is_ok_to_use_qt
QApplication([]) if not is_ok_to_use_qt():
raise Exception('Not OK to use Qt')
@classmethod @classmethod
def config(cls, cfg): def config(cls, cfg):

View File

@ -18,7 +18,7 @@ from calibre.ebooks.metadata import authors_to_string
from PyQt4 import QtCore from PyQt4 import QtCore
from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, \ from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, \
QApplication, QPrinter, QMetaObject, QSizeF, Qt QPrinter, QMetaObject, QSizeF, Qt
from PyQt4.QtWebKit import QWebView from PyQt4.QtWebKit import QWebView
from pyPdf import PdfFileWriter, PdfFileReader from pyPdf import PdfFileWriter, PdfFileReader
@ -37,8 +37,9 @@ class PDFMetadata(object):
class PDFWriter(QObject): class PDFWriter(QObject):
def __init__(self, opts, log): def __init__(self, opts, log):
if QApplication.instance() is None: from calibre.gui2 import is_ok_to_use_qt
QApplication([]) if not is_ok_to_use_qt():
raise Exception('Not OK to use Qt')
QObject.__init__(self) QObject.__init__(self)
self.logger = log self.logger = log

View File

@ -528,12 +528,14 @@ class Application(QApplication):
if set_qt_translator(self._translator): if set_qt_translator(self._translator):
self.installTranslator(self._translator) self.installTranslator(self._translator)
_store_app = None
def is_ok_to_use_qt(): def is_ok_to_use_qt():
global gui_thread global gui_thread, _store_app
if islinux and ':' not in os.environ.get('DISPLAY', ''): if islinux and ':' not in os.environ.get('DISPLAY', ''):
return False return False
if QApplication.instance() is None: if _store_app is None and QApplication.instance() is None:
QApplication([]) _store_app = QApplication([])
if gui_thread is None: if gui_thread is None:
gui_thread = QThread.currentThread() gui_thread = QThread.currentThread()
return gui_thread is QThread.currentThread() return gui_thread is QThread.currentThread()

View File

@ -98,7 +98,7 @@ class FontKeyChooser(QDialog, Ui_Dialog):
if __name__ == '__main__': if __name__ == '__main__':
from PyQt4.Qt import QApplication from calibre.gui2 import is_ok_to_use_qt
QApplication([]) is_ok_to_use_qt()
d = FontKeyChooser() d = FontKeyChooser()
d.exec_() d.exec_()

View File

@ -20,9 +20,9 @@ if pictureflow is not None:
class EmptyImageList(pictureflow.FlowImages): class EmptyImageList(pictureflow.FlowImages):
def __init__(self): def __init__(self):
pictureflow.FlowImages.__init__(self) pictureflow.FlowImages.__init__(self)
class FileSystemImages(pictureflow.FlowImages): class FileSystemImages(pictureflow.FlowImages):
def __init__(self, dirpath): def __init__(self, dirpath):
pictureflow.FlowImages.__init__(self) pictureflow.FlowImages.__init__(self)
self.images = [] self.images = []
@ -33,58 +33,58 @@ if pictureflow is not None:
if not img.isNull(): if not img.isNull():
self.images.append(img) self.images.append(img)
self.captions.append(os.path.basename(f)) self.captions.append(os.path.basename(f))
def count(self): def count(self):
return len(self.images) return len(self.images)
def image(self, index): def image(self, index):
return self.images[index] return self.images[index]
def caption(self, index): def caption(self, index):
return self.captions[index] return self.captions[index]
def currentChanged(self, index): def currentChanged(self, index):
print 'current changed:', index print 'current changed:', index
class DatabaseImages(pictureflow.FlowImages): class DatabaseImages(pictureflow.FlowImages):
def __init__(self, model, buffer=20): def __init__(self, model, buffer=20):
pictureflow.FlowImages.__init__(self) pictureflow.FlowImages.__init__(self)
self.model = model self.model = model
QObject.connect(self.model, SIGNAL('modelReset()'), self.reset) QObject.connect(self.model, SIGNAL('modelReset()'), self.reset)
def count(self): def count(self):
return self.model.count() return self.model.count()
def caption(self, index): def caption(self, index):
return self.model.title(index) return self.model.title(index)
def reset(self): def reset(self):
self.emit(SIGNAL('dataChanged()')) self.emit(SIGNAL('dataChanged()'))
def image(self, index): def image(self, index):
return self.model.cover(index) return self.model.cover(index)
class CoverFlow(pictureflow.PictureFlow): class CoverFlow(pictureflow.PictureFlow):
def __init__(self, height=300, parent=None, text_height=25): def __init__(self, height=300, parent=None, text_height=25):
pictureflow.PictureFlow.__init__(self, parent, pictureflow.PictureFlow.__init__(self, parent,
config['cover_flow_queue_length']+1) config['cover_flow_queue_length']+1)
self.setSlideSize(QSize(int(2/3. * height), height)) self.setSlideSize(QSize(int(2/3. * height), height))
self.setMinimumSize(QSize(int(2.35*0.67*height), (5/3.)*height+text_height)) self.setMinimumSize(QSize(int(2.35*0.67*height), (5/3.)*height+text_height))
self.setFocusPolicy(Qt.WheelFocus) self.setFocusPolicy(Qt.WheelFocus)
self.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)) self.setSizePolicy(QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum))
def wheelEvent(self, ev): def wheelEvent(self, ev):
ev.accept() ev.accept()
if ev.delta() < 0: if ev.delta() < 0:
self.showNext() self.showNext()
elif ev.delta() > 0: elif ev.delta() > 0:
self.showPrevious() self.showPrevious()
else: else:
CoverFlow = None CoverFlow = None
DatabaseImages = None DatabaseImages = None
@ -105,7 +105,7 @@ if __name__ == '__main__':
cf.setImages(model) cf.setImages(model)
cf.connect(cf, SIGNAL('currentChanged(int)'), model.currentChanged) cf.connect(cf, SIGNAL('currentChanged(int)'), model.currentChanged)
w.setCentralWidget(cf) w.setCentralWidget(cf)
w.show() w.show()
cf.setFocus(Qt.OtherFocusReason) cf.setFocus(Qt.OtherFocusReason)
sys.exit(app.exec_()) sys.exit(app.exec_())

View File

@ -9,7 +9,7 @@ Scheduler for automated recipe downloads
from datetime import datetime, timedelta from datetime import datetime, timedelta
from PyQt4.Qt import QDialog, QApplication, SIGNAL, Qt, QTime, QObject, QMenu, \ from PyQt4.Qt import QDialog, SIGNAL, Qt, QTime, QObject, QMenu, \
QAction, QIcon, QMutex, QTimer QAction, QIcon, QMutex, QTimer
from calibre.gui2.dialogs.scheduler_ui import Ui_Dialog from calibre.gui2.dialogs.scheduler_ui import Ui_Dialog
@ -306,7 +306,8 @@ class Scheduler(QObject):
self.download(urn) self.download(urn)
if __name__ == '__main__': if __name__ == '__main__':
QApplication([]) from calibre.gui2 import is_ok_to_use_qt
is_ok_to_use_qt()
from calibre.library.database2 import LibraryDatabase2 from calibre.library.database2 import LibraryDatabase2
d = SchedulerDialog(RecipeModel(LibraryDatabase2('/home/kovid/documents/library'))) d = SchedulerDialog(RecipeModel(LibraryDatabase2('/home/kovid/documents/library')))
d.exec_() d.exec_()

View File

@ -314,8 +314,8 @@ class %(classname)s(%(base_class)s):
self.source_code.setText('') self.source_code.setText('')
if __name__ == '__main__': if __name__ == '__main__':
from PyQt4.Qt import QApplication from calibre.gui2 import is_ok_to_use_qt
QApplication([]) is_ok_to_use_qt()
from calibre.library.database2 import LibraryDatabase2 from calibre.library.database2 import LibraryDatabase2
from calibre.web.feeds.recipes.model import RecipeModel from calibre.web.feeds.recipes.model import RecipeModel
d=UserProfiles(None, RecipeModel(LibraryDatabase2('/home/kovid/documents/library'))) d=UserProfiles(None, RecipeModel(LibraryDatabase2('/home/kovid/documents/library')))

View File

@ -282,9 +282,10 @@ class StatusBar(QStatusBar):
if __name__ == '__main__': if __name__ == '__main__':
# Used to create the animated status icon # Used to create the animated status icon
from PyQt4.Qt import QApplication, QPainter, QSvgRenderer, QColor from PyQt4.Qt import QPainter, QSvgRenderer, QColor
from subprocess import check_call from subprocess import check_call
app = QApplication([]) from calibre.gui2 import is_ok_to_use_qt
is_ok_to_use_qt()
def create_pixmaps(path, size=16, delta=20): def create_pixmaps(path, size=16, delta=20):
r = QSvgRenderer(path) r = QSvgRenderer(path)

View File

@ -10,7 +10,7 @@ from BeautifulSoup import BeautifulSoup, Tag
from PyQt4 import QtCore from PyQt4 import QtCore
from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, QApplication, Qt, \ from PyQt4.Qt import QUrl, QEventLoop, SIGNAL, QObject, Qt, \
QPrinter, QPrintPreviewDialog, QPrintDialog, QDialog, QMetaObject, Q_ARG QPrinter, QPrintPreviewDialog, QPrintDialog, QDialog, QMetaObject, Q_ARG
from PyQt4.QtWebKit import QWebView from PyQt4.QtWebKit import QWebView
@ -18,8 +18,9 @@ PRINTCSS = 'body{width:100%;margin:0;padding:0;font-family:Arial;color:#000;back
class Printing(QObject): class Printing(QObject):
def __init__(self, spine, preview): def __init__(self, spine, preview):
if QApplication.instance() is None: from calibre.gui2 import is_ok_to_use_qt
QApplication([]) if not is_ok_to_use_qt():
raise Exception('Not OK to use Qt')
QObject.__init__(self) QObject.__init__(self)
self.loop = QEventLoop() self.loop = QEventLoop()