diff --git a/nw/gui/winmain.py b/nw/gui/winmain.py deleted file mode 100644 index 7d4aa545..00000000 --- a/nw/gui/winmain.py +++ /dev/null @@ -1,538 +0,0 @@ -# -*- coding: utf-8 -*- -"""novelWriter GUI Main Window - - novelWriter – GUI Main Window -=============================== - Class holding the main window - - File History: - Created: 2018-09-22 [0.0.1] - -""" - -import logging -import nw - -from os import path -from PyQt5.QtWidgets import qApp, QWidget, QMainWindow, QVBoxLayout, QFrame, QSplitter, QAction, QToolBar, QFileDialog, QStackedWidget -from PyQt5.QtCore import Qt, QSize, pyqtSlot -from PyQt5.QtGui import QIcon - -from nw.gui.doctree import GuiDocTree -from nw.gui.doctreectx import GuiDocTreeCtx -from nw.gui.doceditor import GuiDocEditor -from nw.gui.docdetails import GuiDocDetails -from nw.gui.projecteditor import GuiProjectEditor -from nw.gui.statusbar import GuiMainStatus -from nw.project.project import NWProject -from nw.project.document import NWDoc -from nw.project.item import NWItem -from nw.enum import nwItemType, nwItemClass, nwDocAction, nwItemAction - -logger = logging.getLogger(__name__) - -class GuiMain(QMainWindow): - - def __init__(self): - QWidget.__init__(self) - - logger.debug("Initialising GUI ...") - self.mainConf = nw.CONFIG - self.theProject = NWProject() - self.theDocument = NWDoc(self.theProject, self) - - self.resize(*self.mainConf.winGeometry) - self._setWindowTitle() - self.setWindowIcon(QIcon(path.join(self.mainConf.appPath,"..","novelWriter.svg"))) - - # Main GUI Elements - self.docEditor = GuiDocEditor(self) - self.docDetails = GuiDocDetails(self.theProject) - self.treeView = GuiDocTree(self.theProject) - - # Assemble Main Window - self.stackPane = QStackedWidget() - self.stackNone = self.stackPane.addWidget(QWidget()) - self.stackDoc = self.stackPane.addWidget(self.docEditor) - self.stackPane.setCurrentIndex(self.stackNone) - - self.treePane = QFrame() - self.treeBox = QVBoxLayout() - self.treeBox.addWidget(self.treeView) - self.treeBox.addWidget(self.docDetails) - self.treePane.setLayout(self.treeBox) - - self.splitMain = QSplitter(Qt.Horizontal) - self.splitMain.addWidget(self.treePane) - self.splitMain.addWidget(self.stackPane) - self.splitMain.setSizes(self.mainConf.mainPanePos) - self.splitMain.splitterMoved.connect(self._splitMainMove) - - self.setCentralWidget(self.splitMain) - - # Build Menus - self._buildMenu() - self.treeView.setContextMenuPolicy(Qt.CustomContextMenu) - self.treeView.customContextMenuRequested.connect(self._openDocTreeContextMenu) - self.treeView.itemSelectionChanged.connect(self._treeSingleClick) - self.treeView.itemDoubleClicked.connect(self._treeDoubleClick) - self.treeView.buildTree() - - # Build Status Bar - self.statusBar = GuiMainStatus() - self.setStatusBar(self.statusBar) - self.statusBar.showMessage("Ready") - - # Load Theme StyleSheet - cssFile = path.join(self.mainConf.themePath,self.mainConf.guiTheme+".css") - if path.isfile(cssFile): - with open(cssFile,mode="r") as inFile: - theCss = inFile.read() - self.setStyleSheet(theCss) - - self.show() - - logger.debug("GUI initialisation complete") - - return - - ## - # Project Actions - ## - - def newProject(self): - logger.info("Creating new project") - self.theProject.newProject() - self.treeView.buildTree() - return - - def openProject(self): - dlgOpt = QFileDialog.Options() - dlgOpt |= QFileDialog.DontUseNativeDialog - projPath, _ = QFileDialog.getOpenFileName( - self,"Open novelWriter Project","","novelWriter Project File (nwProject.nwx);;All Files (*)", options=dlgOpt - ) - if projPath: - self.theProject.openProject(projPath) - self.treeView.buildTree() - self._setWindowTitle(self.theProject.projName) - else: - return False - return True - - def saveProject(self): - if self.theProject.projPath is None: - dlgOpt = QFileDialog.Options() - dlgOpt |= QFileDialog.DontUseNativeDialog - projPath, _ = QFileDialog.getSaveFileName( - self,"Save novelWriter Project","","novelWriter Project File (nwProject.nwx);;All Files (*)", options=dlgOpt - ) - if projPath: - self.theProject.setProjectPath(projPath) - else: - return False - self.treeView.saveTreeOrder() - self.theProject.saveProject() - return True - - def editProject(self): - dlgProj = GuiProjectEditor(self, self.theProject) - dlgProj.exec_() - return True - - def openRecentProject(self, menuItem, recentItem): - logger.verbose("User requested opening recent project #%d" % recentItem) - self.theProject.openProject(self.mainConf.recentList[recentItem]) - self.treeView.buildTree() - self._setWindowTitle(self.theProject.projName) - return True - - ## - # Document Actions - ## - - def openDocument(self, tHandle): - self.stackPane.setCurrentIndex(self.stackDoc) - self.docEditor.setText(self.theDocument.openDocument(tHandle)) - self.docEditor.changeWidth() - return - - def saveDocument(self): - docHtml = self.docEditor.getText() - self.theDocument.theItem.setCharCount(self.docEditor.charCount) - self.theDocument.theItem.setWordCount(self.docEditor.wordCount) - self.theDocument.theItem.setParaCount(self.docEditor.paraCount) - self.theDocument.saveDocument(docHtml) - return - - ## - # Internal Functions - ## - - def _treeSingleClick(self): - sHandle = self.treeView.getSelectedHandle() - if sHandle is not None: - self.docDetails.buildViewBox(sHandle) - return - - def _treeDoubleClick(self, tItem, colNo): - tHandle = tItem.text(3) - logger.verbose("User double clicked tree item with handle %s" % tHandle) - nwItem = self.theProject.getItem(tHandle) - if nwItem.itemType == nwItemType.FILE: - logger.verbose("Requested item %s is a file" % tHandle) - self.openDocument(tHandle) - else: - logger.verbose("Requested item %s is a folder" % tHandle) - return - - def _closeMain(self): - logger.info("Exiting %s" % nw.__package__) - self.mainConf.setWinSize(self.width(), self.height()) - self.mainConf.setTreeColWidths(self.treeView.getColumnSizes()) - self.mainConf.setMainPanePos(self.splitMain.sizes()) - self.mainConf.saveConfig() - return - - def _setWindowTitle(self, projName=None): - winTitle = "%s [%s]" % (nw.__package__, nw.__version__) - if projName is not None: - winTitle += " - %s" % projName - self.setWindowTitle(winTitle) - return True - - ## - # Menu Action - ## - - def _menuExit(self): - self._closeMain() - qApp.quit() - return True - - def _showAbout(self): - self.docTabs.createTab(None,nw.DOCTYPE_ABOUT) - return True - - ## - # DocTree Context Menu - ## - - def _openDocTreeContextMenu(self, thePosition): - - ctxMenu = GuiDocTreeCtx(self.treeView, self.theProject, thePosition) - selHandle = ctxMenu.selHandle - selAction = ctxMenu.selAction - selClass = ctxMenu.selClass - selType = ctxMenu.selType - selTarget = ctxMenu.selTarget - - # print(selHandle, selAction, selClass, selType, selTarget) - - if selAction == nwItemAction.ADD_ROOT: - self.treeView.newTreeItem(selHandle, selType, selClass) - elif selAction == nwItemAction.ADD_FOLDER: - self.treeView.newTreeItem(selHandle, selType, selClass) - elif selAction == nwItemAction.ADD_FILE: - self.treeView.newTreeItem(selHandle, selType, selClass) - elif selAction == nwItemAction.MOVE_UP: - self.treeView.moveTreeItem(selHandle, -1) - elif selAction == nwItemAction.MOVE_DOWN: - self.treeView.moveTreeItem(selHandle, 1) - elif selAction == nwItemAction.MOVE_TO: - pass - elif selAction == nwItemAction.MOVE_TRASH: - pass - elif selAction == nwItemAction.SPLIT: - pass - elif selAction == nwItemAction.MERGE: - pass - elif selAction == nwItemAction.DELETE: - pass - elif selAction == nwItemAction.DELETE_ROOT: - pass - elif selAction == nwItemAction.EMPTY_TRASH: - pass - elif selAction == nwItemAction.RENAME: - self.treeView.renameTreeItem(selHandle) - - return - - ## - # Events - ## - - def resizeEvent(self, theEvent): - """Extend QMainWindow.resizeEvent to signal dependent GUI elements that its pane may have changed size. - """ - QMainWindow.resizeEvent(self,theEvent) - if self.stackPane.currentIndex() == self.stackDoc: - self.docEditor.changeWidth() - return - - def closeEvent(self, theEvent): - self._closeMain() - QMainWindow.closeEvent(self,theEvent) - return - - ## - # Signal Handlers - ## - - def _splitMainMove(self, pWidth, pHeight): - """Alert dependent GUI elements that the main pane splitter has been moved. - """ - if self.stackPane.currentIndex() == self.stackDoc: - self.docEditor.changeWidth() - return - - ## - # GUI Builders - ## - - def _buildMenu(self): - menuBar = self.menuBar() - - # Project - projMenu = menuBar.addMenu("&Project") - - # Project > New Project - menuItem = QAction(QIcon.fromTheme("folder-new"), "New Project", menuBar) - menuItem.setStatusTip("Create New Project") - menuItem.triggered.connect(self.newProject) - projMenu.addAction(menuItem) - - # Project > Open Project - menuItem = QAction(QIcon.fromTheme("folder-open"), "Open Project", menuBar) - menuItem.setStatusTip("Open Project") - menuItem.setShortcut("Ctrl+Shift+O") - menuItem.triggered.connect(self.openProject) - projMenu.addAction(menuItem) - - # Project > Save Project - menuItem = QAction(QIcon.fromTheme("document-save"), "Save Project", menuBar) - menuItem.setStatusTip("Save Project") - menuItem.setShortcut("Ctrl+Shift+S") - menuItem.triggered.connect(self.saveProject) - projMenu.addAction(menuItem) - - # Project > Recent Projects - recentMenu = projMenu.addMenu(QIcon.fromTheme("document-open-recent"),"Recent Projects") - for n in range(len(self.mainConf.recentList)): - recentProject = self.mainConf.recentList[n] - if recentProject == "": continue - menuItem = QAction(QIcon.fromTheme("folder-open"), "%d: %s" % (n,recentProject), projMenu) - menuItem.triggered.connect(lambda menuItem, n=n : self.openRecentProject(menuItem, n)) - recentMenu.addAction(menuItem) - - # Project > Separator - projMenu.addSeparator() - - # Project > Project Settings - menuItem = QAction(QIcon.fromTheme("document-properties"), "Project Settings", menuBar) - menuItem.setStatusTip("Project Settings") - menuItem.triggered.connect(self.editProject) - projMenu.addAction(menuItem) - - # Project > Separator - projMenu.addSeparator() - - # Project > Exit - menuItem = QAction(QIcon.fromTheme("application-exit"), "Exit", menuBar) - menuItem.setStatusTip("Exit %s" % nw.__package__) - menuItem.setShortcut("Ctrl+Q") - menuItem.triggered.connect(self._menuExit) - projMenu.addAction(menuItem) - - ############################################################################################ - - # Item - itemMenu = menuBar.addMenu("&Item") - - # Item > New - menuItem = QAction(QIcon.fromTheme("document-new"), "&New Document", menuBar) - menuItem.setStatusTip("Create New Document") - menuItem.setShortcut("Ctrl+N") - itemMenu.addAction(menuItem) - - # Item > Open - menuItem = QAction(QIcon.fromTheme("document-open"), "&Open Document", menuBar) - menuItem.setStatusTip("Open Selected Document") - menuItem.setShortcut("Ctrl+O") - itemMenu.addAction(menuItem) - - # Item > Save - menuItem = QAction(QIcon.fromTheme("document-save"), "&Save Document", menuBar) - menuItem.setStatusTip("Save Current Document") - menuItem.setShortcut("Ctrl+S") - menuItem.triggered.connect(self.saveDocument) - itemMenu.addAction(menuItem) - - # Item > Separator - itemMenu.addSeparator() - - # Item > New Folder - menuItem = QAction(QIcon.fromTheme("folder-new"), "New Folder", menuBar) - menuItem.setStatusTip("New Folder") - menuItem.setShortcut("Ctrl+Shift+N") - itemMenu.addAction(menuItem) - - # Item > New Root - rootMenu = itemMenu.addMenu(QIcon.fromTheme("folder-new"), "Create Root Group") - self.rootItems = {} - self.rootItems[nwItemClass.NOVEL] = QAction(QIcon.fromTheme("folder-new"), "Novel Root", rootMenu) - self.rootItems[nwItemClass.PLOT] = QAction(QIcon.fromTheme("folder-new"), "Plot Root", rootMenu) - self.rootItems[nwItemClass.CHARACTER] = QAction(QIcon.fromTheme("folder-new"), "Character Root", rootMenu) - self.rootItems[nwItemClass.WORLD] = QAction(QIcon.fromTheme("folder-new"), "Location Root", rootMenu) - self.rootItems[nwItemClass.TIMELINE] = QAction(QIcon.fromTheme("folder-new"), "Timeline Root", rootMenu) - self.rootItems[nwItemClass.OBJECT] = QAction(QIcon.fromTheme("folder-new"), "Object Root", rootMenu) - self.rootItems[nwItemClass.CUSTOM] = QAction(QIcon.fromTheme("folder-new"), "Custom Root", rootMenu) - rootMenu.addActions(self.rootItems.values()) - - # Item > Separator - itemMenu.addSeparator() - - # Item > Delete Item - menuItem = QAction(QIcon.fromTheme("folder-delete"), "Delete Item", menuBar) - menuItem.setStatusTip("Delete Selected Item") - menuItem.setShortcut("Del") - itemMenu.addAction(menuItem) - - ############################################################################################ - - # Edit - editMenu = menuBar.addMenu("&Edit") - - # Edit > Undo - menuItem = QAction(QIcon.fromTheme("edit-undo"), "Undo", menuBar) - menuItem.setStatusTip("Undo Last Change") - menuItem.setShortcut("Ctrl+Z") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.UNDO)) - editMenu.addAction(menuItem) - - # Edit > Redo - menuItem = QAction(QIcon.fromTheme("edit-redo"), "Redo", menuBar) - menuItem.setStatusTip("Redo Last Change") - menuItem.setShortcut("Ctrl+Y") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.REDO)) - editMenu.addAction(menuItem) - - # Edit > Separator - editMenu.addSeparator() - - # Edit > Cut - menuItem = QAction(QIcon.fromTheme("edit-cut"), "Cut", menuBar) - menuItem.setStatusTip("Cut Selected Text") - menuItem.setShortcut("Ctrl+X") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.CUT)) - editMenu.addAction(menuItem) - - # Edit > Copy - menuItem = QAction(QIcon.fromTheme("edit-copy"), "Copy", menuBar) - menuItem.setStatusTip("Copy Selected Text") - menuItem.setShortcut("Ctrl+C") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.COPY)) - editMenu.addAction(menuItem) - - # Edit > Paste - menuItem = QAction(QIcon.fromTheme("edit-paste"), "Paste", menuBar) - menuItem.setStatusTip("Paste Text from Clipboard") - menuItem.setShortcut("Ctrl+V") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.PASTE)) - editMenu.addAction(menuItem) - - # Edit > Separator - editMenu.addSeparator() - - # Edit > Select All - menuItem = QAction(QIcon.fromTheme("edit-select-all"), "Select All", menuBar) - menuItem.setStatusTip("Select All Text in Document") - menuItem.setShortcut("Ctrl+A") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.SEL_ALL)) - editMenu.addAction(menuItem) - - # Edit > Select Paragraph - menuItem = QAction(QIcon.fromTheme("edit-select-all"), "Select Paragraph", menuBar) - menuItem.setStatusTip("Select All Text in Paragraph") - menuItem.setShortcut("Ctrl+Shift+A") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.SEL_PARA)) - editMenu.addAction(menuItem) - - # Edit > Separator - editMenu.addSeparator() - - # Edit > Settings - menuItem = QAction(QIcon.fromTheme("applications-system"), "Program Setting", menuBar) - menuItem.setStatusTip("Change %s Settings" % nw.__package__) - editMenu.addAction(menuItem) - - ############################################################################################ - - # Format - fmtMenu = menuBar.addMenu("&Format") - - # Format > Bold Text - menuItem = QAction(QIcon.fromTheme("format-text-bold"), "Bold Text", menuBar) - menuItem.setStatusTip("Make Selected Text Bold") - menuItem.setShortcut("Ctrl+B") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.BOLD)) - fmtMenu.addAction(menuItem) - - # Format > Italic Text - menuItem = QAction(QIcon.fromTheme("format-text-italic"), "Italic Text", menuBar) - menuItem.setStatusTip("Make Selected Text Italic") - menuItem.setShortcut("Ctrl+I") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.ITALIC)) - fmtMenu.addAction(menuItem) - - # Format > Underline Text - menuItem = QAction(QIcon.fromTheme("format-text-underline"), "Underline Text", menuBar) - menuItem.setStatusTip("Underline Selected Text") - menuItem.setShortcut("Ctrl+U") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.U_LINE)) - fmtMenu.addAction(menuItem) - - # Edit > Separator - fmtMenu.addSeparator() - - # Format > Double Quotes - menuItem = QAction(QIcon.fromTheme("insert-text"), "Wrap Double Quotes", menuBar) - menuItem.setStatusTip("Wrap Selected Text in Double Quotes") - menuItem.setShortcut("Ctrl+D") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.D_QUOTE)) - fmtMenu.addAction(menuItem) - - # Format > Single Quotes - menuItem = QAction(QIcon.fromTheme("insert-text"), "Wrap Single Quotes", menuBar) - menuItem.setStatusTip("Wrap Selected Text in Single Quotes") - menuItem.setShortcut("Ctrl+Shift+D") - menuItem.triggered.connect(lambda: self.docEditor.docAction(nwDocAction.S_QUOTE)) - fmtMenu.addAction(menuItem) - - ############################################################################################ - - # Help - helpMenu = menuBar.addMenu("&Help") - - # Help > About - menuItem = QAction(QIcon.fromTheme("help-about"), "About %s" % nw.__package__, menuBar) - menuItem.setStatusTip("About %s" % nw.__package__) - menuItem.triggered.connect(self._showAbout) - helpMenu.addAction(menuItem) - - # Help > About Qt5 - menuItem = QAction(QIcon.fromTheme("help-about"), "About Qt5", menuBar) - menuItem.setStatusTip("About Qt5") - helpMenu.addAction(menuItem) - - if not self.mainConf.debugGUI: - return - - ############################################################################################ - - # Debug GUI - debugMenu = menuBar.addMenu("&Debug") - - return - -# END Class GuiMain