Create subclasses for non-blocking dialogs

This commit is contained in:
Veronica Berglyd Olsen
2024-05-01 20:08:35 +02:00
parent 600b60b441
commit a56b38694c
9 changed files with 99 additions and 74 deletions
+3 -3
View File
@@ -27,20 +27,20 @@ import logging
from PyQt5.QtGui import QCloseEvent, QColor
from PyQt5.QtWidgets import (
QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QTextBrowser, QVBoxLayout,
QWidget
QDialogButtonBox, QHBoxLayout, QLabel, QTextBrowser, QVBoxLayout, QWidget
)
from novelwriter import CONFIG, SHARED
from novelwriter.common import cssCol, readTextFile
from novelwriter.extensions.configlayout import NColourLabel
from novelwriter.extensions.modified import NNonBlockingDialog
from novelwriter.extensions.versioninfo import VersionInfoWidget
from novelwriter.types import QtAlignRightTop, QtDialogClose
logger = logging.getLogger(__name__)
class GuiAbout(QDialog):
class GuiAbout(NNonBlockingDialog):
def __init__(self, parent: QWidget) -> None:
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] NSpinBox
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
Copyright 20182024, Veronica Berglyd Olsen
@@ -29,9 +31,52 @@ from enum import Enum
from PyQt5.QtCore import QSize, Qt
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):
+11 -26
View File
@@ -23,18 +23,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import sys
import logging
import sys
from time import time
from pathlib import Path
from datetime import datetime
from pathlib import Path
from time import time
from PyQt5.QtCore import Qt, QTimer, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QCursor, QIcon
from PyQt5.QtWidgets import (
QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox, QShortcut, QSplitter,
QStackedWidget, QVBoxLayout, QWidget
QApplication, QFileDialog, QHBoxLayout, QMainWindow, QMessageBox,
QShortcut, QSplitter, QStackedWidget, QVBoxLayout, QWidget
)
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.projectsettings import GuiProjectSettings
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.docviewer import GuiDocViewer
from novelwriter.gui.docviewerpanel import GuiDocViewerPanel
@@ -794,10 +794,7 @@ class GuiMain(QMainWindow):
"""Open the novel details dialog."""
if SHARED.hasProject:
dialog = GuiNovelDetails(self)
dialog.setModal(True)
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.activateDialog()
dialog.updateValues()
return
@@ -807,10 +804,7 @@ class GuiMain(QMainWindow):
if SHARED.hasProject:
if (dialog := SHARED.findTopLevelWidget(GuiManuscript)) is None:
dialog = GuiManuscript(self)
dialog.setModal(False)
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.activateDialog()
dialog.loadContent()
return
@@ -829,10 +823,7 @@ class GuiMain(QMainWindow):
if SHARED.hasProject:
if (dialog := SHARED.findTopLevelWidget(GuiWritingStats)) is None:
dialog = GuiWritingStats(self)
dialog.setModal(False)
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.activateDialog()
dialog.populateGUI()
return
@@ -840,10 +831,7 @@ class GuiMain(QMainWindow):
def showAboutNWDialog(self) -> None:
"""Show the novelWriter about dialog."""
dialog = GuiAbout(self)
dialog.setModal(True)
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.activateDialog()
dialog.populateGUI()
return
@@ -858,10 +846,7 @@ class GuiMain(QMainWindow):
def showDictionariesDialog(self) -> None:
"""Show the download dictionaries dialog."""
dialog = GuiDictionaries(self)
dialog.setModal(True)
dialog.show()
dialog.raise_()
QApplication.processEvents()
dialog.activateDialog()
if not dialog.initDialog():
dialog.close()
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.QtGui import QCloseEvent, QTextCursor
from PyQt5.QtWidgets import (
QApplication, QDialog, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout,
QLabel, QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget
QApplication, QDialogButtonBox, QFileDialog, QFrame, QHBoxLayout, QLabel,
QLineEdit, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget
)
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.extensions.modified import NIconToolButton
from novelwriter.extensions.modified import NIconToolButton, NNonBlockingDialog
from novelwriter.types import QtDialogClose
logger = logging.getLogger(__name__)
class GuiDictionaries(QDialog):
class GuiDictionaries(NNonBlockingDialog):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
+9 -15
View File
@@ -33,8 +33,8 @@ from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent
from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog
from PyQt5.QtWidgets import (
QAbstractItemView, QApplication, QDialog, QFormLayout, QGridLayout,
QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton, QSplitter,
QAbstractItemView, QApplication, QFormLayout, QGridLayout, QHBoxLayout,
QLabel, QListWidget, QListWidgetItem, QPushButton, QSplitter,
QStackedWidget, QTabWidget, QTextBrowser, QTreeWidget, QTreeWidgetItem,
QVBoxLayout, QWidget
)
@@ -47,7 +47,7 @@ from novelwriter.core.tohtml import ToHtml
from novelwriter.core.tokenizer import HeadingFormatter
from novelwriter.error import logException
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.tools.manusbuild import GuiManuscriptBuild
from novelwriter.tools.manussettings import GuiBuildSettings
@@ -59,7 +59,7 @@ from novelwriter.types import (
logger = logging.getLogger(__name__)
class GuiManuscript(QDialog):
class GuiManuscript(NToolDialog):
"""GUI Tools: Manuscript Tool
The dialog displays all the users build definitions, a preview panel
@@ -74,8 +74,6 @@ class GuiManuscript(QDialog):
logger.debug("Create: GuiManuscript")
self.setObjectName("GuiManuscript")
if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool)
self._builds = BuildCollection(SHARED.project)
self._buildMap: dict[str, QListWidgetItem] = {}
@@ -466,17 +464,13 @@ class GuiManuscript(QDialog):
if isinstance(obj, GuiBuildSettings):
if obj.buildID == build.buildID:
logger.debug("Found instance of GuiBuildSettings")
obj.show()
obj.raise_()
obj.activateDialog()
return
dlgSettings = GuiBuildSettings(SHARED.mainGui, build)
dlgSettings.setModal(False)
dlgSettings.show()
dlgSettings.raise_()
QApplication.processEvents()
dlgSettings.loadContent()
dlgSettings.newSettingsReady.connect(self._processNewSettings)
dialog = GuiBuildSettings(SHARED.mainGui, build)
dialog.activateDialog()
dialog.loadContent()
dialog.newSettingsReady.connect(self._processNewSettings)
return
+7 -7
View File
@@ -25,11 +25,11 @@ from __future__ import annotations
import logging
from PyQt5.QtCore import QEvent, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtCore import QEvent, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QFont, QIcon, QSyntaxHighlighter, QTextCharFormat, QTextDocument
from PyQt5.QtWidgets import (
QAbstractButton, QAbstractItemView, QDialog, QDialogButtonBox, QFontDialog,
QFrame, QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu,
QAbstractButton, QAbstractItemView, QDialogButtonBox, QFontDialog, QFrame,
QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu,
QPlainTextEdit, QPushButton, QSplitter, QStackedWidget, QTreeWidget,
QTreeWidgetItem, QVBoxLayout, QWidget
)
@@ -40,7 +40,9 @@ from novelwriter.core.buildsettings import BuildSettings, FilterMode
from novelwriter.extensions.configlayout import (
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.switch import NSwitch
from novelwriter.extensions.switchbox import NSwitchBox
@@ -52,7 +54,7 @@ from novelwriter.types import (
logger = logging.getLogger(__name__)
class GuiBuildSettings(QDialog):
class GuiBuildSettings(NToolDialog):
"""GUI Tools: Manuscript Build Settings Dialog
The main tool for configuring manuscript builds. It's a GUI tool for
@@ -72,8 +74,6 @@ class GuiBuildSettings(QDialog):
logger.debug("Create: GuiBuildSettings")
self.setObjectName("GuiBuildSettings")
if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool)
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
import math
import logging
import math
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtWidgets import (
QAbstractItemView, QDialog, QDialogButtonBox, QFormLayout, QGridLayout,
QHBoxLayout, QLabel, QSpinBox, QStackedWidget, QTreeWidget,
QTreeWidgetItem, QVBoxLayout, QWidget
QAbstractItemView, QDialogButtonBox, QFormLayout, QGridLayout, QHBoxLayout,
QLabel, QSpinBox, QStackedWidget, QTreeWidget, QTreeWidgetItem,
QVBoxLayout, QWidget
)
from novelwriter import CONFIG, SHARED
from novelwriter.common import formatTime, numberToRoman
from novelwriter.constants import nwUnicode
from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollablePage
from novelwriter.extensions.modified import NNonBlockingDialog
from novelwriter.extensions.novelselector import NovelSelector
from novelwriter.extensions.pagedsidebar import NPagedSideBar
from novelwriter.extensions.switch import NSwitch
@@ -46,7 +47,7 @@ from novelwriter.types import QtAlignRight, QtDecoration, QtDialogClose
logger = logging.getLogger(__name__)
class GuiNovelDetails(QDialog):
class GuiNovelDetails(NNonBlockingDialog):
PAGE_OVERVIEW = 1
PAGE_CONTENTS = 2
+4 -5
View File
@@ -32,15 +32,16 @@ from typing import TYPE_CHECKING
from PyQt5.QtCore import Qt, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QCursor, QPixmap
from PyQt5.QtWidgets import (
QAction, QApplication, QDialog, QDialogButtonBox, QFileDialog, QGridLayout,
QAction, QApplication, QDialogButtonBox, QFileDialog, QGridLayout,
QGroupBox, QHBoxLayout, QLabel, QMenu, QSpinBox, QTreeWidget,
QTreeWidgetItem
)
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.error import formatException
from novelwriter.extensions.modified import NToolDialog
from novelwriter.extensions.switch import NSwitch
from novelwriter.types import (
QtAlignLeftMiddle, QtAlignRight, QtAlignRightMiddle, QtDecoration,
@@ -53,7 +54,7 @@ if TYPE_CHECKING: # pragma: no cover
logger = logging.getLogger(__name__)
class GuiWritingStats(QDialog):
class GuiWritingStats(NToolDialog):
"""GUI Tools: Writing Statistics
Displays data from the NWSessionLog object.
@@ -73,8 +74,6 @@ class GuiWritingStats(QDialog):
logger.debug("Create: GuiWritingStats")
self.setObjectName("GuiWritingStats")
if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool)
self.logData = []
self.filterData = []
+7 -6
View File
@@ -20,18 +20,18 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import pytest
import sys
from pathlib import Path
from pytestqt.qtbot import QtBot
import pytest
from mocked import causeOSError
from tools import C, buildTestProject
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtPrintSupport import QPrintPreviewDialog
from PyQt5.QtWidgets import QAction, QListWidgetItem
from pytestqt.qtbot import QtBot
from tools import C, buildTestProject
from novelwriter import CONFIG, SHARED
from novelwriter.constants import nwHeadFmt
@@ -127,8 +127,10 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path):
# Edit the new build
manus.buildList.clearSelection()
manus.buildList.setCurrentRow(0)
manus.tbEdit.click()
with qtbot.waitSignal(manus.tbEdit.clicked, timeout=5000):
manus.tbEdit.click()
manus._editSelectedBuild()
bSettings = SHARED.findTopLevelWidget(GuiBuildSettings)
assert isinstance(bSettings, GuiBuildSettings)
build = None
@@ -147,7 +149,6 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path):
# May have been garbage collected, but if it isn't, it should be hidden
assert bSettings.isVisible() is False
# Finish
# qtbot.stop()
# END Test testManuscript_Builds