Add move buttons to project tree toolbar

This commit is contained in:
Veronica Berglyd Olsen
2022-06-07 00:11:42 +02:00
parent 272e7f6e24
commit 5a6ef5efd3
6 changed files with 78 additions and 58 deletions
+1 -2
View File
@@ -48,7 +48,7 @@ The main shorcuts are as follows:
":kbd:`Ctrl`:kbd:`H`", "Open the search and replace bar and search for the selected word, if any is selected. (On Mac, this is :kbd:`Cmd`:kbd:`=`.)"
":kbd:`Ctrl`:kbd:`I`", "Format selected text, or word under cursor, with emphasis (italic)."
":kbd:`Ctrl`:kbd:`K`", "Activate the insert commands. The commands are listed in :ref:`a_kb_ins`."
":kbd:`Ctrl`:kbd:`N`", "Create new document."
":kbd:`Ctrl`:kbd:`N`", "Create new project item."
":kbd:`Ctrl`:kbd:`O`", "Open selected document."
":kbd:`Ctrl`:kbd:`Q`", "Exit novelWriter."
":kbd:`Ctrl`:kbd:`R`", "If in the project tree, open a document for viewing. If the editor has focus, open current document for viewing."
@@ -72,7 +72,6 @@ The main shorcuts are as follows:
":kbd:`Ctrl`:kbd:`Shift`:kbd:`A`", "Select all text in current paragraph."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`G`", "Find previous occurrence of search word in current document."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`I`", "Import text to the current document from a text file."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`N`", "Create new folder."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`O`", "Open a project."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`R`", "Close the document viewer."
":kbd:`Ctrl`:kbd:`Shift`:kbd:`S`", "Save the current project."
+2 -2
View File
@@ -25,7 +25,7 @@ from novelwriter.gui.itemdetails import GuiItemDetails
from novelwriter.gui.mainmenu import GuiMainMenu
from novelwriter.gui.noveltree import GuiNovelTree
from novelwriter.gui.outline import GuiOutline
from novelwriter.gui.projtree import GuiProjectWiew
from novelwriter.gui.projtree import GuiProjectView
from novelwriter.gui.statusbar import GuiMainStatus
from novelwriter.gui.theme import GuiTheme
from novelwriter.gui.viewsbar import GuiViewsBar
@@ -39,7 +39,7 @@ __all__ = [
"GuiMainStatus",
"GuiNovelTree",
"GuiOutline",
"GuiProjectWiew",
"GuiProjectView",
"GuiTheme",
"GuiViewsBar",
]
+1 -21
View File
@@ -33,7 +33,7 @@ from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtWidgets import QMenuBar, QAction
from novelwriter.enum import nwItemType, nwDocAction, nwDocInsert, nwWidget
from novelwriter.enum import nwDocAction, nwDocInsert, nwWidget
from novelwriter.constants import trConst, nwKeyWords, nwLabels, nwUnicode
logger = logging.getLogger(__name__)
@@ -62,8 +62,6 @@ class GuiMainMenu(QMenuBar):
# Function Pointers
self._docAction = self.theParent.passDocumentAction
self._moveTreeItem = self.theParent.treeView.moveTreeItem
self._newTreeItem = self.theParent.treeView.newTreeItem
self._docInsert = self.theParent.docEditor.insertText
self._insertKeyWord = self.theParent.docEditor.insertKeyWord
@@ -176,18 +174,6 @@ class GuiMainMenu(QMenuBar):
self.aDeleteItem.triggered.connect(lambda: self.theParent.treeView.deleteItem(None))
self.projMenu.addAction(self.aDeleteItem)
# Project > Move Up
self.aMoveUp = QAction(self.tr("Move Item Up"), self)
self.aMoveUp.setShortcut("Ctrl+Up")
self.aMoveUp.triggered.connect(lambda: self._moveTreeItem(-1))
self.projMenu.addAction(self.aMoveUp)
# Project > Move Down
self.aMoveDown = QAction(self.tr("Move Item Down"), self)
self.aMoveDown.setShortcut("Ctrl+Down")
self.aMoveDown.triggered.connect(lambda: self._moveTreeItem(1))
self.projMenu.addAction(self.aMoveDown)
# Project > Undo Last Action
self.aMoveUndo = QAction(self.tr("Undo Last Move"), self)
self.aMoveUndo.setShortcut("Ctrl+Shift+Z")
@@ -217,12 +203,6 @@ class GuiMainMenu(QMenuBar):
# Document
self.docuMenu = self.addMenu(self.tr("&Document"))
# Document > New
self.aNewDoc = QAction(self.tr("New Document"), self)
self.aNewDoc.setShortcut("Ctrl+N")
self.aNewDoc.triggered.connect(lambda: self._newTreeItem(nwItemType.FILE))
self.docuMenu.addAction(self.aNewDoc)
# Document > Open
self.aOpenDoc = QAction(self.tr("Open Document"), self)
self.aOpenDoc.setShortcut("Ctrl+O")
+49 -9
View File
@@ -6,7 +6,7 @@ GUI classes for the main window project tree
File History:
Created: 2018-09-29 [0.0.1] GuiProjectTree
Created: 2020-06-04 [0.7] GuiProjectTreeMenu
Created: 2022-06-06 [1.7b1] GuiProjectWiew
Created: 2022-06-06 [1.7b1] GuiProjectView
Created: 2022-06-06 [1.7b1] GuiProjectToolBar
This file is a part of novelWriter
@@ -35,9 +35,9 @@ from time import time
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction, QFrame,
QDialog, QHeaderView, QWidget, QVBoxLayout, QToolBar, QLabel, QToolButton,
QSizePolicy, QInputDialog
qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction,
QFrame, QDialog, QHeaderView, QWidget, QVBoxLayout, QToolBar, QLabel,
QToolButton, QSizePolicy, QInputDialog
)
from novelwriter.core import NWDoc
@@ -48,7 +48,7 @@ from novelwriter.constants import trConst, nwLabels
logger = logging.getLogger(__name__)
class GuiProjectWiew(QWidget):
class GuiProjectView(QWidget):
"""This is a wrapper class holding all the elements of the project
tree. The core object is the project tree itself. Most methods
available are mapped through to the project tree class.
@@ -87,7 +87,6 @@ class GuiProjectWiew(QWidget):
# Function Mappings
self.newTreeItem = self.projTree.newTreeItem
self.revealNewTreeItem = self.projTree.revealNewTreeItem
self.moveTreeItem = self.projTree.moveTreeItem
self.editTreeItem = self.projTree.editTreeItem
self.getTreeFromHandle = self.projTree.getTreeFromHandle
self.emptyTrash = self.projTree.emptyTrash
@@ -121,9 +120,26 @@ class GuiProjectWiew(QWidget):
self.projTree.buildTree()
return
def setFocus(self):
"""Forward the set focus call to the tree widget.
"""
self.projTree.setFocus()
return
def treeFocus(self):
"""Check if the project tree has focus.
"""
return self.projTree.hasFocus()
def anyFocus(self):
"""Check if any widget or child widget has focus.
"""
if self.hasFocus():
return True
if self.isAncestorOf(qApp.focusWidget()):
return True
return False
##
# Public Solts
##
@@ -136,7 +152,7 @@ class GuiProjectWiew(QWidget):
self.wordCountsChanged.emit()
return
# END Class GuiProjectWiew
# END Class GuiProjectView
class GuiProjectToolBar(QToolBar):
@@ -171,6 +187,19 @@ class GuiProjectToolBar(QToolBar):
self.projLabel.setContentsMargins(0, 0, mPx, 0)
self.projLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# Move Buttons
self.tbMoveU = QToolButton(self)
self.tbMoveU.setToolTip("%s [Ctrl+Up]" % self.tr("Move Up"))
self.tbMoveU.setShortcut("Ctrl+Up")
self.tbMoveU.setIcon(self.theTheme.getIcon("up"))
self.tbMoveU.clicked.connect(lambda: self._forwardMoveItem(-1))
self.tbMoveD = QToolButton(self)
self.tbMoveD.setToolTip("%s [Ctrl+Down]" % self.tr("Move Down"))
self.tbMoveD.setShortcut("Ctrl+Down")
self.tbMoveD.setIcon(self.theTheme.getIcon("down"))
self.tbMoveD.clicked.connect(lambda: self._forwardMoveItem(1))
# Items Menu
self.mItems = QMenu()
@@ -207,6 +236,8 @@ class GuiProjectToolBar(QToolBar):
self._addRootFolderEntry(nwItemClass.CUSTOM)
self.tbItems = QToolButton(self)
self.tbItems.setToolTip("%s [Ctrl+N]" % self.tr("Add Item"))
self.tbItems.setShortcut("Ctrl+N")
self.tbItems.setIcon(self.theTheme.getIcon("add"))
self.tbItems.setMenu(self.mItems)
self.tbItems.setPopupMode(QToolButton.InstantPopup)
@@ -219,6 +250,8 @@ class GuiProjectToolBar(QToolBar):
# Assemble
self.addWidget(self.projLabel)
self.addSeparator()
self.addWidget(self.tbMoveU)
self.addWidget(self.tbMoveD)
self.addWidget(self.tbItems)
self.addWidget(self.tbSettings)
@@ -253,6 +286,13 @@ class GuiProjectToolBar(QToolBar):
self.theWidget.projTree.newTreeItem(nwItemType.FOLDER)
return
@pyqtSlot(int)
def _forwardMoveItem(self, steps):
"""Forward the request to move an item up or down.
"""
self.theWidget.projTree.moveTreeItem(steps)
return
##
# Internal Functions
##
@@ -492,7 +532,7 @@ class GuiProjectTree(QTreeWidget):
logger.error("No project open")
return False
if not self.hasFocus():
if not self.theWidget.anyFocus():
return False
tHandle = self.getSelectedHandle()
@@ -831,7 +871,7 @@ class GuiProjectTree(QTreeWidget):
dstItem = self._lastMove.get("parent", None)
dstIndex = self._lastMove.get("index", None)
if not self.hasFocus():
if not self.theWidget.anyFocus():
return False
if srcItem is None or dstItem is None or dstIndex is None:
+2 -2
View File
@@ -40,7 +40,7 @@ from PyQt5.QtWidgets import (
from novelwriter.gui import (
GuiDocEditor, GuiDocViewDetails, GuiDocViewer, GuiItemDetails, GuiMainMenu,
GuiMainStatus, GuiNovelTree, GuiOutline, GuiProjectWiew, GuiTheme,
GuiMainStatus, GuiNovelTree, GuiOutline, GuiProjectView, GuiTheme,
GuiViewsBar
)
from novelwriter.dialogs import (
@@ -105,7 +105,7 @@ class GuiMain(QMainWindow):
# Main GUI Elements
self.statusBar = GuiMainStatus(self)
self.treeView = GuiProjectWiew(self)
self.treeView = GuiProjectView(self)
self.novelView = GuiNovelTree(self)
self.docEditor = GuiDocEditor(self)
self.viewMeta = GuiDocViewDetails(self)
+23 -22
View File
@@ -26,7 +26,7 @@ from tools import buildTestProject
from PyQt5.QtWidgets import QAction, QMessageBox, QInputDialog
from novelwriter.gui.projtree import GuiProjectTree
from novelwriter.gui.projtree import GuiProjectView, GuiProjectTree
from novelwriter.enum import nwItemType, nwItemClass
@@ -163,11 +163,12 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
monkeypatch.setattr(QInputDialog, "getText", lambda *a, text: (text, True))
monkeypatch.setattr(GuiProjectView, "anyFocus", lambda *a: True)
nwTree = nwGUI.treeView
# Try to move item with no project
assert nwTree.moveTreeItem(1) is False
assert nwTree.projTree.moveTreeItem(1) is False
# Create a project
prjDir = os.path.join(fncDir, "project")
@@ -187,33 +188,33 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
]
# Move item without focus
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: False)
assert nwTree.moveTreeItem(1) is False
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000e", "000000000000f",
"0000000000010", "0000000000011", "0000000000012",
]
monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True)
with monkeypatch.context() as mp:
mp.setattr(GuiProjectView, "anyFocus", lambda *a: False)
assert nwTree.projTree.moveTreeItem(1) is False
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000e", "000000000000f",
"0000000000010", "0000000000011", "0000000000012",
]
# Move with no selections
nwTree.projTree.clearSelection()
assert nwTree.moveTreeItem(1) is False
assert nwTree.projTree.moveTreeItem(1) is False
# Move second item up twice (should give same result)
nwTree.setSelectedHandle("000000000000f")
assert nwTree.moveTreeItem(-1) is True
assert nwTree.projTree.moveTreeItem(-1) is True
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000f", "000000000000e",
"0000000000010", "0000000000011", "0000000000012",
]
assert nwTree.moveTreeItem(-1) is False
assert nwTree.projTree.moveTreeItem(-1) is False
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000f", "000000000000e",
"0000000000010", "0000000000011", "0000000000012",
]
# Restore via menu entry
nwGUI.mainMenu.aMoveDown.activate(QAction.Trigger)
# Restore
assert nwTree.projTree.moveTreeItem(1) is True
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000e", "000000000000f",
"0000000000010", "0000000000011", "0000000000012",
@@ -221,19 +222,19 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
# Move fifth item down twice (should give same result)
nwTree.setSelectedHandle("0000000000011")
assert nwTree.moveTreeItem(1) is True
assert nwTree.projTree.moveTreeItem(1) is True
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000e", "000000000000f",
"0000000000010", "0000000000012", "0000000000011",
]
assert nwTree.moveTreeItem(1) is False
assert nwTree.projTree.moveTreeItem(1) is False
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000e", "000000000000f",
"0000000000010", "0000000000012", "0000000000011",
]
# Restore via menu entry
nwGUI.mainMenu.aMoveUp.activate(QAction.Trigger)
# Restore
assert nwTree.projTree.moveTreeItem(-1) is True
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000e", "000000000000f",
"0000000000010", "0000000000011", "0000000000012",
@@ -241,7 +242,7 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
# Move down again, and restore via undo
nwTree.setSelectedHandle("0000000000011")
assert nwTree.moveTreeItem(1) is True
assert nwTree.projTree.moveTreeItem(1) is True
assert nwTree.getTreeFromHandle("000000000000d") == [
"000000000000d", "000000000000e", "000000000000f",
"0000000000010", "0000000000012", "0000000000011",
@@ -259,15 +260,15 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0
# Move novel folder up
assert nwTree.moveTreeItem(-1) is False
assert nwTree.projTree.moveTreeItem(-1) is False
assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0
# Move novel folder down
assert nwTree.moveTreeItem(1) is True
assert nwTree.projTree.moveTreeItem(1) is True
assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 1
# Move novel folder up again
assert nwTree.moveTreeItem(-1) is True
assert nwTree.projTree.moveTreeItem(-1) is True
assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0
# Clean up