Clean up Main GUI inheritance
This commit is contained in:
@@ -25,14 +25,13 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QCloseEvent
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractItemView, QApplication, QDialog, QDialogButtonBox, QFileDialog,
|
||||
QHBoxLayout, QLineEdit, QListWidget, QVBoxLayout
|
||||
QHBoxLayout, QLineEdit, QListWidget, QVBoxLayout, QWidget
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -42,9 +41,6 @@ from novelwriter.extensions.configlayout import NColourLabel
|
||||
from novelwriter.extensions.modified import NIconToolButton
|
||||
from novelwriter.types import QtDialogClose, QtDialogSave
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -52,8 +48,8 @@ class GuiWordList(QDialog):
|
||||
|
||||
newWordListReady = pyqtSignal()
|
||||
|
||||
def __init__(self, mainGui: GuiMain) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiWordList")
|
||||
self.setObjectName("GuiWordList")
|
||||
|
||||
@@ -36,7 +36,6 @@ import logging
|
||||
|
||||
from enum import Enum
|
||||
from time import time
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtCore import (
|
||||
QObject, QPoint, QRegularExpression, QRunnable, Qt, QTimer, pyqtSignal,
|
||||
@@ -69,9 +68,6 @@ from novelwriter.types import (
|
||||
QtMoveAnchor, QtMoveLeft, QtMoveRight
|
||||
)
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -107,15 +103,14 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
requestProjectItemSelected = pyqtSignal(str, bool)
|
||||
requestProjectItemRenamed = pyqtSignal(str, str)
|
||||
requestNewNoteCreation = pyqtSignal(str, nwItemClass)
|
||||
requestNextDocument = pyqtSignal(str, bool)
|
||||
|
||||
def __init__(self, mainGui: GuiMain) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiDocEditor")
|
||||
|
||||
# Class Variables
|
||||
self.mainGui = mainGui
|
||||
|
||||
self._nwDocument = None
|
||||
self._nwItem = None
|
||||
|
||||
@@ -1319,9 +1314,8 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
self.docSearch.setResultCount(0, 0)
|
||||
self._lastFind = None
|
||||
if CONFIG.searchNextFile and not goBack:
|
||||
self.mainGui.openNextDocument(
|
||||
self._docHandle, wrapAround=CONFIG.searchLoop
|
||||
)
|
||||
self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
|
||||
QApplication.processEvents()
|
||||
self.beginSearch()
|
||||
self.setFocus()
|
||||
return
|
||||
@@ -1340,9 +1334,8 @@ class GuiDocEditor(QPlainTextEdit):
|
||||
|
||||
if resIdx > maxIdx and self._docHandle:
|
||||
if CONFIG.searchNextFile and not goBack:
|
||||
self.mainGui.openNextDocument(
|
||||
self._docHandle, wrapAround=CONFIG.searchLoop
|
||||
)
|
||||
self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
|
||||
QApplication.processEvents()
|
||||
self.beginSearch()
|
||||
self.setFocus()
|
||||
return
|
||||
|
||||
@@ -29,9 +29,8 @@ import logging
|
||||
|
||||
from enum import Enum
|
||||
from time import time
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSlot, pyqtSignal
|
||||
from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent
|
||||
from PyQt5.QtWidgets import (
|
||||
QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView,
|
||||
@@ -52,9 +51,6 @@ from novelwriter.types import (
|
||||
QtUserRole
|
||||
)
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -74,10 +70,8 @@ class GuiNovelView(QWidget):
|
||||
selectedItemChanged = pyqtSignal(str)
|
||||
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
|
||||
|
||||
def __init__(self, mainGui: GuiMain) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
|
||||
self.mainGui = mainGui
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
# Build GUI
|
||||
self.novelTree = GuiNovelTree(self)
|
||||
@@ -202,7 +196,6 @@ class GuiNovelToolBar(QWidget):
|
||||
logger.debug("Create: GuiNovelToolBar")
|
||||
|
||||
self.novelView = novelView
|
||||
self.mainGui = novelView.mainGui
|
||||
|
||||
iSz = SHARED.theme.baseIconSize
|
||||
mPx = CONFIG.pxInt(2)
|
||||
@@ -378,7 +371,6 @@ class GuiNovelTree(QTreeWidget):
|
||||
logger.debug("Create: GuiNovelTree")
|
||||
|
||||
self.novelView = novelView
|
||||
self.mainGui = novelView.mainGui
|
||||
|
||||
# Internal Variables
|
||||
self._treeMap = {}
|
||||
@@ -493,7 +485,7 @@ class GuiNovelTree(QTreeWidget):
|
||||
if rootHandle is None:
|
||||
rootHandle = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
|
||||
|
||||
treeChanged = self.mainGui.projView.changedSince(self._lastBuild)
|
||||
treeChanged = SHARED.mainGui.projView.changedSince(self._lastBuild)
|
||||
indexChanged = SHARED.project.index.rootChangedSince(rootHandle, self._lastBuild)
|
||||
if not (treeChanged or indexChanged or overRide):
|
||||
logger.debug("No changes have been made to the novel index")
|
||||
|
||||
@@ -30,7 +30,6 @@ import logging
|
||||
|
||||
from enum import Enum
|
||||
from time import time
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtCore import QPoint, Qt, QTimer, pyqtSignal, pyqtSlot
|
||||
from PyQt5.QtGui import QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon, QMouseEvent, QPalette
|
||||
@@ -57,9 +56,6 @@ from novelwriter.types import (
|
||||
QtUserRole
|
||||
)
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -81,10 +77,8 @@ class GuiProjectView(QWidget):
|
||||
# Requests for the main GUI
|
||||
projectSettingsRequest = pyqtSignal(int)
|
||||
|
||||
def __init__(self, mainGui: GuiMain) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
|
||||
self.mainGui = mainGui
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
# Build GUI
|
||||
self.projTree = GuiProjectTree(self)
|
||||
@@ -263,7 +257,6 @@ class GuiProjectToolBar(QWidget):
|
||||
|
||||
self.projView = projView
|
||||
self.projTree = projView.projTree
|
||||
self.mainGui = projView.mainGui
|
||||
|
||||
iSz = SHARED.theme.baseIconSize
|
||||
mPx = CONFIG.pxInt(2)
|
||||
@@ -499,7 +492,6 @@ class GuiProjectTree(QTreeWidget):
|
||||
logger.debug("Create: GuiProjectTree")
|
||||
|
||||
self.projView = projView
|
||||
self.mainGui = projView.mainGui
|
||||
|
||||
# Internal Variables
|
||||
self._treeMap: dict[str, QTreeWidgetItem] = {}
|
||||
@@ -1010,8 +1002,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
trItemP.takeChild(tIndex)
|
||||
|
||||
for dHandle in reversed(self.getTreeFromHandle(tHandle)):
|
||||
if self.mainGui.docEditor.docHandle == dHandle:
|
||||
self.mainGui.closeDocument()
|
||||
SHARED.closeDocument(dHandle)
|
||||
SHARED.project.removeItem(dHandle)
|
||||
self._treeMap.pop(dHandle, None)
|
||||
|
||||
@@ -1410,7 +1401,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
if not newFile:
|
||||
itemList.remove(tHandle)
|
||||
|
||||
dlgMerge = GuiDocMerge(self.mainGui, tHandle, itemList)
|
||||
dlgMerge = GuiDocMerge(SHARED.mainGui, tHandle, itemList)
|
||||
dlgMerge.exec()
|
||||
|
||||
if dlgMerge.result() == QDialog.DialogCode.Accepted:
|
||||
@@ -1451,7 +1442,8 @@ class GuiProjectTree(QTreeWidget):
|
||||
if newFile:
|
||||
self.revealNewTreeItem(mHandle, nHandle=tHandle, wordCount=True)
|
||||
|
||||
self.mainGui.openDocument(mHandle, doScroll=True)
|
||||
self.projView.openDocumentRequest.emit(mHandle, nwDocMode.EDIT, "", False)
|
||||
self.projView.setSelectedHandle(mHandle, doScroll=True)
|
||||
|
||||
if mrgData.get("moveToTrash", False):
|
||||
for sHandle in reversed(mrgData.get("finalItems", [])):
|
||||
@@ -1480,7 +1472,7 @@ class GuiProjectTree(QTreeWidget):
|
||||
logger.error("Only valid document items can be split")
|
||||
return False
|
||||
|
||||
dlgSplit = GuiDocSplit(self.mainGui, tHandle)
|
||||
dlgSplit = GuiDocSplit(SHARED.mainGui, tHandle)
|
||||
dlgSplit.exec()
|
||||
|
||||
if dlgSplit.result() == QDialog.DialogCode.Accepted:
|
||||
|
||||
@@ -27,8 +27,8 @@ import logging
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from PyQt5.QtGui import QPalette
|
||||
from PyQt5.QtCore import QEvent, QPoint, QSize, pyqtSignal
|
||||
from PyQt5.QtGui import QPalette
|
||||
from PyQt5.QtWidgets import QMenu, QVBoxLayout, QWidget
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
@@ -58,7 +58,7 @@ class GuiSideBar(QWidget):
|
||||
iSz = QSize(iPx, iPx)
|
||||
|
||||
self.setContentsMargins(0, 0, 0, 0)
|
||||
self.installEventFilter(StatusTipFilter(mainGui))
|
||||
self.installEventFilter(StatusTipFilter(self.mainGui))
|
||||
|
||||
# Buttons
|
||||
self.tbProject = NIconToolButton(self, iSz)
|
||||
|
||||
@@ -27,26 +27,23 @@ import logging
|
||||
|
||||
from datetime import datetime
|
||||
from time import time
|
||||
from typing import TYPE_CHECKING, Literal
|
||||
from typing import Literal
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, QLocale
|
||||
from PyQt5.QtWidgets import QApplication, QStatusBar, QLabel
|
||||
from PyQt5.QtCore import QLocale, pyqtSlot
|
||||
from PyQt5.QtWidgets import QApplication, QLabel, QStatusBar, QWidget
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import formatTime
|
||||
from novelwriter.constants import nwConst
|
||||
from novelwriter.extensions.statusled import StatusLED
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from novelwriter.guimain import GuiMain
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GuiMainStatus(QStatusBar):
|
||||
|
||||
def __init__(self, mainGui: GuiMain) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiMainStatus")
|
||||
|
||||
@@ -238,6 +235,7 @@ class GuiMainStatus(QStatusBar):
|
||||
before starting novelWriter.
|
||||
"""
|
||||
import tracemalloc
|
||||
|
||||
from collections import Counter
|
||||
|
||||
widgets = QApplication.allWidgets()
|
||||
|
||||
+22
-27
@@ -263,6 +263,7 @@ class GuiMain(QMainWindow):
|
||||
self.docEditor.requestProjectItemRenamed.connect(self.projView.renameTreeItem)
|
||||
self.docEditor.requestNewNoteCreation.connect(self.projView.createNewNote)
|
||||
self.docEditor.docTextChanged.connect(self.projSearch.textChanged)
|
||||
self.docEditor.requestNextDocument.connect(self.openNextDocument)
|
||||
|
||||
self.docViewer.documentLoaded.connect(self.docViewerPanel.updateHandle)
|
||||
self.docViewer.loadDocumentTagRequest.connect(self._followTag)
|
||||
@@ -549,36 +550,30 @@ class GuiMain(QMainWindow):
|
||||
|
||||
return True
|
||||
|
||||
def openNextDocument(self, tHandle: str, wrapAround: bool = False) -> bool:
|
||||
@pyqtSlot(str, bool)
|
||||
def openNextDocument(self, tHandle: str, wrapAround: bool) -> None:
|
||||
"""Open the next document in the project tree, following the
|
||||
document with the given handle. Stop when reaching the end.
|
||||
"""
|
||||
if not SHARED.hasProject:
|
||||
logger.error("No project open")
|
||||
return False
|
||||
|
||||
nHandle = None # The next handle after tHandle
|
||||
fHandle = None # The first file handle we encounter
|
||||
foundIt = False # We've found tHandle, pick the next we see
|
||||
for tItem in SHARED.project.tree:
|
||||
if not tItem.isFileType():
|
||||
continue
|
||||
if fHandle is None:
|
||||
fHandle = tItem.itemHandle
|
||||
if tItem.itemHandle == tHandle:
|
||||
foundIt = True
|
||||
elif foundIt:
|
||||
nHandle = tItem.itemHandle
|
||||
break
|
||||
|
||||
if nHandle is not None:
|
||||
self.openDocument(nHandle, tLine=1, doScroll=True)
|
||||
return True
|
||||
elif wrapAround:
|
||||
self.openDocument(fHandle, tLine=1, doScroll=True)
|
||||
return False
|
||||
|
||||
return False
|
||||
if SHARED.hasProject:
|
||||
nHandle = None # The next handle after tHandle
|
||||
fHandle = None # The first file handle we encounter
|
||||
foundIt = False # We've found tHandle, pick the next we see
|
||||
for tItem in SHARED.project.tree:
|
||||
if not tItem.isFileType():
|
||||
continue
|
||||
if fHandle is None:
|
||||
fHandle = tItem.itemHandle
|
||||
if tItem.itemHandle == tHandle:
|
||||
foundIt = True
|
||||
elif foundIt:
|
||||
nHandle = tItem.itemHandle
|
||||
break
|
||||
if nHandle is not None:
|
||||
self.openDocument(nHandle, tLine=1, doScroll=True)
|
||||
elif wrapAround:
|
||||
self.openDocument(fHandle, tLine=1, doScroll=True)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def saveDocument(self) -> None:
|
||||
|
||||
@@ -171,6 +171,12 @@ class SharedData(QObject):
|
||||
logger.debug("Thread Pool Max Count: %d", QThreadPool.globalInstance().maxThreadCount())
|
||||
return
|
||||
|
||||
def closeDocument(self, tHandle: str | None = None) -> None:
|
||||
"""Close the document editor, optionally a specific document."""
|
||||
if tHandle is None or tHandle == self.mainGui.docEditor.docHandle:
|
||||
self.mainGui.closeDocument()
|
||||
return
|
||||
|
||||
def saveDocument(self) -> None:
|
||||
"""Forward save document call to main GUI."""
|
||||
self.mainGui.saveDocument()
|
||||
|
||||
@@ -69,8 +69,8 @@ class GuiWritingStats(NToolDialog):
|
||||
FMT_JSON = 0
|
||||
FMT_CSV = 1
|
||||
|
||||
def __init__(self, mainGui: GuiMain) -> None:
|
||||
super().__init__(parent=mainGui)
|
||||
def __init__(self, parent: GuiMain) -> None:
|
||||
super().__init__(parent=parent)
|
||||
|
||||
logger.debug("Create: GuiWritingStats")
|
||||
self.setObjectName("GuiWritingStats")
|
||||
|
||||
@@ -21,24 +21,25 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
from shutil import copyfile
|
||||
|
||||
from tools import C, NWD_IGNORE, cmpFiles, buildTestProject, XML_IGNORE
|
||||
import pytest
|
||||
|
||||
from PyQt5.QtGui import QPalette
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QMenu, QInputDialog
|
||||
from PyQt5.QtGui import QPalette
|
||||
from PyQt5.QtWidgets import QInputDialog, QMenu
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||
from novelwriter.enum import nwItemType, nwView, nwWidget
|
||||
from novelwriter.gui.outline import GuiOutlineView
|
||||
from novelwriter.gui.projtree import GuiProjectTree
|
||||
from novelwriter.gui.doceditor import GuiDocEditor
|
||||
from novelwriter.gui.noveltree import GuiNovelView
|
||||
from novelwriter.gui.outline import GuiOutlineView
|
||||
from novelwriter.gui.projtree import GuiProjectTree
|
||||
from novelwriter.tools.welcome import GuiWelcome
|
||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||
|
||||
from tests.tools import NWD_IGNORE, XML_IGNORE, C, buildTestProject, cmpFiles
|
||||
|
||||
KEY_DELAY = 1
|
||||
|
||||
@@ -50,7 +51,6 @@ def testGuiMain_ProjectBlocker(nwGUI):
|
||||
assert nwGUI.closeProject() is True
|
||||
assert nwGUI.saveProject() is False
|
||||
assert nwGUI.openDocument(None) is False
|
||||
assert nwGUI.openNextDocument(None) is False
|
||||
assert nwGUI.viewDocument(None) is False
|
||||
assert nwGUI.importDocument() is False
|
||||
|
||||
@@ -84,7 +84,7 @@ def testGuiMain_Launch(qtbot, monkeypatch, nwGUI, projPath):
|
||||
nwGUI.closeProject()
|
||||
|
||||
# Check that latest release info updated
|
||||
CONFIG.lastNotes != "0x0"
|
||||
assert CONFIG.lastNotes != "0x0"
|
||||
|
||||
# Check that project open dialog launches
|
||||
nwGUI.postLaunchTasks(None)
|
||||
|
||||
Reference in New Issue
Block a user