Skip to content

Commit

Permalink
Improve dialog handling (#1844)
Browse files Browse the repository at this point in the history
  • Loading branch information
vkbo authored May 1, 2024
2 parents aa7208b + 53d410a commit 7180fae
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 114 deletions.
6 changes: 3 additions & 3 deletions novelwriter/dialogs/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@

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)
Expand Down
49 changes: 47 additions & 2 deletions novelwriter/extensions/modified.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
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 2018–2024, Veronica Berglyd Olsen
Expand All @@ -29,9 +31,52 @@

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):
Expand Down
37 changes: 11 additions & 26 deletions novelwriter/guimain.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@
"""
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__
Expand All @@ -44,7 +44,7 @@
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
Expand Down Expand Up @@ -794,10 +794,7 @@ def showNovelDetailsDialog(self) -> None:
"""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

Expand All @@ -807,10 +804,7 @@ def showBuildManuscriptDialog(self) -> None:
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

Expand All @@ -829,21 +823,15 @@ def showWritingStatsDialog(self) -> None:
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

@pyqtSlot()
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

Expand All @@ -858,10 +846,7 @@ def showAboutQtDialog(self) -> None:
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."))
Expand Down
10 changes: 5 additions & 5 deletions novelwriter/tools/dictionaries.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@
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)
Expand Down
65 changes: 30 additions & 35 deletions novelwriter/tools/manuscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,15 @@

from datetime import datetime
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.QtPrintSupport import QPrintPreviewDialog, QPrinter
from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog
from PyQt5.QtWidgets import (
QAbstractItemView, QApplication, QDialog, QFormLayout, QGridLayout,
QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QPushButton,
QSplitter, QStackedWidget, QTabWidget, QTextBrowser, QTreeWidget,
QTreeWidgetItem, QVBoxLayout, QWidget
QAbstractItemView, QApplication, QFormLayout, QGridLayout, QHBoxLayout,
QLabel, QListWidget, QListWidgetItem, QPushButton, QSplitter,
QStackedWidget, QTabWidget, QTextBrowser, QTreeWidget, QTreeWidgetItem,
QVBoxLayout, QWidget
)

from novelwriter import CONFIG, SHARED
Expand All @@ -48,7 +47,7 @@
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
Expand All @@ -57,13 +56,10 @@
QtSizeExpanding, QtSizeIgnored, QtUserRole
)

if TYPE_CHECKING: # pragma: no cover
from novelwriter.guimain import GuiMain

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
Expand All @@ -73,15 +69,11 @@ class GuiManuscript(QDialog):

D_KEY = QtUserRole

def __init__(self, mainGui: GuiMain) -> None:
super().__init__(parent=mainGui)
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)

logger.debug("Create: GuiManuscript")
self.setObjectName("GuiManuscript")
if CONFIG.osDarwin:
self.setWindowFlag(Qt.WindowType.Tool)

self.mainGui = mainGui

self._builds = BuildCollection(SHARED.project)
self._buildMap: dict[str, QListWidgetItem] = {}
Expand Down Expand Up @@ -280,7 +272,7 @@ def closeEvent(self, event: QCloseEvent) -> None:
dialog open.
"""
self._saveSettings()
for obj in self.mainGui.children():
for obj in SHARED.mainGui.children():
# Make sure we don't have any settings windows open
if isinstance(obj, GuiBuildSettings) and obj.isVisible():
obj.close()
Expand Down Expand Up @@ -319,6 +311,8 @@ def _deleteSelectedBuild(self) -> None:
"""Delete the currently selected build settings entry."""
if build := self._getSelectedBuild():
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._updateBuildsList()
return
Expand Down Expand Up @@ -467,22 +461,14 @@ def _saveSettings(self) -> None:

def _openSettingsDialog(self, build: BuildSettings) -> None:
"""Open the build settings dialog."""
for obj in self.mainGui.children():
# Don't open a second dialog if one exists
if isinstance(obj, GuiBuildSettings):
if obj.buildID == build.buildID:
logger.debug("Found instance of GuiBuildSettings")
obj.show()
obj.raise_()
return

dlgSettings = GuiBuildSettings(self.mainGui, build)
dlgSettings.setModal(False)
dlgSettings.show()
dlgSettings.raise_()
QApplication.processEvents()
dlgSettings.loadContent()
dlgSettings.newSettingsReady.connect(self._processNewSettings)
if dialog := self._findSettingsDialog(build.buildID):
dialog.activateDialog()
return

dialog = GuiBuildSettings(SHARED.mainGui, build)
dialog.activateDialog()
dialog.loadContent()
dialog.newSettingsReady.connect(self._processNewSettings)

return

Expand All @@ -507,6 +493,15 @@ def _updateBuildItem(self, build: BuildSettings) -> None:
self._updateBuildsList()
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


Expand Down
Loading

0 comments on commit 7180fae

Please sign in to comment.