mirror of
https://github.com/ankitects/anki.git
synced 2025-09-22 07:52:24 -04:00
Add setting to hide bottom toolbar
This commit is contained in:
parent
e5a946bb1a
commit
ef54865a2c
6 changed files with 124 additions and 47 deletions
|
@ -51,22 +51,20 @@ body {
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&:not(.fancy).collapsed {
|
&:not(.fancy).hidden {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
transition: opacity var(--transition) ease-in-out;
|
transition: opacity var(--transition) ease-in-out;
|
||||||
|
|
||||||
&.fancy {
|
&.fancy {
|
||||||
&.collapsed {
|
margin-bottom: 5px;
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
transform: translateY(-100vh);
|
transform: translateY(-100vh);
|
||||||
}
|
}
|
||||||
transition: transform var(--transition) ease-in-out;
|
transition: transform var(--transition) ease-in-out;
|
||||||
|
|
||||||
.header {
|
|
||||||
height: 41px;
|
|
||||||
}
|
|
||||||
.toolbar {
|
.toolbar {
|
||||||
height: 31px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-bottom-left-radius: prop(border-radius-medium);
|
border-bottom-left-radius: prop(border-radius-medium);
|
||||||
border-bottom-right-radius: prop(border-radius-medium);
|
border-bottom-right-radius: prop(border-radius-medium);
|
||||||
|
|
|
@ -66,7 +66,7 @@ from aqt.qt import sip
|
||||||
from aqt.sync import sync_collection, sync_login
|
from aqt.sync import sync_collection, sync_login
|
||||||
from aqt.taskman import TaskManager
|
from aqt.taskman import TaskManager
|
||||||
from aqt.theme import Theme, theme_manager
|
from aqt.theme import Theme, theme_manager
|
||||||
from aqt.toolbar import Toolbar, ToolbarWebView
|
from aqt.toolbar import BottomWebView, Toolbar, TopWebView
|
||||||
from aqt.undo import UndoActionsInfo
|
from aqt.undo import UndoActionsInfo
|
||||||
from aqt.utils import (
|
from aqt.utils import (
|
||||||
HelpPage,
|
HelpPage,
|
||||||
|
@ -150,17 +150,17 @@ class MainWebView(AnkiWebView):
|
||||||
return handled
|
return handled
|
||||||
|
|
||||||
if evt.type() == QEvent.Type.Leave:
|
if evt.type() == QEvent.Type.Leave:
|
||||||
if self.mw.pm.collapse_toolbar():
|
if self.mw.pm.hide_top_bar():
|
||||||
# Expand toolbar when mouse moves above main webview
|
# Show toolbar when mouse moves outside main webview
|
||||||
# and automatically collapse it with delay after mouse leaves
|
# and automatically hide it with delay after mouse has entered again
|
||||||
if self.mapFromGlobal(QCursor.pos()).y() < self.geometry().y():
|
self.mw.toolbarWeb.show()
|
||||||
if self.mw.toolbarWeb.collapsed:
|
self.mw.bottomWeb.show()
|
||||||
self.mw.toolbarWeb.expand()
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if evt.type() == QEvent.Type.Enter:
|
if evt.type() == QEvent.Type.Enter:
|
||||||
if self.mw.pm.collapse_toolbar():
|
if self.mw.pm.hide_top_bar():
|
||||||
self.mw.toolbarWeb.hide_timer.start()
|
self.mw.toolbarWeb.hide_timer.start()
|
||||||
|
self.mw.bottomWeb.hide_timer.start()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -729,16 +729,21 @@ class AnkiQt(QMainWindow):
|
||||||
|
|
||||||
def _reviewState(self, oldState: MainWindowState) -> None:
|
def _reviewState(self, oldState: MainWindowState) -> None:
|
||||||
self.reviewer.show()
|
self.reviewer.show()
|
||||||
if self.pm.collapse_toolbar():
|
|
||||||
self.toolbarWeb.collapse()
|
if self.pm.hide_top_bar():
|
||||||
|
self.toolbarWeb.hide()
|
||||||
else:
|
else:
|
||||||
self.toolbarWeb.flatten()
|
self.toolbarWeb.flatten()
|
||||||
|
|
||||||
|
if self.pm.hide_bottom_bar():
|
||||||
|
self.bottomWeb.hide()
|
||||||
|
|
||||||
def _reviewCleanup(self, newState: MainWindowState) -> None:
|
def _reviewCleanup(self, newState: MainWindowState) -> None:
|
||||||
if newState != "resetRequired" and newState != "review":
|
if newState != "resetRequired" and newState != "review":
|
||||||
self.reviewer.cleanup()
|
self.reviewer.cleanup()
|
||||||
self.toolbarWeb.elevate()
|
self.toolbarWeb.elevate()
|
||||||
self.toolbarWeb.expand()
|
self.toolbarWeb.show()
|
||||||
|
self.bottomWeb.show()
|
||||||
|
|
||||||
# Resetting state
|
# Resetting state
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
@ -872,12 +877,12 @@ title="{}" {}>{}</button>""".format(
|
||||||
self.form = aqt.forms.main.Ui_MainWindow()
|
self.form = aqt.forms.main.Ui_MainWindow()
|
||||||
self.form.setupUi(self)
|
self.form.setupUi(self)
|
||||||
# toolbar
|
# toolbar
|
||||||
tweb = self.toolbarWeb = ToolbarWebView(self, title="top toolbar")
|
tweb = self.toolbarWeb = TopWebView(self, title="top toolbar")
|
||||||
self.toolbar = Toolbar(self, tweb)
|
self.toolbar = Toolbar(self, tweb)
|
||||||
# main area
|
# main area
|
||||||
self.web = MainWebView(self)
|
self.web = MainWebView(self)
|
||||||
# bottom area
|
# bottom area
|
||||||
sweb = self.bottomWeb = AnkiWebView(title="bottom toolbar")
|
sweb = self.bottomWeb = BottomWebView(self, title="bottom toolbar")
|
||||||
sweb.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
|
sweb.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
|
||||||
sweb.disable_zoom()
|
sweb.disable_zoom()
|
||||||
# add in a layout
|
# add in a layout
|
||||||
|
@ -1358,10 +1363,6 @@ title="{}" {}>{}</button>""".format(
|
||||||
window.windowState() ^ Qt.WindowState.WindowFullScreen
|
window.windowState() ^ Qt.WindowState.WindowFullScreen
|
||||||
)
|
)
|
||||||
|
|
||||||
def collapse_toolbar_if_allowed(self) -> None:
|
|
||||||
if self.pm.collapse_toolbar() and self.state == "review":
|
|
||||||
self.toolbarWeb.collapse()
|
|
||||||
|
|
||||||
# Auto update
|
# Auto update
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
|
|
@ -213,10 +213,11 @@ class Preferences(QDialog):
|
||||||
self.form.minimalist_mode.setChecked(self.mw.pm.minimalist_mode())
|
self.form.minimalist_mode.setChecked(self.mw.pm.minimalist_mode())
|
||||||
qconnect(self.form.minimalist_mode.stateChanged, self.mw.pm.set_minimalist_mode)
|
qconnect(self.form.minimalist_mode.stateChanged, self.mw.pm.set_minimalist_mode)
|
||||||
|
|
||||||
self.form.collapse_toolbar.setChecked(self.mw.pm.collapse_toolbar())
|
self.form.hide_top_bar.setChecked(self.mw.pm.hide_top_bar())
|
||||||
qconnect(
|
qconnect(self.form.hide_top_bar.stateChanged, self.mw.pm.set_hide_top_bar)
|
||||||
self.form.collapse_toolbar.stateChanged, self.mw.pm.set_collapse_toolbar
|
|
||||||
)
|
self.form.hide_bottom_bar.setChecked(self.mw.pm.hide_bottom_bar())
|
||||||
|
qconnect(self.form.hide_bottom_bar.stateChanged, self.mw.pm.set_hide_bottom_bar)
|
||||||
|
|
||||||
self.form.uiScale.setValue(int(self.mw.pm.uiScale() * 100))
|
self.form.uiScale.setValue(int(self.mw.pm.uiScale() * 100))
|
||||||
themes = [
|
themes = [
|
||||||
|
|
|
@ -532,13 +532,19 @@ create table if not exists profiles
|
||||||
self.meta["tatsumoto_mode"] = on
|
self.meta["tatsumoto_mode"] = on
|
||||||
gui_hooks.body_classes_need_update()
|
gui_hooks.body_classes_need_update()
|
||||||
|
|
||||||
def collapse_toolbar(self) -> bool:
|
def hide_top_bar(self) -> bool:
|
||||||
return self.meta.get("collapse_toolbar", False)
|
return self.meta.get("hide_top_bar", False)
|
||||||
|
|
||||||
def set_collapse_toolbar(self, on: bool) -> None:
|
def set_hide_top_bar(self, on: bool) -> None:
|
||||||
self.meta["collapse_toolbar"] = on
|
self.meta["hide_top_bar"] = on
|
||||||
gui_hooks.body_classes_need_update()
|
gui_hooks.body_classes_need_update()
|
||||||
|
|
||||||
|
def hide_bottom_bar(self) -> bool:
|
||||||
|
return self.meta.get("hide_bottom_bar", False)
|
||||||
|
|
||||||
|
def set_hide_bottom_bar(self, on: bool) -> None:
|
||||||
|
self.meta["hide_bottom_bar"] = on
|
||||||
|
|
||||||
def last_addon_update_check(self) -> int:
|
def last_addon_update_check(self) -> int:
|
||||||
return self.meta.get("last_addon_update_check", 0)
|
return self.meta.get("last_addon_update_check", 0)
|
||||||
|
|
||||||
|
|
|
@ -706,7 +706,6 @@ time = %(time)d;
|
||||||
else:
|
else:
|
||||||
maxTime = 0
|
maxTime = 0
|
||||||
self.bottom.web.eval("showQuestion(%s,%d);" % (json.dumps(middle), maxTime))
|
self.bottom.web.eval("showQuestion(%s,%d);" % (json.dumps(middle), maxTime))
|
||||||
self.bottom.web.adjustHeightToFit()
|
|
||||||
|
|
||||||
def _showEaseButtons(self) -> None:
|
def _showEaseButtons(self) -> None:
|
||||||
middle = self._answerButtons()
|
middle = self._answerButtons()
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional, cast
|
||||||
|
|
||||||
import aqt
|
import aqt
|
||||||
from anki.sync import SyncStatus
|
from anki.sync import SyncStatus
|
||||||
from aqt import gui_hooks
|
from aqt import gui_hooks, props
|
||||||
from aqt.qt import *
|
from aqt.qt import *
|
||||||
from aqt.sync import get_sync_status
|
from aqt.sync import get_sync_status
|
||||||
|
from aqt.theme import theme_manager
|
||||||
from aqt.utils import tr
|
from aqt.utils import tr
|
||||||
from aqt.webview import AnkiWebView
|
from aqt.webview import AnkiWebView
|
||||||
|
|
||||||
|
@ -32,13 +33,10 @@ class ToolbarWebView(AnkiWebView):
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
self.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
|
self.setFocusPolicy(Qt.FocusPolicy.WheelFocus)
|
||||||
self.disable_zoom()
|
self.disable_zoom()
|
||||||
self.collapsed = False
|
self.hidden = False
|
||||||
self.web_height = 0
|
|
||||||
# collapse timer
|
|
||||||
self.hide_timer = QTimer()
|
self.hide_timer = QTimer()
|
||||||
self.hide_timer.setSingleShot(True)
|
self.hide_timer.setSingleShot(True)
|
||||||
self.hide_timer.setInterval(1000)
|
self.hide_timer.setInterval(1000)
|
||||||
qconnect(self.hide_timer.timeout, self.mw.collapse_toolbar_if_allowed)
|
|
||||||
|
|
||||||
def eventFilter(self, obj, evt):
|
def eventFilter(self, obj, evt):
|
||||||
if handled := super().eventFilter(obj, evt):
|
if handled := super().eventFilter(obj, evt):
|
||||||
|
@ -52,29 +50,58 @@ class ToolbarWebView(AnkiWebView):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def hide(self) -> None:
|
||||||
|
self.hidden = True
|
||||||
|
|
||||||
|
def show(self) -> None:
|
||||||
|
self.hidden = False
|
||||||
|
|
||||||
|
def hide_if_allowed(self) -> None:
|
||||||
|
if self.mw.state != "review":
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.hide_condition():
|
||||||
|
self.hide()
|
||||||
|
|
||||||
|
|
||||||
|
class TopWebView(ToolbarWebView):
|
||||||
|
def __init__(self, mw: aqt.AnkiQt, title: str) -> None:
|
||||||
|
super().__init__(mw, title=title)
|
||||||
|
self.web_height = 0
|
||||||
|
self.hide_condition = self.mw.pm.hide_top_bar
|
||||||
|
qconnect(self.hide_timer.timeout, self.hide_if_allowed)
|
||||||
|
|
||||||
def on_body_classes_need_update(self) -> None:
|
def on_body_classes_need_update(self) -> None:
|
||||||
super().on_body_classes_need_update()
|
super().on_body_classes_need_update()
|
||||||
super().adjustHeightToFit()
|
self.adjustHeightToFit()
|
||||||
|
|
||||||
if self.mw.state == "review":
|
if self.mw.state == "review":
|
||||||
if self.mw.pm.collapse_toolbar():
|
if self.mw.pm.hide_top_bar():
|
||||||
self.eval("""document.body.classList.remove("flat"); """)
|
self.eval("""document.body.classList.remove("flat"); """)
|
||||||
else:
|
else:
|
||||||
self.flatten()
|
self.flatten()
|
||||||
|
|
||||||
self.expand()
|
self.show()
|
||||||
|
|
||||||
def _onHeight(self, qvar: Optional[int]) -> None:
|
def _onHeight(self, qvar: Optional[int]) -> None:
|
||||||
super()._onHeight(qvar)
|
super()._onHeight(qvar)
|
||||||
self.web_height = int(qvar)
|
self.web_height = int(qvar)
|
||||||
|
|
||||||
def collapse(self) -> None:
|
def hide(self) -> None:
|
||||||
self.collapsed = True
|
super().hide()
|
||||||
self.eval("""document.body.classList.add("collapsed"); """)
|
|
||||||
|
|
||||||
def expand(self) -> None:
|
self.hidden = True
|
||||||
self.collapsed = False
|
self.eval(
|
||||||
self.eval("""document.body.classList.remove("collapsed"); """)
|
"""document.body.classList.add("hidden"); """,
|
||||||
|
)
|
||||||
|
self.mw.web.eval(
|
||||||
|
f"""document.body.style.setProperty("--toolbar-height", "0px"); """
|
||||||
|
)
|
||||||
|
|
||||||
|
def show(self) -> None:
|
||||||
|
super().show()
|
||||||
|
|
||||||
|
self.eval("""document.body.classList.remove("hidden"); """)
|
||||||
|
|
||||||
def flatten(self) -> None:
|
def flatten(self) -> None:
|
||||||
self.eval("""document.body.classList.add("flat"); """)
|
self.eval("""document.body.classList.add("flat"); """)
|
||||||
|
@ -108,6 +135,51 @@ class ToolbarWebView(AnkiWebView):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BottomWebView(ToolbarWebView):
|
||||||
|
def __init__(self, mw: aqt.AnkiQt, title: str) -> None:
|
||||||
|
super().__init__(mw, title=title)
|
||||||
|
self.hide_condition = self.mw.pm.hide_bottom_bar
|
||||||
|
qconnect(self.hide_timer.timeout, self.hide_if_allowed)
|
||||||
|
|
||||||
|
def on_body_classes_need_update(self) -> None:
|
||||||
|
super().on_body_classes_need_update()
|
||||||
|
|
||||||
|
self.adjustHeightToFit()
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def _onHeight(self, qvar: Optional[int]) -> None:
|
||||||
|
self.web_height = int(qvar)
|
||||||
|
|
||||||
|
if qvar is None:
|
||||||
|
self.mw.progress.single_shot(1000, self.mw.reset)
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.mw.pm.reduce_motion():
|
||||||
|
self.setFixedHeight(int(qvar))
|
||||||
|
else:
|
||||||
|
# Collapse/Expand animation
|
||||||
|
self.setMinimumHeight(0)
|
||||||
|
self.animation = QPropertyAnimation(
|
||||||
|
self, cast(QByteArray, b"maximumHeight")
|
||||||
|
)
|
||||||
|
self.animation.setDuration(int(theme_manager.var(props.TRANSITION)))
|
||||||
|
self.animation.setStartValue(self.height())
|
||||||
|
self.animation.setEndValue(int(qvar))
|
||||||
|
qconnect(self.animation.finished, lambda: self.setFixedHeight(int(qvar)))
|
||||||
|
self.animation.start()
|
||||||
|
|
||||||
|
def hide(self) -> None:
|
||||||
|
super().hide()
|
||||||
|
|
||||||
|
self._onHeight(1)
|
||||||
|
|
||||||
|
def show(self) -> None:
|
||||||
|
super().show()
|
||||||
|
|
||||||
|
self.hidden = False
|
||||||
|
self.adjustHeightToFit()
|
||||||
|
|
||||||
|
|
||||||
class Toolbar:
|
class Toolbar:
|
||||||
def __init__(self, mw: aqt.AnkiQt, web: AnkiWebView) -> None:
|
def __init__(self, mw: aqt.AnkiQt, web: AnkiWebView) -> None:
|
||||||
self.mw = mw
|
self.mw = mw
|
||||||
|
|
Loading…
Reference in a new issue