Tweak project toolbar look, and fix shortcuts

This commit is contained in:
Veronica Berglyd Olsen
2022-06-07 22:38:02 +02:00
parent 5a6ef5efd3
commit ef270bc069
2 changed files with 79 additions and 95 deletions
+79 -86
View File
@@ -33,11 +33,11 @@ from enum import Enum
from time import time
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QIcon, QPalette
from PyQt5.QtWidgets import (
qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction,
QFrame, QDialog, QHeaderView, QWidget, QVBoxLayout, QToolBar, QLabel,
QToolButton, QSizePolicy, QInputDialog
QFrame, QDialog, QHeaderView, QWidget, QVBoxLayout, QLabel, QToolButton,
QSizePolicy, QInputDialog, QHBoxLayout, QShortcut
)
from novelwriter.core import NWDoc
@@ -75,13 +75,24 @@ class GuiProjectView(QWidget):
# Assemble
self.outerBox = QVBoxLayout()
self.outerBox.addWidget(self.projBar)
self.outerBox.addWidget(self.projTree)
self.outerBox.addWidget(self.projBar, 0)
self.outerBox.addWidget(self.projTree, 1)
self.outerBox.setContentsMargins(0, 0, 0, 0)
self.outerBox.setSpacing(0)
self.setLayout(self.outerBox)
# Keyboard Shortcuts
self.keyCtrlUp = QShortcut(self.projTree)
self.keyCtrlUp.setKey("Ctrl+Up")
self.keyCtrlUp.setContext(Qt.WidgetShortcut)
self.keyCtrlUp.activated.connect(lambda: self.projTree.moveTreeItem(-1))
self.keyCtrlDown = QShortcut(self.projTree)
self.keyCtrlDown.setKey("Ctrl+Down")
self.keyCtrlDown.setContext(Qt.WidgetShortcut)
self.keyCtrlDown.activated.connect(lambda: self.projTree.moveTreeItem(1))
# Connect Signals
# Function Mappings
@@ -155,7 +166,7 @@ class GuiProjectView(QWidget):
# END Class GuiProjectView
class GuiProjectToolBar(QToolBar):
class GuiProjectToolBar(QWidget):
ADD_PLAIN = 0
ADD_CHAP = 1
@@ -163,42 +174,52 @@ class GuiProjectToolBar(QToolBar):
ADD_NOTE = 3
ADD_FOLDER = 4
def __init__(self, theWidget):
QTreeWidget.__init__(self, theWidget)
def __init__(self, projView):
QTreeWidget.__init__(self, projView)
logger.debug("Initialising GuiProjectToolBar ...")
self.mainConf = novelwriter.CONFIG
self.theWidget = theWidget
self.theParent = theWidget.theParent
self.theProject = theWidget.theParent.theProject
self.theTheme = theWidget.theParent.theTheme
self.projView = projView
self.theParent = projView.theParent
self.theProject = projView.theParent.theProject
self.theTheme = projView.theParent.theTheme
iPx = self.theTheme.baseIconSize
mPx = self.mainConf.pxInt(12)
mPx = self.mainConf.pxInt(4)
self.setMovable(False)
self.setIconSize(QSize(iPx, iPx))
self.setContentsMargins(0, 0, 0, 0)
self.setStyleSheet("QToolBar {border: 0px;}")
self.setAutoFillBackground(True)
qPalette = self.palette()
qPalette.setBrush(QPalette.Window, qPalette.base())
self.setPalette(qPalette)
fadeCol = qPalette.text().color()
buttonStyle = (
"QToolButton {{border: none; background: transparent;}} "
"QToolButton:hover {{border: none; background: rgba({0},{1},{2},0.2);}}"
).format(fadeCol.red(), fadeCol.green(), fadeCol.blue())
# Tree Label
self.projLabel = QLabel("<b>%s</b>" % self.tr("Project Content"))
self.projLabel.setContentsMargins(0, 0, mPx, 0)
self.projLabel.setContentsMargins(0, 0, 0, 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.tbMoveU.setIconSize(QSize(iPx, iPx))
self.tbMoveU.setStyleSheet(buttonStyle)
self.tbMoveU.clicked.connect(lambda: self.projView.projTree.moveTreeItem(-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))
self.tbMoveD.setIconSize(QSize(iPx, iPx))
self.tbMoveD.setStyleSheet(buttonStyle)
self.tbMoveD.clicked.connect(lambda: self.projView.projTree.moveTreeItem(1))
# Items Menu
self.mItems = QMenu()
@@ -239,21 +260,29 @@ class GuiProjectToolBar(QToolBar):
self.tbItems.setToolTip("%s [Ctrl+N]" % self.tr("Add Item"))
self.tbItems.setShortcut("Ctrl+N")
self.tbItems.setIcon(self.theTheme.getIcon("add"))
self.tbItems.setIconSize(QSize(iPx, iPx))
self.tbItems.setStyleSheet(buttonStyle)
self.tbItems.setMenu(self.mItems)
self.tbItems.setPopupMode(QToolButton.InstantPopup)
# Settings Menu
self.tbSettings = QToolButton(self)
self.tbSettings.setIcon(self.theTheme.getIcon("menu"))
self.tbSettings.setIconSize(QSize(iPx, iPx))
self.tbSettings.setStyleSheet(buttonStyle)
self.tbSettings.setPopupMode(QToolButton.InstantPopup)
# Assemble
self.addWidget(self.projLabel)
self.addSeparator()
self.addWidget(self.tbMoveU)
self.addWidget(self.tbMoveD)
self.addWidget(self.tbItems)
self.addWidget(self.tbSettings)
self.outerBox = QHBoxLayout()
self.outerBox.addWidget(self.projLabel)
self.outerBox.addWidget(self.tbMoveU)
self.outerBox.addWidget(self.tbMoveD)
self.outerBox.addWidget(self.tbItems)
self.outerBox.addWidget(self.tbSettings)
self.outerBox.setContentsMargins(mPx, mPx, 0, mPx)
self.outerBox.setSpacing(mPx)
self.setLayout(self.outerBox)
logger.debug("GuiProjectToolBar initialisation complete")
@@ -267,7 +296,7 @@ class GuiProjectToolBar(QToolBar):
def _forwardNewRootFolder(self, itemClass):
"""Forward the request for a new root folder to the tree.
"""
self.theWidget.projTree.newTreeItem(nwItemType.ROOT, itemClass)
self.projView.projTree.newTreeItem(nwItemType.ROOT, itemClass)
return
@pyqtSlot(int)
@@ -275,22 +304,15 @@ class GuiProjectToolBar(QToolBar):
"""Forward the request for a new item of a given type.
"""
if type == self.ADD_PLAIN:
self.theWidget.projTree.newTreeItem(nwItemType.FILE, hLevel=0, isNote=False)
self.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=0, isNote=False)
elif type == self.ADD_CHAP:
self.theWidget.projTree.newTreeItem(nwItemType.FILE, hLevel=2, isNote=False)
self.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=2, isNote=False)
elif type == self.ADD_SCENE:
self.theWidget.projTree.newTreeItem(nwItemType.FILE, hLevel=3, isNote=False)
self.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=3, isNote=False)
elif type == self.ADD_NOTE:
self.theWidget.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
self.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
elif type == self.ADD_FOLDER:
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)
self.projView.projTree.newTreeItem(nwItemType.FOLDER)
return
##
@@ -315,16 +337,16 @@ class GuiProjectTree(QTreeWidget):
C_EXPORT = 2
C_STATUS = 3
def __init__(self, theWidget):
QTreeWidget.__init__(self, theWidget)
def __init__(self, projView):
QTreeWidget.__init__(self, projView)
logger.debug("Initialising GuiProjectTree ...")
self.mainConf = novelwriter.CONFIG
self.theWidget = theWidget
self.theParent = theWidget.theParent
self.theTheme = theWidget.theParent.theTheme
self.theProject = theWidget.theParent.theProject
self.projView = projView
self.theParent = projView.theParent
self.theTheme = projView.theParent.theTheme
self.theProject = projView.theParent.theProject
# Internal Variables
self._treeMap = {}
@@ -496,7 +518,7 @@ class GuiProjectTree(QTreeWidget):
# If successful, update word count
wC = self.theProject.index.getCounts(tHandle)[1]
self.propagateCount(tHandle, wC)
self.theWidget.wordCountsChanged.emit()
self.projView.wordCountsChanged.emit()
# Add the new item to the project tree
self.revealNewTreeItem(tHandle, nHandle)
@@ -525,19 +547,12 @@ class GuiProjectTree(QTreeWidget):
return True
def moveTreeItem(self, nStep):
"""Move an item up or down in the tree, but only if the project
tree has focus. This also applies when the menu is used.
"""Move an item up or down in the tree.
"""
if not self.theParent.hasProject:
logger.error("No project open")
return False
if not self.theWidget.anyFocus():
return False
tHandle = self.getSelectedHandle()
tItem = self._getTreeItem(tHandle)
if tItem is None:
logger.verbose("No item selected")
return False
pItem = tItem.parent()
@@ -745,7 +760,7 @@ class GuiProjectTree(QTreeWidget):
self._deleteTreeItem(dHandle)
self._alertTreeChange(tHandle=tHandle, flush=autoFlush)
self.theWidget.wordCountsChanged.emit()
self.projView.wordCountsChanged.emit()
else:
# The item is not already in the trash folder, so we
@@ -871,7 +886,7 @@ class GuiProjectTree(QTreeWidget):
dstItem = self._lastMove.get("parent", None)
dstIndex = self._lastMove.get("index", None)
if not self.theWidget.anyFocus():
if not self.projView.anyFocus():
return False
if srcItem is None or dstItem is None or dstIndex is None:
@@ -951,7 +966,7 @@ class GuiProjectTree(QTreeWidget):
"""
tHandle = self.getSelectedHandle()
if tHandle is not None:
self.theWidget.selectedItemChanged.emit(tHandle)
self.projView.selectedItemChanged.emit(tHandle)
return
@pyqtSlot("QTreeWidgetItem*", int)
@@ -968,7 +983,7 @@ class GuiProjectTree(QTreeWidget):
return
if tItem.itemType == nwItemType.FILE:
self.theWidget.openDocumentRequest.emit(tHandle, nwDocMode.EDIT)
self.projView.openDocumentRequest.emit(tHandle, nwDocMode.EDIT)
else:
trItem = self._getTreeItem(tHandle)
if trItem is not None:
@@ -1020,7 +1035,7 @@ class GuiProjectTree(QTreeWidget):
return
if tItem.itemType == nwItemType.FILE:
self.theWidget.openDocumentRequest.emit(tHandle, nwDocMode.VIEW)
self.projView.openDocumentRequest.emit(tHandle, nwDocMode.VIEW)
return
@@ -1227,11 +1242,11 @@ class GuiProjectTree(QTreeWidget):
itemType = tItem.itemType
if itemType == nwItemType.ROOT:
self.theWidget.rootFolderChanged.emit(tHandle)
self.projView.rootFolderChanged.emit(tHandle)
elif itemType == nwItemType.FILE and tItem.isNovelLike():
self.theWidget.novelItemChanged.emit(tHandle)
self.projView.novelItemChanged.emit(tHandle)
self.theWidget.treeItemChanged.emit(tHandle)
self.projView.treeItemChanged.emit(tHandle)
return
@@ -1283,14 +1298,6 @@ class GuiProjectTreeMenu(QMenu):
self.emptyTrash.triggered.connect(self._doEmptyTrash)
self.addAction(self.emptyTrash)
self.moveUp = QAction(self.tr("Move Item Up"), self)
self.moveUp.triggered.connect(self._doMoveUp)
self.addAction(self.moveUp)
self.moveDown = QAction(self.tr("Move Item Down"), self)
self.moveDown.triggered.connect(self._doMoveDown)
self.addAction(self.moveDown)
return
def filterActions(self, theItem):
@@ -1369,18 +1376,4 @@ class GuiProjectTreeMenu(QMenu):
self.theTree.emptyTrash()
return
@pyqtSlot()
def _doMoveUp(self):
"""Forward the move item call to the project tree.
"""
self.theTree.moveTreeItem(-1)
return
@pyqtSlot()
def _doMoveDown(self):
"""Forward the move item call to the project tree.
"""
self.theTree.moveTreeItem(1)
return
# END Class GuiProjectTreeMenu
-9
View File
@@ -187,15 +187,6 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
"0000000000010", "0000000000011", "0000000000012",
]
# Move item without focus
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.projTree.moveTreeItem(1) is False