Improve dialog handling (#1844)

This commit is contained in:
Veronica Berglyd Olsen
2024-05-01 20:24:31 +02:00
committed by GitHub
10 changed files with 141 additions and 113 deletions
+3 -3
View File
@@ -27,20 +27,20 @@ import logging
from PyQt5.QtGui import QCloseEvent, QColor from PyQt5.QtGui import QCloseEvent, QColor
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QTextBrowser, QVBoxLayout, QDialogButtonBox, QHBoxLayout, QLabel, QTextBrowser, QVBoxLayout, QWidget
QWidget
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.common import cssCol, readTextFile from novelwriter.common import cssCol, readTextFile
from novelwriter.extensions.configlayout import NColourLabel from novelwriter.extensions.configlayout import NColourLabel
from novelwriter.extensions.modified import NNonBlockingDialog
from novelwriter.extensions.versioninfo import VersionInfoWidget from novelwriter.extensions.versioninfo import VersionInfoWidget
from novelwriter.types import QtAlignRightTop, QtDialogClose from novelwriter.types import QtAlignRightTop, QtDialogClose
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiAbout(QDialog): class GuiAbout(NNonBlockingDialog):
def __init__(self, parent: QWidget) -> None: def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
+47 -2
View File
@@ -6,6 +6,8 @@ File History:
Created: 2024-02-01 [2.3b1] NComboBox Created: 2024-02-01 [2.3b1] NComboBox
Created: 2024-02-01 [2.3b1] NSpinBox Created: 2024-02-01 [2.3b1] NSpinBox
Created: 2024-02-01 [2.3b1] NDoubleSpinBox Created: 2024-02-01 [2.3b1] NDoubleSpinBox
Created: 2024-05-01 [2.5b1] NToolDialog
Created: 2024-05-01 [2.5b1] NNonBlockingDialog
This file is a part of novelWriter This file is a part of novelWriter
Copyright 20182024, Veronica Berglyd Olsen Copyright 20182024, Veronica Berglyd Olsen
@@ -29,9 +31,52 @@ from enum import Enum
from PyQt5.QtCore import QSize, Qt from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QWheelEvent from PyQt5.QtGui import QWheelEvent
from PyQt5.QtWidgets import QComboBox, QDoubleSpinBox, QSpinBox, QToolButton, QWidget from PyQt5.QtWidgets import (
QApplication, QComboBox, QDialog, QDoubleSpinBox, QSpinBox, QToolButton,
QWidget
)
from novelwriter import SHARED from novelwriter import CONFIG, SHARED
class NToolDialog(QDialog):
def __init__(self, parent: QWidget | None = None) -> None:
super().__init__(parent=parent)
self.setModal(False)
if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool)
return
def activateDialog(self) -> None:
"""Helper function to activate dialog on various systems."""
self.show()
if CONFIG.osWindows:
self.activateWindow()
self.raise_()
QApplication.processEvents()
return
# END Class NToolDialog
class NNonBlockingDialog(QDialog):
def __init__(self, parent: QWidget | None = None) -> None:
super().__init__(parent=parent)
self.setModal(True)
return
def activateDialog(self) -> None:
"""Helper function to activate dialog on various systems."""
self.show()
if CONFIG.osWindows:
self.activateWindow()
self.raise_()
QApplication.processEvents()
return
# END Class NNonBlockingDialog
class NComboBox(QComboBox): class NComboBox(QComboBox):
+11 -26
View File
@@ -23,18 +23,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from __future__ import annotations from __future__ import annotations
import sys
import logging import logging
import sys
from time import time
from pathlib import Path
from datetime import datetime from datetime import datetime
from pathlib import Path
from time import time
from PyQt5.QtCore import Qt, QTimer, pyqtSlot from PyQt5.QtCore import Qt, QTimer, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QCursor, QIcon from PyQt5.QtGui import QCloseEvent, QCursor, QIcon
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox, QShortcut, QSplitter, QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox,
QStackedWidget, QVBoxLayout, QWidget QShortcut, QSplitter, QStackedWidget, QVBoxLayout, QWidget
) )
from novelwriter import CONFIG, SHARED, __hexversion__, __version__ from novelwriter import CONFIG, SHARED, __hexversion__, __version__
@@ -44,7 +44,7 @@ from novelwriter.dialogs.about import GuiAbout
from novelwriter.dialogs.preferences import GuiPreferences from novelwriter.dialogs.preferences import GuiPreferences
from novelwriter.dialogs.projectsettings import GuiProjectSettings from novelwriter.dialogs.projectsettings import GuiProjectSettings
from novelwriter.dialogs.wordlist import GuiWordList from novelwriter.dialogs.wordlist import GuiWordList
from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwWidget, nwView from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwView, nwWidget
from novelwriter.gui.doceditor import GuiDocEditor from novelwriter.gui.doceditor import GuiDocEditor
from novelwriter.gui.docviewer import GuiDocViewer from novelwriter.gui.docviewer import GuiDocViewer
from novelwriter.gui.docviewerpanel import GuiDocViewerPanel from novelwriter.gui.docviewerpanel import GuiDocViewerPanel
@@ -794,10 +794,7 @@ class GuiMain(QMainWindow):
"""Open the novel details dialog.""" """Open the novel details dialog."""
if SHARED.hasProject: if SHARED.hasProject:
dialog = GuiNovelDetails(self) dialog = GuiNovelDetails(self)
dialog.setModal(True) dialog.activateDialog()
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.updateValues() dialog.updateValues()
return return
@@ -807,10 +804,7 @@ class GuiMain(QMainWindow):
if SHARED.hasProject: if SHARED.hasProject:
if (dialog := SHARED.findTopLevelWidget(GuiManuscript)) is None: if (dialog := SHARED.findTopLevelWidget(GuiManuscript)) is None:
dialog = GuiManuscript(self) dialog = GuiManuscript(self)
dialog.setModal(False) dialog.activateDialog()
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.loadContent() dialog.loadContent()
return return
@@ -829,10 +823,7 @@ class GuiMain(QMainWindow):
if SHARED.hasProject: if SHARED.hasProject:
if (dialog := SHARED.findTopLevelWidget(GuiWritingStats)) is None: if (dialog := SHARED.findTopLevelWidget(GuiWritingStats)) is None:
dialog = GuiWritingStats(self) dialog = GuiWritingStats(self)
dialog.setModal(False) dialog.activateDialog()
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.populateGUI() dialog.populateGUI()
return return
@@ -840,10 +831,7 @@ class GuiMain(QMainWindow):
def showAboutNWDialog(self) -> None: def showAboutNWDialog(self) -> None:
"""Show the novelWriter about dialog.""" """Show the novelWriter about dialog."""
dialog = GuiAbout(self) dialog = GuiAbout(self)
dialog.setModal(True) dialog.activateDialog()
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.populateGUI() dialog.populateGUI()
return return
@@ -858,10 +846,7 @@ class GuiMain(QMainWindow):
def showDictionariesDialog(self) -> None: def showDictionariesDialog(self) -> None:
"""Show the download dictionaries dialog.""" """Show the download dictionaries dialog."""
dialog = GuiDictionaries(self) dialog = GuiDictionaries(self)
dialog.setModal(True) dialog.activateDialog()
dialog.show()
dialog.raise_()
QApplication.processEvents()
if not dialog.initDialog(): if not dialog.initDialog():
dialog.close() dialog.close()
SHARED.error(self.tr("Could not initialise the dialog.")) SHARED.error(self.tr("Could not initialise the dialog."))
+5 -5
View File
@@ -31,20 +31,20 @@ from zipfile import ZipFile
from PyQt5.QtCore import pyqtSlot from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QCloseEvent, QTextCursor from PyQt5.QtGui import QCloseEvent, QTextCursor
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QApplication, QDialog, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout, QApplication, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout, QLabel,
QLabel, QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.common import formatFileFilter, openExternalPath, formatInt, getFileSize from novelwriter.common import formatFileFilter, formatInt, getFileSize, openExternalPath
from novelwriter.error import formatException from novelwriter.error import formatException
from novelwriter.extensions.modified import NIconToolButton from novelwriter.extensions.modified import NIconToolButton, NNonBlockingDialog
from novelwriter.types import QtDialogClose from novelwriter.types import QtDialogClose
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiDictionaries(QDialog): class GuiDictionaries(NNonBlockingDialog):
def __init__(self, parent: QWidget) -> None: def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
+29 -34
View File
@@ -28,16 +28,15 @@ import logging
from datetime import datetime from datetime import datetime
from time import time from time import time
from typing import TYPE_CHECKING
from PyQt5.QtCore import QTimer, QUrl, Qt, pyqtSignal, pyqtSlot from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent
from PyQt5.QtPrintSupport import QPrintPreviewDialog, QPrinter from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAbstractItemView, QApplication, QDialog, QFormLayout, QGridLayout, QAbstractItemView, QApplication, QFormLayout, QGridLayout, QHBoxLayout,
QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton, QLabel, QListWidget, QListWidgetItem, QPushButton, QSplitter,
QSplitter, QStackedWidget, QTabWidget, QTextBrowser, QTreeWidget, QStackedWidget, QTabWidget, QTextBrowser, QTreeWidget, QTreeWidgetItem,
QTreeWidgetItem, QVBoxLayout, QWidget QVBoxLayout, QWidget
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
@@ -48,7 +47,7 @@ from novelwriter.core.tohtml import ToHtml
from novelwriter.core.tokenizer import HeadingFormatter from novelwriter.core.tokenizer import HeadingFormatter
from novelwriter.error import logException from novelwriter.error import logException
from novelwriter.extensions.circularprogress import NProgressCircle from novelwriter.extensions.circularprogress import NProgressCircle
from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton, NToolDialog
from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
from novelwriter.tools.manusbuild import GuiManuscriptBuild from novelwriter.tools.manusbuild import GuiManuscriptBuild
from novelwriter.tools.manussettings import GuiBuildSettings from novelwriter.tools.manussettings import GuiBuildSettings
@@ -57,13 +56,10 @@ from novelwriter.types import (
QtSizeExpanding, QtSizeIgnored, QtUserRole QtSizeExpanding, QtSizeIgnored, QtUserRole
) )
if TYPE_CHECKING: # pragma: no cover
from novelwriter.guimain import GuiMain
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiManuscript(QDialog): class GuiManuscript(NToolDialog):
"""GUI Tools: Manuscript Tool """GUI Tools: Manuscript Tool
The dialog displays all the users build definitions, a preview panel The dialog displays all the users build definitions, a preview panel
@@ -73,15 +69,11 @@ class GuiManuscript(QDialog):
D_KEY = QtUserRole D_KEY = QtUserRole
def __init__(self, mainGui: GuiMain) -> None: def __init__(self, parent: QWidget) -> None:
super().__init__(parent=mainGui) super().__init__(parent=parent)
logger.debug("Create: GuiManuscript") logger.debug("Create: GuiManuscript")
self.setObjectName("GuiManuscript") self.setObjectName("GuiManuscript")
if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool)
self.mainGui = mainGui
self._builds = BuildCollection(SHARED.project) self._builds = BuildCollection(SHARED.project)
self._buildMap: dict[str, QListWidgetItem] = {} self._buildMap: dict[str, QListWidgetItem] = {}
@@ -280,7 +272,7 @@ class GuiManuscript(QDialog):
dialog open. dialog open.
""" """
self._saveSettings() self._saveSettings()
for obj in self.mainGui.children(): for obj in SHARED.mainGui.children():
# Make sure we don't have any settings windows open # Make sure we don't have any settings windows open
if isinstance(obj, GuiBuildSettings) and obj.isVisible(): if isinstance(obj, GuiBuildSettings) and obj.isVisible():
obj.close() obj.close()
@@ -319,6 +311,8 @@ class GuiManuscript(QDialog):
"""Delete the currently selected build settings entry.""" """Delete the currently selected build settings entry."""
if build := self._getSelectedBuild(): if build := self._getSelectedBuild():
if SHARED.question(self.tr("Delete build '{0}'?".format(build.name))): if SHARED.question(self.tr("Delete build '{0}'?".format(build.name))):
if dialog := self._findSettingsDialog(build.buildID):
dialog.close()
self._builds.removeBuild(build.buildID) self._builds.removeBuild(build.buildID)
self._updateBuildsList() self._updateBuildsList()
return return
@@ -467,22 +461,14 @@ class GuiManuscript(QDialog):
def _openSettingsDialog(self, build: BuildSettings) -> None: def _openSettingsDialog(self, build: BuildSettings) -> None:
"""Open the build settings dialog.""" """Open the build settings dialog."""
for obj in self.mainGui.children(): if dialog := self._findSettingsDialog(build.buildID):
# Don't open a second dialog if one exists dialog.activateDialog()
if isinstance(obj, GuiBuildSettings): return
if obj.buildID == build.buildID:
logger.debug("Found instance of GuiBuildSettings")
obj.show()
obj.raise_()
return
dlgSettings = GuiBuildSettings(self.mainGui, build) dialog = GuiBuildSettings(SHARED.mainGui, build)
dlgSettings.setModal(False) dialog.activateDialog()
dlgSettings.show() dialog.loadContent()
dlgSettings.raise_() dialog.newSettingsReady.connect(self._processNewSettings)
QApplication.processEvents()
dlgSettings.loadContent()
dlgSettings.newSettingsReady.connect(self._processNewSettings)
return return
@@ -507,6 +493,15 @@ class GuiManuscript(QDialog):
self._updateBuildsList() self._updateBuildsList()
return return
def _findSettingsDialog(self, buildID: str) -> GuiBuildSettings | None:
"""Return an open build settings dialog for a given build, if
one exists.
"""
for obj in SHARED.mainGui.children():
if isinstance(obj, GuiBuildSettings) and obj.buildID == buildID:
return obj
return None
# END Class GuiManuscript # END Class GuiManuscript
+19 -24
View File
@@ -25,13 +25,11 @@ from __future__ import annotations
import logging import logging
from typing import TYPE_CHECKING from PyQt5.QtCore import QEvent, pyqtSignal, pyqtSlot
from PyQt5.QtCore import QEvent, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFontDialog, QAbstractButton, QAbstractItemView, QDialogButtonBox, QFontDialog, QFrame,
QFrame, QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu, QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu,
QPlainTextEdit, QPushButton, QSplitter, QStackedWidget, QTreeWidget, QPlainTextEdit, QPushButton, QSplitter, QStackedWidget, QTreeWidget,
QTreeWidgetItem, QVBoxLayout, QWidget QTreeWidgetItem, QVBoxLayout, QWidget
) )
@@ -42,7 +40,9 @@ from novelwriter.core.buildsettings import BuildSettings, FilterMode
from novelwriter.extensions.configlayout import ( from novelwriter.extensions.configlayout import (
NColourLabel, NFixedPage, NScrollableForm, NScrollablePage NColourLabel, NFixedPage, NScrollableForm, NScrollablePage
) )
from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NIconToolButton, NSpinBox from novelwriter.extensions.modified import (
NComboBox, NDoubleSpinBox, NIconToolButton, NSpinBox, NToolDialog
)
from novelwriter.extensions.pagedsidebar import NPagedSideBar from novelwriter.extensions.pagedsidebar import NPagedSideBar
from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.switch import NSwitch
from novelwriter.extensions.switchbox import NSwitchBox from novelwriter.extensions.switchbox import NSwitchBox
@@ -51,13 +51,10 @@ from novelwriter.types import (
QtRoleApply, QtRoleReject, QtUserRole QtRoleApply, QtRoleReject, QtUserRole
) )
if TYPE_CHECKING: # pragma: no cover
from novelwriter.guimain import GuiMain
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiBuildSettings(QDialog): class GuiBuildSettings(NToolDialog):
"""GUI Tools: Manuscript Build Settings Dialog """GUI Tools: Manuscript Build Settings Dialog
The main tool for configuring manuscript builds. It's a GUI tool for The main tool for configuring manuscript builds. It's a GUI tool for
@@ -72,13 +69,11 @@ class GuiBuildSettings(QDialog):
newSettingsReady = pyqtSignal(BuildSettings) newSettingsReady = pyqtSignal(BuildSettings)
def __init__(self, mainGui: GuiMain, build: BuildSettings) -> None: def __init__(self, parent: QWidget, build: BuildSettings) -> None:
super().__init__(parent=mainGui) super().__init__(parent=parent)
logger.debug("Create: GuiBuildSettings") logger.debug("Create: GuiBuildSettings")
self.setObjectName("GuiBuildSettings") self.setObjectName("GuiBuildSettings")
if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool)
self._build = build self._build = build
@@ -296,8 +291,8 @@ class _FilterTab(NFixedPage):
F_INCLUDED = 2 F_INCLUDED = 2
F_EXCLUDED = 3 F_EXCLUDED = 3
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None: def __init__(self, parent: QWidget, build: BuildSettings) -> None:
super().__init__(parent=buildMain) super().__init__(parent=parent)
self._treeMap: dict[str, QTreeWidgetItem] = {} self._treeMap: dict[str, QTreeWidgetItem] = {}
self._build = build self._build = build
@@ -586,8 +581,8 @@ class _HeadingsTab(NScrollablePage):
EDIT_HSCENE = 5 EDIT_HSCENE = 5
EDIT_SECTION = 6 EDIT_SECTION = 6
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None: def __init__(self, parent: QWidget, build: BuildSettings) -> None:
super().__init__(parent=buildMain) super().__init__(parent=parent)
self._build = build self._build = build
self._editing = 0 self._editing = 0
@@ -972,8 +967,8 @@ class _HeadingSyntaxHighlighter(QSyntaxHighlighter):
class _ContentTab(NScrollableForm): class _ContentTab(NScrollableForm):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None: def __init__(self, parent: QWidget, build: BuildSettings) -> None:
super().__init__(parent=buildMain) super().__init__(parent=parent)
self._build = build self._build = build
@@ -1057,8 +1052,8 @@ class _ContentTab(NScrollableForm):
class _FormatTab(NScrollableForm): class _FormatTab(NScrollableForm):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None: def __init__(self, parent: QWidget, build: BuildSettings) -> None:
super().__init__(parent=buildMain) super().__init__(parent=parent)
self._build = build self._build = build
self._unitScale = 1.0 self._unitScale = 1.0
@@ -1324,8 +1319,8 @@ class _FormatTab(NScrollableForm):
class _OutputTab(NScrollableForm): class _OutputTab(NScrollableForm):
def __init__(self, buildMain: GuiBuildSettings, build: BuildSettings) -> None: def __init__(self, parent: QWidget, build: BuildSettings) -> None:
super().__init__(parent=buildMain) super().__init__(parent=parent)
self._build = build self._build = build
+6 -5
View File
@@ -23,21 +23,22 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from __future__ import annotations from __future__ import annotations
import math
import logging import logging
import math
from PyQt5.QtCore import pyqtSlot from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QCloseEvent from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAbstractItemView, QDialog, QDialogButtonBox, QFormLayout, QGridLayout, QAbstractItemView, QDialogButtonBox, QFormLayout, QGridLayout, QHBoxLayout,
QHBoxLayout, QLabel, QSpinBox, QStackedWidget, QTreeWidget, QLabel, QSpinBox, QStackedWidget, QTreeWidget, QTreeWidgetItem,
QTreeWidgetItem, QVBoxLayout, QWidget QVBoxLayout, QWidget
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.common import formatTime, numberToRoman from novelwriter.common import formatTime, numberToRoman
from novelwriter.constants import nwUnicode from novelwriter.constants import nwUnicode
from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollablePage from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollablePage
from novelwriter.extensions.modified import NNonBlockingDialog
from novelwriter.extensions.novelselector import NovelSelector from novelwriter.extensions.novelselector import NovelSelector
from novelwriter.extensions.pagedsidebar import NPagedSideBar from novelwriter.extensions.pagedsidebar import NPagedSideBar
from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.switch import NSwitch
@@ -46,7 +47,7 @@ from novelwriter.types import QtAlignRight, QtDecoration, QtDialogClose
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiNovelDetails(QDialog): class GuiNovelDetails(NNonBlockingDialog):
PAGE_OVERVIEW = 1 PAGE_OVERVIEW = 1
PAGE_CONTENTS = 2 PAGE_CONTENTS = 2
+4 -5
View File
@@ -32,15 +32,16 @@ from typing import TYPE_CHECKING
from PyQt5.QtCore import Qt, pyqtSlot from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QCursor, QPixmap from PyQt5.QtGui import QCloseEvent, QCursor, QPixmap
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QAction, QApplication, QDialog, QDialogButtonBox, QFileDialog, QGridLayout, QAction, QApplication, QDialogButtonBox, QFileDialog, QGridLayout,
QGroupBox, QHBoxLayout, QLabel, QMenu, QSpinBox, QTreeWidget, QGroupBox, QHBoxLayout, QLabel, QMenu, QSpinBox, QTreeWidget,
QTreeWidgetItem QTreeWidgetItem
) )
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.common import formatTime, checkInt, checkIntTuple, minmax from novelwriter.common import checkInt, checkIntTuple, formatTime, minmax
from novelwriter.constants import nwConst from novelwriter.constants import nwConst
from novelwriter.error import formatException from novelwriter.error import formatException
from novelwriter.extensions.modified import NToolDialog
from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.switch import NSwitch
from novelwriter.types import ( from novelwriter.types import (
QtAlignLeftMiddle, QtAlignRight, QtAlignRightMiddle, QtDecoration, QtAlignLeftMiddle, QtAlignRight, QtAlignRightMiddle, QtDecoration,
@@ -53,7 +54,7 @@ if TYPE_CHECKING: # pragma: no cover
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiWritingStats(QDialog): class GuiWritingStats(NToolDialog):
"""GUI Tools: Writing Statistics """GUI Tools: Writing Statistics
Displays data from the NWSessionLog object. Displays data from the NWSessionLog object.
@@ -73,8 +74,6 @@ class GuiWritingStats(QDialog):
logger.debug("Create: GuiWritingStats") logger.debug("Create: GuiWritingStats")
self.setObjectName("GuiWritingStats") self.setObjectName("GuiWritingStats")
if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool)
self.logData = [] self.logData = []
self.filterData = [] self.filterData = []
+2 -2
View File
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.5a2" hexVersion="0x020500a1" fileVersion="1.5" fileRevision="4" timeStamp="2024-04-18 17:57:37"> <novelWriterXML appVersion="2.5a3" hexVersion="0x020500a3" fileVersion="1.5" fileRevision="4" timeStamp="2024-05-01 19:43:08">
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="1916" autoCount="274" editTime="87487"> <project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="1917" autoCount="274" editTime="87503">
<name>Sample Project</name> <name>Sample Project</name>
<author>Jane Smith</author> <author>Jane Smith</author>
</project> </project>
+15 -7
View File
@@ -20,18 +20,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from __future__ import annotations from __future__ import annotations
import pytest
import sys import sys
from pathlib import Path from pathlib import Path
from pytestqt.qtbot import QtBot
import pytest
from mocked import causeOSError from mocked import causeOSError
from tools import C, buildTestProject
from PyQt5.QtCore import pyqtSlot from PyQt5.QtCore import pyqtSlot
from PyQt5.QtPrintSupport import QPrintPreviewDialog from PyQt5.QtPrintSupport import QPrintPreviewDialog
from PyQt5.QtWidgets import QAction, QListWidgetItem from PyQt5.QtWidgets import QAction, QListWidgetItem
from pytestqt.qtbot import QtBot
from tools import C, buildTestProject
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.constants import nwHeadFmt from novelwriter.constants import nwHeadFmt
@@ -98,7 +98,14 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path):
manus.show() manus.show()
manus.loadContent() manus.loadContent()
# Delete the default build # Delete the default build, while it is open
manus.buildList.clearSelection()
manus.buildList.setCurrentRow(0)
with qtbot.waitSignal(manus.tbEdit.clicked, timeout=5000):
manus.tbEdit.click()
manus._editSelectedBuild()
manus.buildList.clearSelection() manus.buildList.clearSelection()
manus.buildList.setCurrentRow(0) manus.buildList.setCurrentRow(0)
manus.tbDel.click() manus.tbDel.click()
@@ -127,8 +134,10 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path):
# Edit the new build # Edit the new build
manus.buildList.clearSelection() manus.buildList.clearSelection()
manus.buildList.setCurrentRow(0) manus.buildList.setCurrentRow(0)
manus.tbEdit.click() with qtbot.waitSignal(manus.tbEdit.clicked, timeout=5000):
manus.tbEdit.click()
manus._editSelectedBuild()
bSettings = SHARED.findTopLevelWidget(GuiBuildSettings) bSettings = SHARED.findTopLevelWidget(GuiBuildSettings)
assert isinstance(bSettings, GuiBuildSettings) assert isinstance(bSettings, GuiBuildSettings)
build = None build = None
@@ -147,7 +156,6 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path):
# May have been garbage collected, but if it isn't, it should be hidden # May have been garbage collected, but if it isn't, it should be hidden
assert bSettings.isVisible() is False assert bSettings.isVisible() is False
# Finish
# qtbot.stop() # qtbot.stop()
# END Test testManuscript_Builds # END Test testManuscript_Builds