Add focus indication to editor and viewer header

This commit is contained in:
Veronica Berglyd Olsen
2024-06-18 22:42:52 +02:00
parent 930c60ae4a
commit c6569b63e5
4 changed files with 53 additions and 15 deletions
+8 -2
View File
@@ -55,6 +55,7 @@ from novelwriter.common import minmax, transferCase
from novelwriter.constants import nwConst, nwKeyWords, nwShortcode, nwUnicode
from novelwriter.core.document import NWDocument
from novelwriter.enum import nwComment, nwDocAction, nwDocInsert, nwDocMode, nwItemClass, nwTrinary
from novelwriter.extensions.configlayout import NColourLabel
from novelwriter.extensions.eventfilters import WheelEventFilter
from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton
from novelwriter.gui.dochighlight import BLOCK_META, BLOCK_TITLE
@@ -210,6 +211,7 @@ class GuiDocEditor(QPlainTextEdit):
# Function Mapping
self.closeSearch = self.docSearch.closeSearch
self.searchVisible = self.docSearch.isVisible
self.changeFocusState = self.docHeader.changeFocusState
# Finalise
self.updateSyntaxColours()
@@ -2785,8 +2787,7 @@ class GuiDocEditHeader(QWidget):
self.setAutoFillBackground(True)
# Title Label
self.itemTitle = QLabel("", self)
self.itemTitle.setIndent(0)
self.itemTitle = NColourLabel("", self, faded=SHARED.theme.fadedText)
self.itemTitle.setMargin(0)
self.itemTitle.setContentsMargins(0, 0, 0, 0)
self.itemTitle.setAutoFillBackground(True)
@@ -2924,6 +2925,11 @@ class GuiDocEditHeader(QWidget):
return
def changeFocusState(self, state: bool) -> None:
"""Toggle focus state."""
self.itemTitle.setColorState(state)
return
def setHandle(self, tHandle: str) -> None:
"""Set the document title from the handle, or alternatively, set
the whole document path within the project.
+11 -4
View File
@@ -33,7 +33,7 @@ from enum import Enum
from PyQt5.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QCursor, QMouseEvent, QPalette, QResizeEvent, QTextCursor
from PyQt5.QtWidgets import (
QAction, QApplication, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser,
QAction, QApplication, QFrame, QHBoxLayout, QMenu, QTextBrowser,
QToolButton, QWidget
)
@@ -42,6 +42,7 @@ from novelwriter.constants import nwHeaders, nwUnicode
from novelwriter.core.toqdoc import TextDocumentTheme, ToQTextDocument
from novelwriter.enum import nwDocAction, nwDocMode, nwItemType
from novelwriter.error import logException
from novelwriter.extensions.configlayout import NColourLabel
from novelwriter.extensions.eventfilters import WheelEventFilter
from novelwriter.extensions.modified import NIconToolButton
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
@@ -92,6 +93,9 @@ class GuiDocViewer(QTextBrowser):
self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.customContextMenuRequested.connect(self._openContextMenu)
# Function Mapping
self.changeFocusState = self.docHeader.changeFocusState
self.initViewer()
logger.debug("Ready: GuiDocViewer")
@@ -597,9 +601,7 @@ class GuiDocViewHeader(QWidget):
self.setAutoFillBackground(True)
# Title Label
self.itemTitle = QLabel(self)
self.itemTitle.setText("")
self.itemTitle.setIndent(0)
self.itemTitle = NColourLabel("", self, faded=SHARED.theme.fadedText)
self.itemTitle.setMargin(0)
self.itemTitle.setContentsMargins(0, 0, 0, 0)
self.itemTitle.setAutoFillBackground(True)
@@ -738,6 +740,11 @@ class GuiDocViewHeader(QWidget):
self.itemTitle.setPalette(palette)
return
def changeFocusState(self, state: bool) -> None:
"""Toggle focus state."""
self.itemTitle.setColorState(state)
return
def setHandle(self, tHandle: str) -> None:
"""Sets the document title from the handle, or alternatively,
set the whole document path.
+23
View File
@@ -326,6 +326,11 @@ class GuiMain(QMainWindow):
def postLaunchTasks(self, cmdOpen: str | None) -> None:
"""Process tasks after the main window has been created."""
QApplication.processEvents()
app = QApplication.instance()
if isinstance(app, QApplication):
app.focusChanged.connect(self._appFocusChanged)
# Check that config loaded fine
if CONFIG.hasError:
SHARED.error(CONFIG.errorText())
@@ -948,6 +953,24 @@ class GuiMain(QMainWindow):
# Private Slots
##
@pyqtSlot("QWidget*", "QWidget*")
def _appFocusChanged(self, old: QWidget, new: QWidget) -> None:
"""Alert main widgets that they have received or lost focus."""
if isinstance(new, QWidget):
docEditor = False
docViewer = False
if self.docEditor.isAncestorOf(new):
docEditor = True
elif self.docViewer.isAncestorOf(new):
docViewer = True
self.docEditor.changeFocusState(docEditor)
self.docViewer.changeFocusState(docViewer)
logger.debug("Main focus switched to: %s", type(new).__name__)
return
@pyqtSlot(bool)
def _focusModeChanged(self, focusMode: bool) -> None:
"""Handle change of focus mode. The Main GUI Focus Mode hides
+11 -9
View File
@@ -62,15 +62,17 @@ def testBaseInit_Launch(caplog, monkeypatch, fncPath):
CONFIG.osWindows = osWindows
# Normal Launch
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.__init__", lambda *a: None)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.setApplicationName", lambda *a: None)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.setApplicationVersion", lambda *a: None)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.setWindowIcon", lambda *a: None)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.setOrganizationDomain", lambda *a: None)
monkeypatch.setattr("PyQt5.QtWidgets.QApplication.exec", lambda *a: 0)
with pytest.raises(SystemExit) as ex:
main([f"--config={fncPath}", f"--data={fncPath}"])
assert ex.value.code == 0
with monkeypatch.context() as mp:
mp.setattr("PyQt5.QtWidgets.QApplication.__init__", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.QApplication.setApplicationName", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.QApplication.setApplicationVersion", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.QApplication.setWindowIcon", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.QApplication.setOrganizationDomain", lambda *a: None)
mp.setattr("PyQt5.QtWidgets.QApplication.exec", lambda *a: 0)
# mp.setattr("PyQt5.QtWidgets.QApplication.focusChange.connect", lambda *a: None)
with pytest.raises(SystemExit) as ex:
main([f"--config={fncPath}", f"--data={fncPath}"])
assert ex.value.code == 0
@pytest.mark.base