Reordering in widget submodules
This commit is contained in:
parent
133d720de5
commit
96747c9d58
@ -102,6 +102,118 @@ class TabbedBrowser(TabWidget):
|
|||||||
self._space.setContext(Qt.WidgetWithChildrenShortcut)
|
self._space.setContext(Qt.WidgetWithChildrenShortcut)
|
||||||
self._space.activated.connect(lambda: self.cur_scroll_page(0, 1))
|
self._space.activated.connect(lambda: self.cur_scroll_page(0, 1))
|
||||||
|
|
||||||
|
def _cb_tab_shutdown(self, tab):
|
||||||
|
"""Called after a tab has been shut down completely."""
|
||||||
|
try:
|
||||||
|
self._tabs.remove(tab)
|
||||||
|
except ValueError:
|
||||||
|
logging.exception("tab {} could not be removed".format(tab))
|
||||||
|
logging.debug("Tabs after removing: {}".format(self._tabs))
|
||||||
|
if not self._tabs: # all tabs shut down
|
||||||
|
logging.debug("Tab shutdown complete.")
|
||||||
|
self.shutdown_complete.emit()
|
||||||
|
|
||||||
|
def _cur_scroll_percent(self, perc=None, count=None, orientation=None):
|
||||||
|
"""Inner logic for cur_scroll_percent_(x|y)."""
|
||||||
|
if perc is None and count is None:
|
||||||
|
perc = 100
|
||||||
|
elif perc is None:
|
||||||
|
perc = int(count)
|
||||||
|
else:
|
||||||
|
perc = float(perc)
|
||||||
|
frame = self.currentWidget().page_.mainFrame()
|
||||||
|
m = frame.scrollBarMaximum(orientation)
|
||||||
|
if m == 0:
|
||||||
|
return
|
||||||
|
frame.setScrollBarValue(orientation, int(m * perc / 100))
|
||||||
|
|
||||||
|
def _widget(self, count=None):
|
||||||
|
"""Return a widget based on a count/idx.
|
||||||
|
|
||||||
|
If count is None, return the current widget.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if count is None:
|
||||||
|
return self.currentWidget()
|
||||||
|
elif 1 <= count <= self.count():
|
||||||
|
return self.widget(count - 1)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _titleChanged_handler(self, text):
|
||||||
|
"""Set the title of a tab.
|
||||||
|
|
||||||
|
Slot for the titleChanged signal of any tab.
|
||||||
|
|
||||||
|
"""
|
||||||
|
logging.debug('title changed to "{}"'.format(text))
|
||||||
|
if text:
|
||||||
|
self.setTabText(self.indexOf(self.sender()), text)
|
||||||
|
else:
|
||||||
|
logging.debug('ignoring title change')
|
||||||
|
|
||||||
|
def _filter_factory(self, signal):
|
||||||
|
"""Return a partial functon calling _filter_signals with a signal."""
|
||||||
|
return functools.partial(self._filter_signals, signal)
|
||||||
|
|
||||||
|
def _filter_signals(self, signal, *args):
|
||||||
|
"""Filter signals and trigger TabbedBrowser signals if needed.
|
||||||
|
|
||||||
|
Triggers signal if the original signal was sent from the _current_ tab
|
||||||
|
and not from any other one.
|
||||||
|
|
||||||
|
The original signal does not matter, since we get the new signal and
|
||||||
|
all args.
|
||||||
|
|
||||||
|
The current value of the signal is also stored in tab.signal_cache so
|
||||||
|
it can be emitted later when the tab changes to the current tab.
|
||||||
|
|
||||||
|
signal -- The signal to emit if the sender was the current widget.
|
||||||
|
*args -- The args to pass to the signal.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# FIXME BUG the signal cache ordering seems to be weird sometimes.
|
||||||
|
# How to reproduce:
|
||||||
|
# - Open tab
|
||||||
|
# - While loading, open another tab
|
||||||
|
# - Switch back to #1 when loading finished
|
||||||
|
# - It seems loadingStarted is before loadingFinished
|
||||||
|
sender = self.sender()
|
||||||
|
log_signal = not signal.signal.startswith('2cur_progress')
|
||||||
|
if log_signal:
|
||||||
|
logging.debug('signal {} (tab {})'.format(dbg_signal(signal, args),
|
||||||
|
self.indexOf(sender)))
|
||||||
|
if not isinstance(sender, BrowserTab):
|
||||||
|
# FIXME why does this happen?
|
||||||
|
logging.warn('Got signal {} by {} which is no tab!'.format(
|
||||||
|
dbg_signal(signal, args), sender))
|
||||||
|
return
|
||||||
|
sender.signal_cache.add(signal, args)
|
||||||
|
if self.currentWidget() == sender:
|
||||||
|
if log_signal:
|
||||||
|
logging.debug(' emitting')
|
||||||
|
return signal.emit(*args)
|
||||||
|
else:
|
||||||
|
if log_signal:
|
||||||
|
logging.debug(' ignoring')
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
"""Try to shut down all tabs cleanly."""
|
||||||
|
try:
|
||||||
|
self.currentChanged.disconnect()
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
tabcount = self.count()
|
||||||
|
if tabcount == 0:
|
||||||
|
logging.debug("No tabs -> shutdown complete")
|
||||||
|
self.shutdown_complete.emit()
|
||||||
|
return
|
||||||
|
for tabidx in range(tabcount):
|
||||||
|
logging.debug("Shutting down tab {}/{}".format(tabidx, tabcount))
|
||||||
|
tab = self.widget(tabidx)
|
||||||
|
tab.shutdown(callback=functools.partial(self._cb_tab_shutdown,
|
||||||
|
tab))
|
||||||
|
|
||||||
def tabopen(self, url):
|
def tabopen(self, url):
|
||||||
"""Open a new tab with a given url.
|
"""Open a new tab with a given url.
|
||||||
|
|
||||||
@ -136,17 +248,6 @@ class TabbedBrowser(TabWidget):
|
|||||||
url = urlutils.urlstring(self.currentWidget().url())
|
url = urlutils.urlstring(self.currentWidget().url())
|
||||||
self.set_cmd_text.emit(':tabopen ' + url)
|
self.set_cmd_text.emit(':tabopen ' + url)
|
||||||
|
|
||||||
def openurl(self, url, count=None):
|
|
||||||
"""Open an url in the current/[count]th tab.
|
|
||||||
|
|
||||||
Command handler for :open.
|
|
||||||
url -- The URL to open.
|
|
||||||
|
|
||||||
"""
|
|
||||||
tab = self._widget(count)
|
|
||||||
if tab is not None:
|
|
||||||
tab.openurl(url)
|
|
||||||
|
|
||||||
def opencur(self):
|
def opencur(self):
|
||||||
"""Set the statusbar to :open and the current URL."""
|
"""Set the statusbar to :open and the current URL."""
|
||||||
url = urlutils.urlstring(self.currentWidget().url())
|
url = urlutils.urlstring(self.currentWidget().url())
|
||||||
@ -183,16 +284,16 @@ class TabbedBrowser(TabWidget):
|
|||||||
elif last_close == 'blank':
|
elif last_close == 'blank':
|
||||||
tab.openurl('about:blank')
|
tab.openurl('about:blank')
|
||||||
|
|
||||||
def _cb_tab_shutdown(self, tab):
|
def openurl(self, url, count=None):
|
||||||
"""Called after a tab has been shut down completely."""
|
"""Open an url in the current/[count]th tab.
|
||||||
try:
|
|
||||||
self._tabs.remove(tab)
|
Command handler for :open.
|
||||||
except ValueError:
|
url -- The URL to open.
|
||||||
logging.exception("tab {} could not be removed".format(tab))
|
|
||||||
logging.debug("Tabs after removing: {}".format(self._tabs))
|
"""
|
||||||
if not self._tabs: # all tabs shut down
|
tab = self._widget(count)
|
||||||
logging.debug("Tab shutdown complete.")
|
if tab is not None:
|
||||||
self.shutdown_complete.emit()
|
tab.openurl(url)
|
||||||
|
|
||||||
def cur_reload(self, count=None):
|
def cur_reload(self, count=None):
|
||||||
"""Reload the current/[count]th tab.
|
"""Reload the current/[count]th tab.
|
||||||
@ -289,20 +390,6 @@ class TabbedBrowser(TabWidget):
|
|||||||
"""
|
"""
|
||||||
self._cur_scroll_percent(perc, count, Qt.Vertical)
|
self._cur_scroll_percent(perc, count, Qt.Vertical)
|
||||||
|
|
||||||
def _cur_scroll_percent(self, perc=None, count=None, orientation=None):
|
|
||||||
"""Inner logic for cur_scroll_percent_(x|y)."""
|
|
||||||
if perc is None and count is None:
|
|
||||||
perc = 100
|
|
||||||
elif perc is None:
|
|
||||||
perc = int(count)
|
|
||||||
else:
|
|
||||||
perc = float(perc)
|
|
||||||
frame = self.currentWidget().page_.mainFrame()
|
|
||||||
m = frame.scrollBarMaximum(orientation)
|
|
||||||
if m == 0:
|
|
||||||
return
|
|
||||||
frame.setScrollBarValue(orientation, int(m * perc / 100))
|
|
||||||
|
|
||||||
def cur_scroll_page(self, mx, my, count=1):
|
def cur_scroll_page(self, mx, my, count=1):
|
||||||
"""Scroll the frame mx pages to the right and my pages down."""
|
"""Scroll the frame mx pages to the right and my pages down."""
|
||||||
# FIXME this might not work with HTML frames
|
# FIXME this might not work with HTML frames
|
||||||
@ -311,6 +398,30 @@ class TabbedBrowser(TabWidget):
|
|||||||
page.mainFrame().scroll(int(count) * float(mx) * size.width(),
|
page.mainFrame().scroll(int(count) * float(mx) * size.width(),
|
||||||
int(count) * float(my) * size.height())
|
int(count) * float(my) * size.height())
|
||||||
|
|
||||||
|
def cur_yank(self, sel=False):
|
||||||
|
"""Yank the current url to the clipboard or primary selection.
|
||||||
|
|
||||||
|
Command handler for :yank.
|
||||||
|
|
||||||
|
"""
|
||||||
|
clip = QApplication.clipboard()
|
||||||
|
url = urlutils.urlstring(self.currentWidget().url())
|
||||||
|
mode = QClipboard.Selection if sel else QClipboard.Clipboard
|
||||||
|
clip.setText(url, mode)
|
||||||
|
# FIXME provide visual feedback
|
||||||
|
|
||||||
|
def cur_yank_title(self, sel=False):
|
||||||
|
"""Yank the current title to the clipboard or primary selection.
|
||||||
|
|
||||||
|
Command handler for :yanktitle.
|
||||||
|
|
||||||
|
"""
|
||||||
|
clip = QApplication.clipboard()
|
||||||
|
title = self.tabText(self.currentIndex())
|
||||||
|
mode = QClipboard.Selection if sel else QClipboard.Clipboard
|
||||||
|
clip.setText(title, mode)
|
||||||
|
# FIXME provide visual feedbac
|
||||||
|
|
||||||
def switch_prev(self, count=1):
|
def switch_prev(self, count=1):
|
||||||
"""Switch to the ([count]th) previous tab.
|
"""Switch to the ([count]th) previous tab.
|
||||||
|
|
||||||
@ -337,30 +448,6 @@ class TabbedBrowser(TabWidget):
|
|||||||
# FIXME
|
# FIXME
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def cur_yank(self, sel=False):
|
|
||||||
"""Yank the current url to the clipboard or primary selection.
|
|
||||||
|
|
||||||
Command handler for :yank.
|
|
||||||
|
|
||||||
"""
|
|
||||||
clip = QApplication.clipboard()
|
|
||||||
url = urlutils.urlstring(self.currentWidget().url())
|
|
||||||
mode = QClipboard.Selection if sel else QClipboard.Clipboard
|
|
||||||
clip.setText(url, mode)
|
|
||||||
# FIXME provide visual feedback
|
|
||||||
|
|
||||||
def cur_yank_title(self, sel=False):
|
|
||||||
"""Yank the current title to the clipboard or primary selection.
|
|
||||||
|
|
||||||
Command handler for :yanktitle.
|
|
||||||
|
|
||||||
"""
|
|
||||||
clip = QApplication.clipboard()
|
|
||||||
title = self.tabText(self.currentIndex())
|
|
||||||
mode = QClipboard.Selection if sel else QClipboard.Clipboard
|
|
||||||
clip.setText(title, mode)
|
|
||||||
# FIXME provide visual feedbac
|
|
||||||
|
|
||||||
def paste(self, sel=False):
|
def paste(self, sel=False):
|
||||||
"""Open a page from the clipboard.
|
"""Open a page from the clipboard.
|
||||||
|
|
||||||
@ -392,93 +479,6 @@ class TabbedBrowser(TabWidget):
|
|||||||
self.keypress.emit(e)
|
self.keypress.emit(e)
|
||||||
super().keyPressEvent(e)
|
super().keyPressEvent(e)
|
||||||
|
|
||||||
def _widget(self, count=None):
|
|
||||||
"""Return a widget based on a count/idx.
|
|
||||||
|
|
||||||
If count is None, return the current widget.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if count is None:
|
|
||||||
return self.currentWidget()
|
|
||||||
elif 1 <= count <= self.count():
|
|
||||||
return self.widget(count - 1)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _titleChanged_handler(self, text):
|
|
||||||
"""Set the title of a tab.
|
|
||||||
|
|
||||||
Slot for the titleChanged signal of any tab.
|
|
||||||
|
|
||||||
"""
|
|
||||||
logging.debug('title changed to "{}"'.format(text))
|
|
||||||
if text:
|
|
||||||
self.setTabText(self.indexOf(self.sender()), text)
|
|
||||||
else:
|
|
||||||
logging.debug('ignoring title change')
|
|
||||||
|
|
||||||
def _filter_factory(self, signal):
|
|
||||||
"""Return a partial functon calling _filter_signals with a signal."""
|
|
||||||
return functools.partial(self._filter_signals, signal)
|
|
||||||
|
|
||||||
def _filter_signals(self, signal, *args):
|
|
||||||
"""Filter signals and trigger TabbedBrowser signals if needed.
|
|
||||||
|
|
||||||
Triggers signal if the original signal was sent from the _current_ tab
|
|
||||||
and not from any other one.
|
|
||||||
|
|
||||||
The original signal does not matter, since we get the new signal and
|
|
||||||
all args.
|
|
||||||
|
|
||||||
The current value of the signal is also stored in tab.signal_cache so
|
|
||||||
it can be emitted later when the tab changes to the current tab.
|
|
||||||
|
|
||||||
signal -- The signal to emit if the sender was the current widget.
|
|
||||||
*args -- The args to pass to the signal.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# FIXME BUG the signal cache ordering seems to be weird sometimes.
|
|
||||||
# How to reproduce:
|
|
||||||
# - Open tab
|
|
||||||
# - While loading, open another tab
|
|
||||||
# - Switch back to #1 when loading finished
|
|
||||||
# - It seems loadingStarted is before loadingFinished
|
|
||||||
sender = self.sender()
|
|
||||||
log_signal = not signal.signal.startswith('2cur_progress')
|
|
||||||
if log_signal:
|
|
||||||
logging.debug('signal {} (tab {})'.format(dbg_signal(signal, args),
|
|
||||||
self.indexOf(sender)))
|
|
||||||
if not isinstance(sender, BrowserTab):
|
|
||||||
# FIXME why does this happen?
|
|
||||||
logging.warn('Got signal {} by {} which is no tab!'.format(
|
|
||||||
dbg_signal(signal, args), sender))
|
|
||||||
return
|
|
||||||
sender.signal_cache.add(signal, args)
|
|
||||||
if self.currentWidget() == sender:
|
|
||||||
if log_signal:
|
|
||||||
logging.debug(' emitting')
|
|
||||||
return signal.emit(*args)
|
|
||||||
else:
|
|
||||||
if log_signal:
|
|
||||||
logging.debug(' ignoring')
|
|
||||||
|
|
||||||
def shutdown(self):
|
|
||||||
"""Try to shut down all tabs cleanly."""
|
|
||||||
try:
|
|
||||||
self.currentChanged.disconnect()
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
tabcount = self.count()
|
|
||||||
if tabcount == 0:
|
|
||||||
logging.debug("No tabs -> shutdown complete")
|
|
||||||
self.shutdown_complete.emit()
|
|
||||||
return
|
|
||||||
for tabidx in range(tabcount):
|
|
||||||
logging.debug("Shutting down tab {}/{}".format(tabidx, tabcount))
|
|
||||||
tab = self.widget(tabidx)
|
|
||||||
tab.shutdown(callback=functools.partial(self._cb_tab_shutdown,
|
|
||||||
tab))
|
|
||||||
|
|
||||||
|
|
||||||
class BrowserTab(QWebView):
|
class BrowserTab(QWebView):
|
||||||
|
|
||||||
@ -664,18 +664,6 @@ class BrowserPage(QWebPage):
|
|||||||
self.network_access_manager = NetworkManager(self)
|
self.network_access_manager = NetworkManager(self)
|
||||||
self.setNetworkAccessManager(self.network_access_manager)
|
self.setNetworkAccessManager(self.network_access_manager)
|
||||||
|
|
||||||
def supportsExtension(self, ext):
|
|
||||||
"""Override QWebPage::supportsExtension to provide error pages."""
|
|
||||||
return ext in self._extension_handlers
|
|
||||||
|
|
||||||
def extension(self, ext, opt, out):
|
|
||||||
"""Override QWebPage::extension to provide error pages."""
|
|
||||||
try:
|
|
||||||
handler = self._extension_handlers[ext]
|
|
||||||
except KeyError:
|
|
||||||
return super().extension(ext, opt, out)
|
|
||||||
return handler(opt, out)
|
|
||||||
|
|
||||||
def _handle_errorpage(self, opt, out):
|
def _handle_errorpage(self, opt, out):
|
||||||
"""Display an error page if needed.
|
"""Display an error page if needed.
|
||||||
|
|
||||||
@ -695,6 +683,18 @@ class BrowserPage(QWebPage):
|
|||||||
title=title, url=urlstr, error=info.errorString, icon='')
|
title=title, url=urlstr, error=info.errorString, icon='')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def supportsExtension(self, ext):
|
||||||
|
"""Override QWebPage::supportsExtension to provide error pages."""
|
||||||
|
return ext in self._extension_handlers
|
||||||
|
|
||||||
|
def extension(self, ext, opt, out):
|
||||||
|
"""Override QWebPage::extension to provide error pages."""
|
||||||
|
try:
|
||||||
|
handler = self._extension_handlers[ext]
|
||||||
|
except KeyError:
|
||||||
|
return super().extension(ext, opt, out)
|
||||||
|
return handler(opt, out)
|
||||||
|
|
||||||
|
|
||||||
class NetworkManager(QNetworkAccessManager):
|
class NetworkManager(QNetworkAccessManager):
|
||||||
|
|
||||||
|
@ -121,6 +121,29 @@ class CompletionView(QTreeView):
|
|||||||
self.hide()
|
self.hide()
|
||||||
# FIXME set elidemode
|
# FIXME set elidemode
|
||||||
|
|
||||||
|
def _next_idx(self, upwards):
|
||||||
|
"""Get the previous/next QModelIndex displayed in the view.
|
||||||
|
|
||||||
|
Used by tab_handler.
|
||||||
|
|
||||||
|
upwards -- Get previous item, not next.
|
||||||
|
|
||||||
|
"""
|
||||||
|
idx = self.selectionModel().currentIndex()
|
||||||
|
if not idx.isValid():
|
||||||
|
# No item selected yet
|
||||||
|
return self.model.first_item()
|
||||||
|
while True:
|
||||||
|
idx = self.indexAbove(idx) if upwards else self.indexBelow(idx)
|
||||||
|
# wrap around if we arrived at beginning/end
|
||||||
|
if not idx.isValid() and upwards:
|
||||||
|
return self.model.last_item()
|
||||||
|
elif not idx.isValid() and not upwards:
|
||||||
|
return self.model.first_item()
|
||||||
|
elif idx.parent().isValid():
|
||||||
|
# Item is a real item, not a category header -> success
|
||||||
|
return idx
|
||||||
|
|
||||||
def setmodel(self, model):
|
def setmodel(self, model):
|
||||||
"""Switch completion to a new model.
|
"""Switch completion to a new model.
|
||||||
|
|
||||||
@ -205,29 +228,6 @@ class CompletionView(QTreeView):
|
|||||||
self._ignore_next = True
|
self._ignore_next = True
|
||||||
self.append_cmd_text.emit(self.model.data(idx) + ' ')
|
self.append_cmd_text.emit(self.model.data(idx) + ' ')
|
||||||
|
|
||||||
def _next_idx(self, upwards):
|
|
||||||
"""Get the previous/next QModelIndex displayed in the view.
|
|
||||||
|
|
||||||
Used by tab_handler.
|
|
||||||
|
|
||||||
upwards -- Get previous item, not next.
|
|
||||||
|
|
||||||
"""
|
|
||||||
idx = self.selectionModel().currentIndex()
|
|
||||||
if not idx.isValid():
|
|
||||||
# No item selected yet
|
|
||||||
return self.model.first_item()
|
|
||||||
while True:
|
|
||||||
idx = self.indexAbove(idx) if upwards else self.indexBelow(idx)
|
|
||||||
# wrap around if we arrived at beginning/end
|
|
||||||
if not idx.isValid() and upwards:
|
|
||||||
return self.model.last_item()
|
|
||||||
elif not idx.isValid() and not upwards:
|
|
||||||
return self.model.first_item()
|
|
||||||
elif idx.parent().isValid():
|
|
||||||
# Item is a real item, not a category header -> success
|
|
||||||
return idx
|
|
||||||
|
|
||||||
|
|
||||||
class _CompletionItemDelegate(QStyledItemDelegate):
|
class _CompletionItemDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
@ -254,40 +254,6 @@ class _CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
self._style = None
|
self._style = None
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
def sizeHint(self, option, index):
|
|
||||||
"""Override sizeHint of QStyledItemDelegate.
|
|
||||||
|
|
||||||
Return the cell size based on the QTextDocument size, but might not
|
|
||||||
work correctly yet.
|
|
||||||
|
|
||||||
"""
|
|
||||||
value = index.data(Qt.SizeHintRole)
|
|
||||||
if value is not None:
|
|
||||||
return value
|
|
||||||
self._opt = QStyleOptionViewItem(option)
|
|
||||||
self.initStyleOption(self._opt, index)
|
|
||||||
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."""
|
|
||||||
self._painter = painter
|
|
||||||
self._painter.save()
|
|
||||||
self._opt = QStyleOptionViewItem(option)
|
|
||||||
self.initStyleOption(self._opt, index)
|
|
||||||
self._style = self._opt.widget.style()
|
|
||||||
|
|
||||||
self._draw_background()
|
|
||||||
self._draw_icon()
|
|
||||||
self._draw_text(index)
|
|
||||||
self._draw_focus_rect()
|
|
||||||
|
|
||||||
self._painter.restore()
|
|
||||||
|
|
||||||
def _draw_background(self):
|
def _draw_background(self):
|
||||||
"""Draw the background of an ItemViewItem."""
|
"""Draw the background of an ItemViewItem."""
|
||||||
self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt,
|
self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt,
|
||||||
@ -428,3 +394,37 @@ class _CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
o.backgroundColor = self._opt.palette.color(cg, role)
|
o.backgroundColor = self._opt.palette.color(cg, role)
|
||||||
self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter,
|
self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter,
|
||||||
self._opt.widget)
|
self._opt.widget)
|
||||||
|
|
||||||
|
def sizeHint(self, option, index):
|
||||||
|
"""Override sizeHint of QStyledItemDelegate.
|
||||||
|
|
||||||
|
Return the cell size based on the QTextDocument size, but might not
|
||||||
|
work correctly yet.
|
||||||
|
|
||||||
|
"""
|
||||||
|
value = index.data(Qt.SizeHintRole)
|
||||||
|
if value is not None:
|
||||||
|
return value
|
||||||
|
self._opt = QStyleOptionViewItem(option)
|
||||||
|
self.initStyleOption(self._opt, index)
|
||||||
|
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."""
|
||||||
|
self._painter = painter
|
||||||
|
self._painter.save()
|
||||||
|
self._opt = QStyleOptionViewItem(option)
|
||||||
|
self.initStyleOption(self._opt, index)
|
||||||
|
self._style = self._opt.widget.style()
|
||||||
|
|
||||||
|
self._draw_background()
|
||||||
|
self._draw_icon()
|
||||||
|
self._draw_text(index)
|
||||||
|
self._draw_focus_rect()
|
||||||
|
|
||||||
|
self._painter.restore()
|
||||||
|
@ -226,49 +226,6 @@ class _Command(QLineEdit):
|
|||||||
sc.activated.connect(handler)
|
sc.activated.connect(handler)
|
||||||
self._shortcuts.append(sc)
|
self._shortcuts.append(sc)
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _on_return_pressed(self):
|
|
||||||
"""Handle the command in the status bar."""
|
|
||||||
signals = {
|
|
||||||
':': self.got_cmd,
|
|
||||||
'/': self.got_search,
|
|
||||||
'?': self.got_search_rev,
|
|
||||||
}
|
|
||||||
self._histbrowse_stop()
|
|
||||||
text = self.text()
|
|
||||||
if not self.history or text != self.history[-1]:
|
|
||||||
self.history.append(text)
|
|
||||||
self.setText('')
|
|
||||||
if text[0] in signals:
|
|
||||||
signals[text[0]].emit(text.lstrip(text[0]))
|
|
||||||
|
|
||||||
@pyqtSlot(str)
|
|
||||||
def set_cmd_text(self, text):
|
|
||||||
"""Preset the statusbar to some text."""
|
|
||||||
self.setText(text)
|
|
||||||
self.setFocus()
|
|
||||||
|
|
||||||
@pyqtSlot(str)
|
|
||||||
def on_append_cmd_text(self, text):
|
|
||||||
"""Append text to the commandline."""
|
|
||||||
# FIXME do the right thing here
|
|
||||||
self.setText(':' + text)
|
|
||||||
self.setFocus()
|
|
||||||
|
|
||||||
def focusOutEvent(self, e):
|
|
||||||
"""Clear the statusbar text if it's explicitely unfocused."""
|
|
||||||
if e.reason() in [Qt.MouseFocusReason, Qt.TabFocusReason,
|
|
||||||
Qt.BacktabFocusReason, Qt.OtherFocusReason]:
|
|
||||||
self.setText('')
|
|
||||||
self._histbrowse_stop()
|
|
||||||
self.hide_completion.emit()
|
|
||||||
super().focusOutEvent(e)
|
|
||||||
|
|
||||||
def focusInEvent(self, e):
|
|
||||||
"""Clear error message when the statusbar is focused."""
|
|
||||||
self._statusbar.clear_error()
|
|
||||||
super().focusInEvent(e)
|
|
||||||
|
|
||||||
def _histbrowse_start(self):
|
def _histbrowse_start(self):
|
||||||
"""Start browsing to the history.
|
"""Start browsing to the history.
|
||||||
|
|
||||||
@ -319,6 +276,49 @@ class _Command(QLineEdit):
|
|||||||
self._tmphist, len(self._tmphist), self._histpos))
|
self._tmphist, len(self._tmphist), self._histpos))
|
||||||
self.set_cmd_text(self._tmphist[self._histpos])
|
self.set_cmd_text(self._tmphist[self._histpos])
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def _on_return_pressed(self):
|
||||||
|
"""Handle the command in the status bar."""
|
||||||
|
signals = {
|
||||||
|
':': self.got_cmd,
|
||||||
|
'/': self.got_search,
|
||||||
|
'?': self.got_search_rev,
|
||||||
|
}
|
||||||
|
self._histbrowse_stop()
|
||||||
|
text = self.text()
|
||||||
|
if not self.history or text != self.history[-1]:
|
||||||
|
self.history.append(text)
|
||||||
|
self.setText('')
|
||||||
|
if text[0] in signals:
|
||||||
|
signals[text[0]].emit(text.lstrip(text[0]))
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def set_cmd_text(self, text):
|
||||||
|
"""Preset the statusbar to some text."""
|
||||||
|
self.setText(text)
|
||||||
|
self.setFocus()
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def on_append_cmd_text(self, text):
|
||||||
|
"""Append text to the commandline."""
|
||||||
|
# FIXME do the right thing here
|
||||||
|
self.setText(':' + text)
|
||||||
|
self.setFocus()
|
||||||
|
|
||||||
|
def focusOutEvent(self, e):
|
||||||
|
"""Clear the statusbar text if it's explicitely unfocused."""
|
||||||
|
if e.reason() in [Qt.MouseFocusReason, Qt.TabFocusReason,
|
||||||
|
Qt.BacktabFocusReason, Qt.OtherFocusReason]:
|
||||||
|
self.setText('')
|
||||||
|
self._histbrowse_stop()
|
||||||
|
self.hide_completion.emit()
|
||||||
|
super().focusOutEvent(e)
|
||||||
|
|
||||||
|
def focusInEvent(self, e):
|
||||||
|
"""Clear error message when the statusbar is focused."""
|
||||||
|
self._statusbar.clear_error()
|
||||||
|
super().focusInEvent(e)
|
||||||
|
|
||||||
|
|
||||||
class _CommandValidator(QValidator):
|
class _CommandValidator(QValidator):
|
||||||
|
|
||||||
@ -397,6 +397,15 @@ class TextBase(QLabel):
|
|||||||
self._elidemode = elidemode
|
self._elidemode = elidemode
|
||||||
self._elided_text = ''
|
self._elided_text = ''
|
||||||
|
|
||||||
|
def _update_elided_text(self, width):
|
||||||
|
"""Update the elided text when necessary.
|
||||||
|
|
||||||
|
width -- The maximal width the text should take.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self._elided_text = self.fontMetrics().elidedText(
|
||||||
|
self.text(), self._elidemode, width, Qt.TextShowMnemonic)
|
||||||
|
|
||||||
def setText(self, txt):
|
def setText(self, txt):
|
||||||
"""Extend QLabel::setText to update the elided text afterwards."""
|
"""Extend QLabel::setText to update the elided text afterwards."""
|
||||||
super().setText(txt)
|
super().setText(txt)
|
||||||
@ -407,15 +416,6 @@ class TextBase(QLabel):
|
|||||||
super().resizeEvent(e)
|
super().resizeEvent(e)
|
||||||
self._update_elided_text(e.size().width())
|
self._update_elided_text(e.size().width())
|
||||||
|
|
||||||
def _update_elided_text(self, width):
|
|
||||||
"""Update the elided text when necessary.
|
|
||||||
|
|
||||||
width -- The maximal width the text should take.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self._elided_text = self.fontMetrics().elidedText(
|
|
||||||
self.text(), self._elidemode, width, Qt.TextShowMnemonic)
|
|
||||||
|
|
||||||
def paintEvent(self, e):
|
def paintEvent(self, e):
|
||||||
"""Override QLabel::paintEvent to draw elided text."""
|
"""Override QLabel::paintEvent to draw elided text."""
|
||||||
if self._elidemode == Qt.ElideNone:
|
if self._elidemode == Qt.ElideNone:
|
||||||
|
Loading…
Reference in New Issue
Block a user