Merge remote-tracking branch 'origin/pr/3908'

This commit is contained in:
Florian Bruhin 2018-06-11 12:06:09 +02:00
commit 1c8d470bd7
9 changed files with 97 additions and 1 deletions

View File

@ -111,6 +111,7 @@ It is possible to run or bind multiple commands by separating them with `;;`.
|<<tab-focus,tab-focus>>|Select the tab given as argument/[count]. |<<tab-focus,tab-focus>>|Select the tab given as argument/[count].
|<<tab-give,tab-give>>|Give the current tab to a new or existing window if win_id given. |<<tab-give,tab-give>>|Give the current tab to a new or existing window if win_id given.
|<<tab-move,tab-move>>|Move the current tab according to the argument and [count]. |<<tab-move,tab-move>>|Move the current tab according to the argument and [count].
|<<tab-mute,tab-mute>>|Mute/Unmute the current/[count]th tab.
|<<tab-next,tab-next>>|Switch to the next tab, or switch [count] tabs forward. |<<tab-next,tab-next>>|Switch to the next tab, or switch [count] tabs forward.
|<<tab-only,tab-only>>|Close all tabs except for the current one. |<<tab-only,tab-only>>|Close all tabs except for the current one.
|<<tab-pin,tab-pin>>|Pin/Unpin the current/[count]th tab. |<<tab-pin,tab-pin>>|Pin/Unpin the current/[count]th tab.
@ -1284,6 +1285,13 @@ If moving relatively: Offset. If moving absolutely: New position (default: 0). T
overrides the index argument, if given. overrides the index argument, if given.
[[tab-mute]]
=== tab-mute
Mute/Unmute the current/[count]th tab.
==== count
The tab index to pin or unpin
[[tab-next]] [[tab-next]]
=== tab-next === tab-next
Switch to the next tab, or switch [count] tabs forward. Switch to the next tab, or switch [count] tabs forward.

View File

@ -3062,6 +3062,7 @@ The following placeholders are defined:
* `{private}`: Indicates when private mode is enabled. * `{private}`: Indicates when private mode is enabled.
* `{current_url}`: URL of the current web page. * `{current_url}`: URL of the current web page.
* `{protocol}`: Protocol (http/https/...) of the current web page. * `{protocol}`: Protocol (http/https/...) of the current web page.
* `{muted}`: Icon if the tab is muted
Type: <<types,FormatString>> Type: <<types,FormatString>>

View File

@ -656,6 +656,8 @@ class AbstractTab(QWidget):
fullscreen_requested = pyqtSignal(bool) fullscreen_requested = pyqtSignal(bool)
renderer_process_terminated = pyqtSignal(TerminationStatus, int) renderer_process_terminated = pyqtSignal(TerminationStatus, int)
predicted_navigation = pyqtSignal(QUrl) predicted_navigation = pyqtSignal(QUrl)
audio_muted_changed = pyqtSignal(bool)
recently_audible_changed = pyqtSignal(bool)
def __init__(self, *, win_id, mode_manager, private, parent=None): def __init__(self, *, win_id, mode_manager, private, parent=None):
self.private = private self.private = private
@ -930,3 +932,15 @@ class AbstractTab(QWidget):
def is_deleted(self): def is_deleted(self):
return sip.isdeleted(self._widget) return sip.isdeleted(self._widget)
def set_muted(self, muted: bool):
"""Set this tab as muted or not."""
raise NotImplementedError
def is_muted(self):
"""Whether this tab is muted."""
raise NotImplementedError
def is_recently_audible(self):
"""Whether this tab has had audio playing recently."""
raise NotImplementedError

View File

@ -2224,3 +2224,20 @@ class CommandDispatcher:
window = self._tabbed_browser.widget.window() window = self._tabbed_browser.widget.window()
window.setWindowState(window.windowState() ^ Qt.WindowFullScreen) window.setWindowState(window.windowState() ^ Qt.WindowFullScreen)
@cmdutils.register(instance='command-dispatcher', scope='window',
name='tab-mute')
@cmdutils.argument('count', count=True)
def tab_mute(self, count=None):
"""Mute/Unmute the current/[count]th tab.
Args:
count: The tab index to mute or unmute, or None
"""
tab = self._cntwidget(count)
if tab is None:
return
try:
tab.set_muted(not tab.is_muted())
except browsertab.WebTabError as e:
raise cmdexc.CommandError(e)

View File

@ -1118,6 +1118,8 @@ class WebEngineTab(browsertab.AbstractTab):
page.fullScreenRequested.connect(self._on_fullscreen_requested) page.fullScreenRequested.connect(self._on_fullscreen_requested)
page.contentsSizeChanged.connect(self.contents_size_changed) page.contentsSizeChanged.connect(self.contents_size_changed)
page.navigation_request.connect(self._on_navigation_request) page.navigation_request.connect(self._on_navigation_request)
page.audioMutedChanged.connect(self.audio_muted_changed)
page.recentlyAudibleChanged.connect(self.recently_audible_changed)
view.titleChanged.connect(self.title_changed) view.titleChanged.connect(self.title_changed)
view.urlChanged.connect(self._on_url_changed) view.urlChanged.connect(self._on_url_changed)
@ -1142,3 +1144,15 @@ class WebEngineTab(browsertab.AbstractTab):
def event_target(self): def event_target(self):
return self._widget.render_widget() return self._widget.render_widget()
def set_muted(self, muted: bool):
page = self._widget.page()
page.setAudioMuted(muted)
def is_muted(self):
page = self._widget.page()
return page.isAudioMuted()
def is_recently_audible(self):
page = self._widget.page()
return page.recentlyAudible()

View File

@ -839,3 +839,14 @@ class WebKitTab(browsertab.AbstractTab):
def event_target(self): def event_target(self):
return self._widget return self._widget
def set_muted(self, muted: bool):
raise browsertab.WebTabError('Muting is not supported on QtWebKit!')
def is_muted(self):
# Dummy value for things that read muted status
return False
def is_recently_audible(self):
# Dummy value for things that read audible status
return False

View File

@ -1359,7 +1359,7 @@ tabs.title.alignment:
desc: Alignment of the text inside of tabs. desc: Alignment of the text inside of tabs.
tabs.title.format: tabs.title.format:
default: '{index}: {title}' default: '{audio}{index}: {title}'
type: type:
name: FormatString name: FormatString
fields: fields:
@ -1374,6 +1374,7 @@ tabs.title.format:
- private - private
- current_url - current_url
- protocol - protocol
- audio
none_ok: true none_ok: true
desc: | desc: |
Format to use for the tab title. Format to use for the tab title.
@ -1391,6 +1392,7 @@ tabs.title.format:
* `{private}`: Indicates when private mode is enabled. * `{private}`: Indicates when private mode is enabled.
* `{current_url}`: URL of the current web page. * `{current_url}`: URL of the current web page.
* `{protocol}`: Protocol (http/https/...) of the current web page. * `{protocol}`: Protocol (http/https/...) of the current web page.
* `{audio}`: Indicator for audio/mute status
tabs.title.format_pinned: tabs.title.format_pinned:
default: '{index}' default: '{index}'
@ -1408,6 +1410,7 @@ tabs.title.format_pinned:
- private - private
- current_url - current_url
- protocol - protocol
- audio
none_ok: true none_ok: true
desc: Format to use for the tab title for pinned tabs. The same placeholders desc: Format to use for the tab title for pinned tabs. The same placeholders
like for `tabs.title.format` are defined. like for `tabs.title.format` are defined.
@ -1575,6 +1578,7 @@ window.title_format:
- private - private
- current_url - current_url
- protocol - protocol
- audio
default: '{perc}{title}{title_sep}qutebrowser' default: '{perc}{title}{title_sep}qutebrowser'
desc: | desc: |
Format to use for the window title. The same placeholders like for Format to use for the window title. The same placeholders like for
@ -2378,6 +2382,7 @@ bindings.default:
<Ctrl-Return>: follow-selected -t <Ctrl-Return>: follow-selected -t
.: repeat-command .: repeat-command
<Ctrl-p>: tab-pin <Ctrl-p>: tab-pin
<Alt-m>: tab-mute
q: record-macro q: record-macro
"@": run-macro "@": run-macro
tsh: config-cycle -p -t -u *://{url:host}/* content.javascript.enabled ;; reload tsh: config-cycle -p -t -u *://{url:host}/* content.javascript.enabled ;; reload

View File

@ -238,6 +238,10 @@ class TabbedBrowser(QWidget):
functools.partial(self.on_window_close_requested, tab)) functools.partial(self.on_window_close_requested, tab))
tab.renderer_process_terminated.connect( tab.renderer_process_terminated.connect(
functools.partial(self._on_renderer_process_terminated, tab)) functools.partial(self._on_renderer_process_terminated, tab))
tab.audio_muted_changed.connect(
functools.partial(self._on_audio_changed, tab))
tab.recently_audible_changed.connect(
functools.partial(self._on_audio_changed, tab))
tab.new_tab_requested.connect(self.tabopen) tab.new_tab_requested.connect(self.tabopen)
if not self.private: if not self.private:
web_history = objreg.get('web-history') web_history = objreg.get('web-history')
@ -734,6 +738,17 @@ class TabbedBrowser(QWidget):
self._update_window_title('scroll_pos') self._update_window_title('scroll_pos')
self.widget.update_tab_title(idx, 'scroll_pos') self.widget.update_tab_title(idx, 'scroll_pos')
def _on_audio_changed(self, tab, _muted):
"""Update audio field in tab when mute or recentlyAudible changed."""
try:
idx = self._tab_index(tab)
except TabDeletedError:
# We can get signals for tabs we already deleted...
return
self.widget.update_tab_title(idx, 'audio')
if idx == self.widget.currentIndex():
self._update_window_title('audio')
def _on_renderer_process_terminated(self, tab, status, code): def _on_renderer_process_terminated(self, tab, status, code):
"""Show an error when a renderer process terminated.""" """Show an error when a renderer process terminated."""
if status == browsertab.TerminationStatus.normal: if status == browsertab.TerminationStatus.normal:

View File

@ -33,6 +33,7 @@ from PyQt5.QtGui import QIcon, QPalette, QColor
from qutebrowser.utils import qtutils, objreg, utils, usertypes, log from qutebrowser.utils import qtutils, objreg, utils, usertypes, log
from qutebrowser.config import config from qutebrowser.config import config
from qutebrowser.misc import objects from qutebrowser.misc import objects
from qutebrowser.browser import browsertab
PixelMetrics = enum.IntEnum('PixelMetrics', ['icon_padding'], PixelMetrics = enum.IntEnum('PixelMetrics', ['icon_padding'],
@ -172,6 +173,16 @@ class TabWidget(QTabWidget):
fields['perc_raw'] = tab.progress() fields['perc_raw'] = tab.progress()
fields['backend'] = objects.backend.name fields['backend'] = objects.backend.name
fields['private'] = ' [Private Mode] ' if tab.private else '' fields['private'] = ' [Private Mode] ' if tab.private else ''
try:
if tab.is_muted():
fields['audio'] = '[M] '
elif tab.is_recently_audible():
fields['audio'] = '[A] '
else:
fields['audio'] = ''
except browsertab.WebTabError:
# Muting is only implemented with QtWebEngine
fields['audio'] = ''
if tab.load_status() == usertypes.LoadStatus.loading: if tab.load_status() == usertypes.LoadStatus.loading:
fields['perc'] = '[{}%] '.format(tab.progress()) fields['perc'] = '[{}%] '.format(tab.progress())