Add more hard references.

This should prevent some segfaults, as pointed out by [1].

 [1]: https://github.com/integricho/path-of-a-pyqter/tree/master/qttut02
This commit is contained in:
Florian Bruhin 2014-02-17 07:50:19 +01:00
parent 933296f47f
commit 76a459f604
4 changed files with 85 additions and 63 deletions

View File

@ -67,16 +67,19 @@ class TabbedBrowser(TabWidget):
set_cmd_text = pyqtSignal(str) # Set commandline to a given text
keypress = pyqtSignal('QKeyEvent')
_url_stack = [] # Stack of URLs of closed tabs
_space = None # Space QShortcut
_tabs = None
def __init__(self, parent=None):
super().__init__(parent)
self.currentChanged.connect(lambda idx:
self.widget(idx).signal_cache.replay())
space = QShortcut(self)
space.setKey(Qt.Key_Space)
space.setContext(Qt.WidgetWithChildrenShortcut)
space.activated.connect(lambda: self.cur_scroll_page(0, 1))
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self._tabs = []
self._space = QShortcut(self)
self._space.setKey(Qt.Key_Space)
self._space.setContext(Qt.WidgetWithChildrenShortcut)
self._space.activated.connect(lambda: self.cur_scroll_page(0, 1))
def tabopen(self, url):
"""Open a new tab with a given url.
@ -87,6 +90,7 @@ class TabbedBrowser(TabWidget):
logging.debug("Opening {}".format(url))
url = urlutils.qurl(url)
tab = BrowserTab(self)
self._tabs.append(tab)
self.addTab(tab, urlutils.urlstring(url))
self.setCurrentWidget(tab)
tab.linkHovered.connect(self._filter_factory(self.cur_link_hovered))
@ -149,6 +153,10 @@ class TabbedBrowser(TabWidget):
# FIXME maybe we actually should store the webview objects here
self._url_stack.append(tab.url())
self.removeTab(idx)
try:
self._tabs.remove(tab)
except ValueError:
pass
else:
# FIXME
pass

View File

@ -226,6 +226,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
opt = None
style = None
painter = None
doc = None
def sizeHint(self, option, index):
"""Override sizeHint of QStyledItemDelegate.
@ -239,11 +240,12 @@ class CompletionItemDelegate(QStyledItemDelegate):
return value
self.opt = QStyleOptionViewItem(option)
self.initStyleOption(self.opt, index)
style = self.opt.widget.style()
doc = self._get_textdoc(index)
docsize = doc.size().toSize()
return style.sizeFromContents(QStyle.CT_ItemViewItem, self.opt,
docsize, self.opt.widget) + QSize(10, 1)
self.style = self.opt.widget.style()
self._get_textdoc(index)
docsize = self.doc.size().toSize()
size = self.style.sizeFromContents(QStyle.CT_ItemViewItem, self.opt,
docsize, self.opt.widget)
return size + QSize(10, 1)
def paint(self, painter, option, index):
"""Override the QStyledItemDelegate paint function."""
@ -326,22 +328,21 @@ class CompletionItemDelegate(QStyledItemDelegate):
self.painter.drawRect(text_rect_.adjusted(0, 0, -1, -1))
self.painter.translate(text_rect.left(), text_rect.top())
doc = self._get_textdoc(index)
self._draw_textdoc(doc, text_rect)
self._get_textdoc(index)
self._draw_textdoc(text_rect)
self.painter.restore()
def _draw_textdoc(self, doc, text_rect):
def _draw_textdoc(self, text_rect):
"""Draw the QTextDocument of an item.
doc -- The QTextDocument to draw.
text_rect -- The QRect to clip the drawing to.
"""
clip = QRectF(0, 0, text_rect.width(), text_rect.height())
doc.drawContents(self.painter, clip)
self.doc.drawContents(self.painter, clip)
def _get_textdoc(self, index):
"""Return the QTextDocument of an item.
"""Create the QTextDocument of an item.
index -- The QModelIndex of the item to draw.
@ -357,31 +358,30 @@ class CompletionItemDelegate(QStyledItemDelegate):
text_option.setAlignment(QStyle.visualAlignment(
self.opt.direction, self.opt.displayAlignment))
doc = QTextDocument()
self.doc = QTextDocument()
if index.parent().isValid():
doc.setPlainText(self.opt.text)
self.doc.setPlainText(self.opt.text)
else:
doc.setHtml('<b>{}</b>'.format(html.escape(self.opt.text)))
doc.setDefaultFont(self.opt.font)
doc.setDefaultTextOption(text_option)
doc.setDefaultStyleSheet(config.get_stylesheet("""
self.doc.setHtml('<b>{}</b>'.format(html.escape(self.opt.text)))
self.doc.setDefaultFont(self.opt.font)
self.doc.setDefaultTextOption(text_option)
self.doc.setDefaultStyleSheet(config.get_stylesheet("""
.highlight {{
{color[completion.match.fg]}
}}
"""))
doc.setDocumentMargin(2)
self.doc.setDocumentMargin(2)
if index.column() == 0:
marks = index.data(Qt.UserRole)
for mark in marks:
cur = QTextCursor(doc)
cur = QTextCursor(self.doc)
cur.setPosition(mark[0])
cur.setPosition(mark[1], QTextCursor.KeepAnchor)
txt = cur.selectedText()
cur.removeSelectedText()
cur.insertHtml('<span class="highlight">{}</span>'.format(
html.escape(txt)))
return doc
def _draw_focus_rect(self):
"""Draw the focus rectangle of an ItemViewItem."""

View File

@ -31,14 +31,21 @@ class CrashDialog(QDialog):
"""Dialog which gets shown after there was a crash."""
vbox = None
lbl = None
txt = None
hbox = None
btn_quit = None
btn_restore = None
def __init__(self, pages, cmdhist, exc):
super().__init__()
self.setFixedSize(500, 350)
self.setWindowTitle('Whoops!')
self.setModal(True)
vbox = QVBoxLayout()
lbl = QLabel(self)
self.vbox = QVBoxLayout()
self.lbl = QLabel(self)
text = ('Argh! qutebrowser crashed unexpectedly.<br/>'
'Please review the info below to remove sensitive data and '
'then submit it to <a href="mailto:crash@qutebrowser.org">'
@ -46,29 +53,29 @@ class CrashDialog(QDialog):
if pages:
text += ('You can click "Restore tabs" to attempt to reopen your '
'open tabs.')
lbl.setText(text)
lbl.setWordWrap(True)
vbox.addWidget(lbl)
self.lbl.setText(text)
self.lbl.setWordWrap(True)
self.vbox.addWidget(self.lbl)
txt = QTextEdit(self)
txt.setReadOnly(True)
txt.setText(self._crash_info(pages, cmdhist, exc))
vbox.addWidget(txt)
self.setLayout(vbox)
self.txt = QTextEdit(self)
self.txt.setReadOnly(True)
self.txt.setText(self._crash_info(pages, cmdhist, exc))
self.vbox.addWidget(self.txt)
self.setLayout(self.vbox)
hbox = QHBoxLayout()
btn_quit = QPushButton(self)
btn_quit.setText('Quit')
btn_quit.clicked.connect(self.reject)
hbox.addWidget(btn_quit)
self.hbox = QHBoxLayout()
self.btn_quit = QPushButton(self)
self.btn_quit.setText('Quit')
self.btn_quit.clicked.connect(self.reject)
self.hbox.addWidget(self.btn_quit)
if pages:
btn_restore = QPushButton(self)
btn_restore.setText('Restore tabs')
btn_restore.clicked.connect(self.accept)
btn_restore.setDefault(True)
hbox.addWidget(btn_restore)
self.btn_restore = QPushButton(self)
self.btn_restore.setText('Restore tabs')
self.btn_restore.clicked.connect(self.accept)
self.btn_restore.setDefault(True)
self.hbox.addWidget(self.btn_restore)
vbox.addLayout(hbox)
self.vbox.addLayout(self.hbox)
def _crash_info(self, pages, cmdhist, exc):
"""Gather crash information to display."""

View File

@ -34,6 +34,7 @@ class StatusBar(QWidget):
"""The statusbar at the bottom of the mainwindow."""
hbox = None
cmd = None
txt = None
keystring = None
@ -43,6 +44,8 @@ class StatusBar(QWidget):
resized = pyqtSignal('QRect')
moved = pyqtSignal('QPoint')
_error = False
_option = None
_painter = None
_stylesheet = """
QWidget#StatusBar[error="false"] {{
{color[statusbar.bg]}
@ -66,28 +69,28 @@ class StatusBar(QWidget):
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
hbox = QHBoxLayout(self)
hbox.setContentsMargins(0, 0, 0, 0)
hbox.setSpacing(5)
self.hbox = QHBoxLayout(self)
self.hbox.setContentsMargins(0, 0, 0, 0)
self.hbox.setSpacing(5)
self.cmd = Command(self)
hbox.addWidget(self.cmd)
self.hbox.addWidget(self.cmd)
self.txt = Text(self)
hbox.addWidget(self.txt)
hbox.addStretch()
self.hbox.addWidget(self.txt)
self.hbox.addStretch()
self.keystring = KeyString(self)
hbox.addWidget(self.keystring)
self.hbox.addWidget(self.keystring)
self.url = Url(self)
hbox.addWidget(self.url)
self.hbox.addWidget(self.url)
self.percentage = Percentage(self)
hbox.addWidget(self.percentage)
self.hbox.addWidget(self.percentage)
self.prog = Progress(self)
hbox.addWidget(self.prog)
self.hbox.addWidget(self.prog)
@pyqtProperty(bool)
def error(self):
@ -109,10 +112,11 @@ class StatusBar(QWidget):
def paintEvent(self, e):
"""Override QWIidget.paintEvent to handle stylesheets."""
# pylint: disable=unused-argument
option = QStyleOption()
option.initFrom(self)
painter = QPainter(self)
self.style().drawPrimitive(QStyle.PE_Widget, option, painter, self)
self._option = QStyleOption()
self._option.initFrom(self)
self._painter = QPainter(self)
self.style().drawPrimitive(QStyle.PE_Widget, self._option,
self._painter, self)
def disp_error(self, text):
"""Displaysan error in the statusbar."""
@ -157,6 +161,7 @@ class Command(QLineEdit):
tab_pressed = pyqtSignal(bool) # Emitted when tab is pressed (arg: shift)
hide_completion = pyqtSignal() # Hide completion window
history = [] # The command history, with newer commands at the bottom
_shortcuts = []
_tmphist = []
_histpos = None
@ -191,6 +196,7 @@ class Command(QLineEdit):
sc.setKey(QKeySequence(key))
sc.setContext(Qt.WidgetWithChildrenShortcut)
sc.activated.connect(handler)
self._shortcuts.append(sc)
def process_cmdline(self):
"""Handle the command in the status bar."""
@ -345,6 +351,7 @@ class TextBase(QLabel):
elidemode = None
_elided_text = None
_painter = None
def __init__(self, bar, elidemode=Qt.ElideRight):
super().__init__(bar)
@ -375,10 +382,10 @@ class TextBase(QLabel):
if self.elidemode == Qt.ElideNone:
super().paintEvent(e)
else:
painter = QPainter(self)
geom = self.geometry()
painter.drawText(0, 0, geom.width(), geom.height(),
self.alignment(), self._elided_text)
self._painter = QPainter(self)
self._painter.drawText(0, 0, self.geometry().width(),
self.geometry().height(), self.alignment(),
self._elided_text)
class Text(TextBase):