Merge pull request #212 from vkbo/dialog_design

Paged Dialogs
This commit is contained in:
Veronica K. Berglyd Olsen
2020-05-17 19:11:18 +02:00
committed by GitHub
16 changed files with 274 additions and 325 deletions
-44
View File
@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="18"
id="Layer_1"
version="1.2"
viewBox="0 0 19 18"
width="19"
xml:space="preserve"
sodipodi:docname="export.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
id="metadata874"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs872" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1080"
id="namedview870"
showgrid="false"
inkscape:zoom="33.875"
inkscape:cx="12.118081"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="M 18.711,6.796 C 18.67,6.755 14.656,2.7 12.729,0.65 12.309,0.236 11.73,0 11.143,0 9.961,0 9,0.896 9,2 H 1 C 0.447,2 0,2.448 0,3 v 14 c 0,0.552 0.447,1 1,1 h 14 c 0.553,0 1,-0.448 1,-1 v -6.045 c 1.434,-1.461 2.688,-2.729 2.711,-2.751 0.387,-0.39 0.387,-1.018 0,-1.408 z m -7.432,6.145 C 11.257,12.968 11.214,13 11.143,13 11.069,13 11.022,12.977 10.999,12.96 V 10 9 h -1 C 8.228,9.034 6.663,9.68 5.246,10.958 5.676,8.743 6.846,6 9.999,6 h 1 V 2.042 C 11.027,2.021 11.07,2 11.143,2 c 0.09,0 0.152,0.05 0.154,0.05 1.436,1.525 4.051,4.187 5.297,5.45 -0.253,0.257 -4.342,4.422 -5.315,5.441 z M 2,16 V 4 h 8 c 0,0.348 0,0.695 0,1 C 5.34,5 4,9.871 4,13.5 V 14 c 1.691,-2.578 3.6,-3.953 6,-4 0,1.045 0,2.838 0,3 0,0.551 0.512,1 1.143,1 0.364,0 0.676,-0.158 0.883,-0.391 0.539,-0.565 1.242,-1.291 1.976,-2.043 V 16 Z"
id="path867"
style="fill:#000000;fill-opacity:0.35408559"
inkscape:connector-curvature="0" /></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

-48
View File
@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="280px"
height="279.416px"
viewBox="340 140 280 279.416"
enable-background="new 340 140 280 279.416"
xml:space="preserve"
sodipodi:docname="gear.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1013"
id="namedview5"
showgrid="false"
inkscape:zoom="0.84461882"
inkscape:cx="22.787362"
inkscape:cy="139.70799"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<path
d="M620,305.666v-51.333l-31.5-5.25c-2.333-8.75-5.833-16.917-9.917-23.917L597.25,199.5l-36.167-36.75l-26.25,18.083 c-7.583-4.083-15.75-7.583-23.916-9.917L505.667,140h-51.334l-5.25,31.5c-8.75,2.333-16.333,5.833-23.916,9.916L399.5,163.333 L362.75,199.5l18.667,25.666c-4.083,7.584-7.583,15.75-9.917,24.5l-31.5,4.667v51.333l31.5,5.25 c2.333,8.75,5.833,16.334,9.917,23.917l-18.667,26.25l36.167,36.167l26.25-18.667c7.583,4.083,15.75,7.583,24.5,9.917l5.25,30.916 h51.333l5.25-31.5c8.167-2.333,16.333-5.833,23.917-9.916l26.25,18.666l36.166-36.166l-18.666-26.25 c4.083-7.584,7.583-15.167,9.916-23.917L620,305.666z M480,333.666c-29.75,0-53.667-23.916-53.667-53.666s24.5-53.667,53.667-53.667 S533.667,250.25,533.667,280S509.75,333.666,480,333.666z"
id="path2"
style="fill:#000000;fill-opacity:0.35408559" />
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

-8
View File
@@ -1,8 +0,0 @@
FROM ICON SET: Typicons
LICENSE: Creative Commons (Attribution-Share Alike 3.0 Unported)
https://creativecommons.org/licenses/by-sa/3.0/
Applies to:
* graphics/export.svg
* graphics/merge.svg
* graphics/split.svg
-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg4"
viewBox="0 0 20 20"
height="20"
width="20"
version="1.2">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<path
style="fill:#000000;fill-opacity:0.35294118;stroke:none;stroke-opacity:1"
id="path2"
d="m 16,5.816 v 1.851 c 0,1.93 -1.57,3.5 -3.5,3.5 -0.827,0 -1.5,0.673 -1.5,1.5 v 1.517 c 1.161,0.415 2,1.514 2,2.816 0,1.654 -1.346,3 -3,3 C 8.346,20 7,18.654 7,17 7,15.698 7.839,14.599 9,14.185 V 12.667 C 9,11.84 8.327,11.167 7.5,11.167 5.57,11.167 4,9.597 4,7.667 V 5.816 C 2.839,5.401 2,4.302 2,3 2,1.346 3.346,0 5,0 6.654,0 8,1.346 8,3 8,4.302 7.161,5.401 6,5.816 v 1.851 c 0,0.827 0.673,1.5 1.5,1.5 0.979,0 1.864,0.407 2.5,1.058 0.636,-0.651 1.521,-1.058 2.5,-1.058 0.827,0 1.5,-0.673 1.5,-1.5 V 5.816 C 12.839,5.401 12,4.302 12,3 c 0,-1.654 1.346,-3 3,-3 1.654,0 3,1.346 3,3 0,1.302 -0.839,2.401 -2,2.816 z M 5,2 C 4.448,2 4,2.449 4,3 4,3.551 4.448,4 5,4 5.552,4 6,3.551 6,3 6,2.449 5.552,2 5,2 Z m 5,16 c 0.552,0 1,-0.449 1,-1 0,-0.551 -0.448,-1 -1,-1 -0.552,0 -1,0.449 -1,1 0,0.551 0.448,1 1,1 z M 15,2 c -0.552,0 -1,0.449 -1,1 0,0.551 0.448,1 1,1 0.552,0 1,-0.449 1,-1 0,-0.551 -0.448,-1 -1,-1 z" />
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg4"
viewBox="0 0 20 20"
height="20"
width="20"
version="1.2">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<path
style="fill:#000000;fill-opacity:0.35294118;stroke:none;stroke-opacity:1"
id="path2"
d="m 16,14.184 v -1.851 c 0,-1.93 -1.57,-3.5 -3.5,-3.5 -0.827,0 -1.5,-0.673 -1.5,-1.5 V 5.816 C 12.161,5.401 13,4.302 13,3 13,1.346 11.654,0 10,0 8.346,0 7,1.346 7,3 7,4.302 7.839,5.401 9,5.815 v 1.518 c 0,0.827 -0.673,1.5 -1.5,1.5 -1.93,0 -3.5,1.57 -3.5,3.5 v 1.851 C 2.839,14.599 2,15.698 2,17 c 0,1.654 1.346,3 3,3 1.654,0 3,-1.346 3,-3 0,-1.302 -0.839,-2.401 -2,-2.816 v -1.851 c 0,-0.827 0.673,-1.5 1.5,-1.5 0.979,0 1.864,-0.407 2.5,-1.058 0.636,0.651 1.521,1.058 2.5,1.058 0.827,0 1.5,0.673 1.5,1.5 v 1.851 c -1.161,0.415 -2,1.514 -2,2.816 0,1.654 1.346,3 3,3 1.654,0 3,-1.346 3,-3 0,-1.302 -0.839,-2.401 -2,-2.816 z M 5,18 c -0.552,0 -1,-0.449 -1,-1 0,-0.551 0.448,-1 1,-1 0.552,0 1,0.449 1,1 0,0.551 -0.448,1 -1,1 z M 10,2 c 0.552,0 1,0.449 1,1 0,0.551 -0.448,1 -1,1 C 9.448,4 9,3.551 9,3 9,2.449 9.448,2 10,2 Z m 5,16 c -0.552,0 -1,-0.449 -1,-1 0,-0.551 0.448,-1 1,-1 0.552,0 1,0.449 1,1 0,0.551 -0.448,1 -1,1 z" />
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

-6
View File
@@ -7,10 +7,6 @@ from nw.gui.mainmenu import GuiMainMenu
from nw.gui.statusbar import GuiMainStatus from nw.gui.statusbar import GuiMainStatus
from nw.gui.theme import GuiTheme from nw.gui.theme import GuiTheme
# Qt Additions
from nw.gui.additions.qconfiglayout import QConfigLayout
from nw.gui.additions.qswitch import QSwitch
# Dialogs # Dialogs
from nw.gui.dialogs.configeditor import GuiConfigEditor from nw.gui.dialogs.configeditor import GuiConfigEditor
from nw.gui.dialogs.docmerge import GuiDocMerge from nw.gui.dialogs.docmerge import GuiDocMerge
@@ -42,8 +38,6 @@ __all__ = [
"GuiMainMenu", "GuiMainMenu",
"GuiMainStatus", "GuiMainStatus",
"GuiTheme", "GuiTheme",
"QConfigLayout",
"QSwitch",
"GuiConfigEditor", "GuiConfigEditor",
"GuiDocMerge", "GuiDocMerge",
"GuiDocSplit", "GuiDocSplit",
+4
View File
@@ -1,8 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from nw.gui.additions.pageddialog import PagedDialog
from nw.gui.additions.qconfiglayout import QConfigLayout from nw.gui.additions.qconfiglayout import QConfigLayout
from nw.gui.additions.qconfiglayout import QHelpLabel
from nw.gui.additions.qswitch import QSwitch from nw.gui.additions.qswitch import QSwitch
__all__ = [ __all__ = [
"PagedDialog",
"QConfigLayout", "QConfigLayout",
"QHelpLabel",
"QSwitch", "QSwitch",
] ]
+117
View File
@@ -0,0 +1,117 @@
# -*- coding: utf-8 -*-
"""novelWriter Paged Dialog
novelWriter Paged Dialog
============================
A custom QDialog with a built-in QTabWidget and vertical tabs.
File History:
Created: 2020-05-17 [0.5.1]
This file is a part of novelWriter
Copyright 2020, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import logging
import nw
from PyQt5.QtCore import Qt, QRect, QPoint
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QTabWidget, QTabBar, QStyle,
QStylePainter, QStyleOptionTab
)
logger = logging.getLogger(__name__)
class PagedDialog(QDialog):
def __init__(self, theParent=None):
QDialog.__init__(self, parent=theParent)
self._outerBox = QVBoxLayout()
self._buttonBox = QHBoxLayout()
self._tabBox = QTabWidget()
self._tabBar = VerticalTabBar(self)
self._tabBox.setTabBar(self._tabBar)
self._tabBox.setTabPosition(QTabWidget.West)
self._tabBar.setExpanding(False)
self._outerBox.addWidget(self._tabBox)
self._outerBox.addLayout(self._buttonBox)
self.setLayout(self._outerBox)
# Default Margins
qM = self._outerBox.contentsMargins()
mL = qM.left()
mR = qM.right()
mT = qM.top()
mB = qM.bottom()
self.setContentsMargins(0, 0, 0, 0)
self._outerBox.setContentsMargins(0, 0, 0, mB)
self._buttonBox.setContentsMargins(mL, 0, mR, 0)
self._outerBox.setSpacing(mT)
return
def addTab(self, tabWidget, tabLabel):
self._tabBox.addTab(tabWidget, tabLabel)
return
def addControls(self, buttonBar):
self._buttonBox.addWidget(buttonBar)
return
# END Class PagedDialog
class VerticalTabBar(QTabBar):
def __init__(self, theParent=None):
QTabBar.__init__(self, parent=theParent)
return
def tabSizeHint(self, theIndex):
tSize = QTabBar.tabSizeHint(self, theIndex)
tSize.transpose()
return tSize
def paintEvent(self, theEvent):
pObj = QStylePainter(self)
oObj = QStyleOptionTab()
for i in range(self.count()):
self.initStyleOption(oObj, i)
pObj.drawControl(QStyle.CE_TabBarTabShape, oObj)
pObj.save()
oSize = oObj.rect.size()
oSize.transpose()
oRect = QRect(QPoint(), oSize)
oRect.moveCenter(oObj.rect.center())
oObj.rect = oRect
oCenter = self.tabRect(i).center()
pObj.translate(oCenter)
pObj.rotate(90)
pObj.translate(-oCenter)
pObj.drawControl(QStyle.CE_TabBarTabLabel, oObj)
pObj.restore()
return
# END Class VerticalTabBar
+23 -9
View File
@@ -130,17 +130,9 @@ class QConfigLayout(QGridLayout):
qLabel.setIndent(8) qLabel.setIndent(8)
if helpText is not None: if helpText is not None:
qHelp = QLabel(str(helpText)) qHelp = QHelpLabel(str(helpText), self._helpCol, self._fontScale)
qHelp.setIndent(8) qHelp.setIndent(8)
lblCol = qHelp.palette()
lblCol.setColor(QPalette.WindowText, self._helpCol)
qHelp.setPalette(lblCol)
lblFont = qHelp.font()
lblFont.setPointSizeF(self._fontScale*lblFont.pointSizeF())
qHelp.setFont(lblFont)
labelBox = QVBoxLayout() labelBox = QVBoxLayout()
labelBox.addWidget(qLabel) labelBox.addWidget(qLabel)
labelBox.addWidget(qHelp) labelBox.addWidget(qHelp)
@@ -176,3 +168,25 @@ class QConfigLayout(QGridLayout):
return self._nextRow - 1 return self._nextRow - 1
# END Class QConfigLayout # END Class QConfigLayout
class QHelpLabel(QLabel):
def __init__(self, theText, textCol, fontSize=0.9):
QLabel.__init__(self, theText)
if isinstance(textCol, QColor):
qCol = textCol
else:
qCol = QColor(*textCol)
lblCol = self.palette()
lblCol.setColor(QPalette.WindowText, qCol)
self.setPalette(lblCol)
lblFont = self.font()
lblFont.setPointSizeF(fontSize*lblFont.pointSizeF())
self.setFont(lblFont)
return
# END Class QHelpLabel
+10 -21
View File
@@ -38,51 +38,39 @@ from PyQt5.QtWidgets import (
QFileDialog QFileDialog
) )
from nw.gui.additions import QSwitch, QConfigLayout from nw.gui.additions import QSwitch, QConfigLayout, PagedDialog
from nw.core import NWSpellCheck, NWSpellSimple, NWSpellEnchant from nw.core import NWSpellCheck, NWSpellSimple, NWSpellEnchant
from nw.constants import nwAlert, nwQuotes from nw.constants import nwAlert, nwQuotes
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiConfigEditor(QDialog): class GuiConfigEditor(PagedDialog):
def __init__(self, theParent, theProject): def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent) PagedDialog.__init__(self, theParent)
logger.debug("Initialising ConfigEditor ...") logger.debug("Initialising ConfigEditor ...")
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theParent = theParent self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.setWindowTitle("Preferences") self.setWindowTitle("Preferences")
self.guiDeco = self.theParent.theTheme.loadDecoration("settings", (64,64))
self.outerBox.setSpacing(16)
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox)
self.setLayout(self.outerBox)
self.tabGeneral = GuiConfigEditGeneralTab(self.theParent) self.tabGeneral = GuiConfigEditGeneralTab(self.theParent)
self.tabLayout = GuiConfigEditLayoutTab(self.theParent) self.tabLayout = GuiConfigEditLayoutTab(self.theParent)
self.tabEditing = GuiConfigEditEditingTab(self.theParent) self.tabEditing = GuiConfigEditEditingTab(self.theParent)
self.tabAutoRep = GuiConfigEditAutoReplaceTab(self.theParent) self.tabAutoRep = GuiConfigEditAutoReplaceTab(self.theParent)
self.tabWidget = QTabWidget() self.addTab(self.tabGeneral, "General")
self.tabWidget.setMinimumWidth(600) self.addTab(self.tabLayout, "Layout")
self.tabWidget.addTab(self.tabGeneral, "General") self.addTab(self.tabEditing, "Editing")
self.tabWidget.addTab(self.tabLayout, "Layout") self.addTab(self.tabAutoRep, "Auto-Replace")
self.tabWidget.addTab(self.tabEditing, "Editing")
self.tabWidget.addTab(self.tabAutoRep, "Auto-Replace")
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doSave) self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self._doClose) self.buttonBox.rejected.connect(self._doClose)
self.addControls(self.buttonBox)
self.innerBox.addWidget(self.tabWidget)
self.innerBox.addWidget(self.buttonBox)
self.show() self.show()
@@ -773,6 +761,7 @@ class GuiConfigEditAutoReplaceTab(QWidget):
def saveValues(self): def saveValues(self):
validEntries = True validEntries = True
needsRestart = False
autoSelect = self.autoSelect.isChecked() autoSelect = self.autoSelect.isChecked()
doReplace = self.autoReplaceMain.isChecked() doReplace = self.autoReplaceMain.isChecked()
@@ -827,7 +816,7 @@ class GuiConfigEditAutoReplaceTab(QWidget):
self.mainConf.confChanged = True self.mainConf.confChanged = True
return validEntries, False return validEntries, needsRestart
## ##
# Slots # Slots
+22 -23
View File
@@ -30,10 +30,12 @@ import nw
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QDialog, QVBoxLayout, QLabel, QListWidget, QAbstractItemView,
QListWidget, QAbstractItemView, QListWidgetItem QListWidgetItem, QDialogButtonBox
) )
from nw.constants import nwAlert, nwItemType from nw.constants import nwAlert, nwItemType
from nw.gui.additions import QHelpLabel
from nw.core import NWDoc from nw.core import NWDoc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -50,34 +52,31 @@ class GuiDocMerge(QDialog):
self.theProject = theProject self.theProject = theProject
self.sourceItem = None self.sourceItem = None
self.outerBox = QHBoxLayout() self.outerBox = QVBoxLayout()
self.innerBox = QVBoxLayout()
self.setLayout(self.outerBox)
self.setWindowTitle("Merge Documents") self.setWindowTitle("Merge Documents")
self.guiDeco = self.theParent.theTheme.loadDecoration("merge",(64,64))
self.outerBox.setSpacing(16)
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop) self.headLabel = QLabel("<b>Documents to Merge</b>")
self.outerBox.addLayout(self.innerBox) self.helpLabel = QHelpLabel(
"Drag and drop items to change the order.", self.theParent.theTheme.helpText
self.doMergeForm = QGridLayout() )
self.doMergeForm.setContentsMargins(0,0,0,0)
self.listBox = QListWidget() self.listBox = QListWidget()
self.listBox.setDragDropMode(QAbstractItemView.InternalMove) self.listBox.setDragDropMode(QAbstractItemView.InternalMove)
self.listBox.setMinimumWidth(400)
self.listBox.setMinimumHeight(180)
self.mergeButton = QPushButton("Merge") self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.mergeButton.clicked.connect(self._doMerge) self.buttonBox.accepted.connect(self._doMerge)
self.buttonBox.rejected.connect(self._doClose)
self.closeButton = QPushButton("Close") self.outerBox.setSpacing(0)
self.closeButton.clicked.connect(self._doClose) self.outerBox.addWidget(self.headLabel)
self.outerBox.addWidget(self.helpLabel)
self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3) self.outerBox.addSpacing(8)
self.doMergeForm.addWidget(self.mergeButton, 1, 1) self.outerBox.addWidget(self.listBox)
self.doMergeForm.addWidget(self.closeButton, 1, 2) self.outerBox.addSpacing(12)
self.outerBox.addWidget(self.buttonBox)
self.innerBox.addLayout(self.doMergeForm) self.setLayout(self.outerBox)
self.rejected.connect(self._doClose) self.rejected.connect(self._doClose)
self.show() self.show()
+22 -24
View File
@@ -30,10 +30,11 @@ import nw
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QComboBox, QDialog, QVBoxLayout, QComboBox, QListWidget, QAbstractItemView,
QListWidget, QAbstractItemView, QListWidgetItem QListWidgetItem, QDialogButtonBox, QLabel
) )
from nw.constants import nwAlert, nwItemType, nwItemClass, nwItemLayout from nw.constants import nwAlert, nwItemType, nwItemClass, nwItemLayout
from nw.gui.additions import QHelpLabel
from nw.core import NWDoc from nw.core import NWDoc
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -51,22 +52,18 @@ class GuiDocSplit(QDialog):
self.optState = self.theProject.optState self.optState = self.theProject.optState
self.sourceItem = None self.sourceItem = None
self.outerBox = QHBoxLayout() self.outerBox = QVBoxLayout()
self.innerBox = QVBoxLayout()
self.setLayout(self.outerBox)
self.setWindowTitle("Split Document") self.setWindowTitle("Split Document")
self.guiDeco = self.theParent.theTheme.loadDecoration("split",(64,64))
self.outerBox.setSpacing(16)
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop) self.headLabel = QLabel("<b>Document Headers</b>")
self.outerBox.addLayout(self.innerBox) self.helpLabel = QHelpLabel(
"Select the maximum level to split into files at.", self.theParent.theTheme.helpText
self.doMergeForm = QGridLayout() )
self.doMergeForm.setContentsMargins(0,0,0,0)
self.listBox = QListWidget() self.listBox = QListWidget()
self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop) self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop)
self.listBox.setMinimumWidth(400)
self.listBox.setMinimumHeight(180)
self.splitLevel = QComboBox(self) self.splitLevel = QComboBox(self)
self.splitLevel.addItem("Split on Header Level 1 (Title)", 1) self.splitLevel.addItem("Split on Header Level 1 (Title)", 1)
@@ -80,18 +77,19 @@ class GuiDocSplit(QDialog):
self.splitLevel.setCurrentIndex(spIndex) self.splitLevel.setCurrentIndex(spIndex)
self.splitLevel.currentIndexChanged.connect(self._populateList) self.splitLevel.currentIndexChanged.connect(self._populateList)
self.splitButton = QPushButton("Split") self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.splitButton.clicked.connect(self._doSplit) self.buttonBox.accepted.connect(self._doSplit)
self.buttonBox.rejected.connect(self._doClose)
self.closeButton = QPushButton("Close") self.outerBox.setSpacing(0)
self.closeButton.clicked.connect(self._doClose) self.outerBox.addWidget(self.headLabel)
self.outerBox.addWidget(self.helpLabel)
self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3) self.outerBox.addSpacing(8)
self.doMergeForm.addWidget(self.splitLevel, 1, 0, 1, 3) self.outerBox.addWidget(self.listBox)
self.doMergeForm.addWidget(self.splitButton, 2, 1) self.outerBox.addWidget(self.splitLevel)
self.doMergeForm.addWidget(self.closeButton, 2, 2) self.outerBox.addSpacing(12)
self.outerBox.addWidget(self.buttonBox)
self.innerBox.addLayout(self.doMergeForm) self.setLayout(self.outerBox)
self.rejected.connect(self._doClose) self.rejected.connect(self._doClose)
self.show() self.show()
+40 -31
View File
@@ -30,11 +30,11 @@ import nw
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QGridLayout, QLineEdit, QDialog, QVBoxLayout, QGridLayout, QLineEdit, QComboBox, QLabel,
QComboBox, QLabel, QSpacerItem, QSizePolicy, QDialogButtonBox QDialogButtonBox
) )
from nw.gui.additions import QSwitch from nw.gui.additions import QSwitch, QHelpLabel
from nw.constants import nwLabels, nwItemLayout, nwItemClass, nwItemType from nw.constants import nwLabels, nwItemLayout, nwItemClass, nwItemType
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -49,31 +49,30 @@ class GuiItemEditor(QDialog):
self.mainConf = nw.CONFIG self.mainConf = nw.CONFIG
self.theProject = theProject self.theProject = theProject
self.theParent = theParent self.theParent = theParent
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.theItem = self.theProject.projTree[tHandle] self.outerBox = QVBoxLayout()
self.theItem = self.theProject.projTree[tHandle]
if self.theItem is None: if self.theItem is None:
self._doClose() self._doClose()
self.setWindowTitle("Item Settings") self.setWindowTitle("Item Settings")
self.guiDeco = self.theParent.theTheme.loadDecoration("settings", (64,64))
self.outerBox.setSpacing(16)
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox)
self.setLayout(self.outerBox) self.setLayout(self.outerBox)
self.mainGroup = QGroupBox("Item Settings") # Labels
self.mainForm = QGridLayout() self.headLabel = QLabel("<b>Edit Item Settings</b>")
self.helpLabel = QHelpLabel(
"Item layout and status options depend on the root folder.",
self.theParent.theTheme.helpText
)
# Item Label
self.editName = QLineEdit() self.editName = QLineEdit()
self.editName.setMinimumWidth(220) self.editName.setMinimumWidth(220)
self.editName.setMaxLength(200) self.editName.setMaxLength(200)
# Item Status
self.editStatus = QComboBox() self.editStatus = QComboBox()
self.editLayout = QComboBox()
if self.theItem.itemClass == nwItemClass.NOVEL: if self.theItem.itemClass == nwItemClass.NOVEL:
for sLabel, _, _ in self.theProject.statusItems: for sLabel, _, _ in self.theProject.statusItems:
self.editStatus.addItem( self.editStatus.addItem(
@@ -85,6 +84,8 @@ class GuiItemEditor(QDialog):
self.theParent.importIcons[sLabel], sLabel, sLabel self.theParent.importIcons[sLabel], sLabel, sLabel
) )
# Item Layout
self.editLayout = QComboBox()
self.validLayouts = [] self.validLayouts = []
if self.theItem.itemType == nwItemType.FILE: if self.theItem.itemType == nwItemType.FILE:
if self.theItem.itemClass == nwItemClass.NOVEL: if self.theItem.itemClass == nwItemClass.NOVEL:
@@ -105,6 +106,7 @@ class GuiItemEditor(QDialog):
if itemLayout in self.validLayouts: if itemLayout in self.validLayouts:
self.editLayout.addItem(nwLabels.LAYOUT_NAME[itemLayout],itemLayout) self.editLayout.addItem(nwLabels.LAYOUT_NAME[itemLayout],itemLayout)
# Export Switch
self.textExport = QLabel("Include when building project") self.textExport = QLabel("Include when building project")
self.editExport = QSwitch() self.editExport = QSwitch()
if self.theItem.itemType == nwItemType.FILE: if self.theItem.itemType == nwItemType.FILE:
@@ -114,18 +116,6 @@ class GuiItemEditor(QDialog):
self.editExport.setEnabled(False) self.editExport.setEnabled(False)
self.editExport.setChecked(False) self.editExport.setChecked(False)
self.mainForm.addWidget(QLabel("Label"), 0, 0)
self.mainForm.addWidget(self.editName, 0, 1, 1, 2)
self.mainForm.addWidget(QLabel("Status"), 1, 0)
self.mainForm.addWidget(self.editStatus, 1, 1, 1, 2)
self.mainForm.addWidget(QLabel("Layout"), 2, 0)
self.mainForm.addWidget(self.editLayout, 2, 1, 1, 2)
self.mainForm.addWidget(self.textExport, 4, 0, 1, 2)
self.mainForm.addWidget(self.editExport, 4, 2)
self.spacerItem = QSpacerItem(12, 12, QSizePolicy.Fixed, QSizePolicy.Fixed)
self.mainForm.addItem(self.spacerItem, 3, 0)
self.editName.setText(self.theItem.itemName) self.editName.setText(self.theItem.itemName)
statusIdx = self.editStatus.findData(self.theItem.itemStatus) statusIdx = self.editStatus.findData(self.theItem.itemStatus)
if statusIdx != -1: if statusIdx != -1:
@@ -134,14 +124,34 @@ class GuiItemEditor(QDialog):
if layoutIdx != -1: if layoutIdx != -1:
self.editLayout.setCurrentIndex(layoutIdx) self.editLayout.setCurrentIndex(layoutIdx)
# Buttons
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doSave) self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self._doClose) self.buttonBox.rejected.connect(self._doClose)
self.mainGroup.setLayout(self.mainForm) # Assemble
self.innerBox.addWidget(self.mainGroup) self.mainForm = QGridLayout()
self.innerBox.addWidget(self.buttonBox) self.mainForm.setVerticalSpacing(4)
self.mainForm.addWidget(QLabel("Label"), 0, 0, 1, 1)
self.mainForm.addWidget(self.editName, 0, 1, 1, 2)
self.mainForm.addWidget(QLabel("Status"), 1, 0, 1, 1)
self.mainForm.addWidget(self.editStatus, 1, 1, 1, 2)
self.mainForm.addWidget(QLabel("Layout"), 2, 0, 1, 1)
self.mainForm.addWidget(self.editLayout, 2, 1, 1, 2)
self.mainForm.addWidget(self.textExport, 3, 0, 1, 2)
self.mainForm.addWidget(self.editExport, 3, 2, 1, 1)
self.outerBox.setSpacing(0)
self.outerBox.addWidget(self.headLabel)
self.outerBox.addWidget(self.helpLabel)
self.outerBox.addSpacing(8)
self.outerBox.addLayout(self.mainForm)
self.outerBox.addSpacing(12)
self.outerBox.addStretch(1)
self.outerBox.addWidget(self.buttonBox)
self.setLayout(self.outerBox)
self.rejected.connect(self._doClose)
self.show() self.show()
self.editName.selectAll() self.editName.selectAll()
@@ -175,7 +185,6 @@ class GuiItemEditor(QDialog):
def _doClose(self): def _doClose(self):
logger.verbose("ItemEditor close button clicked") logger.verbose("ItemEditor close button clicked")
self.reject()
self.close() self.close()
return return
+34 -43
View File
@@ -31,20 +31,21 @@ import nw
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit, QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QLineEdit, QPlainTextEdit,
QLabel, QWidget, QTabWidget, QDialogButtonBox, QListWidget, QPushButton, QLabel, QWidget, QTabWidget, QDialogButtonBox, QListWidget, QPushButton,
QListWidgetItem, QColorDialog, QAbstractItemView, QTreeWidget, QCheckBox, QListWidgetItem, QColorDialog, QAbstractItemView, QTreeWidget, QCheckBox,
QTreeWidgetItem QTreeWidgetItem
) )
from nw.constants import nwAlert from nw.constants import nwAlert
from nw.gui.additions import QSwitch, PagedDialog
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class GuiProjectEditor(QDialog): class GuiProjectEditor(PagedDialog):
def __init__(self, theParent, theProject): def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent) PagedDialog.__init__(self, theParent)
logger.debug("Initialising ProjectEditor ...") logger.debug("Initialising ProjectEditor ...")
@@ -52,35 +53,23 @@ class GuiProjectEditor(QDialog):
self.theParent = theParent self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.setWindowTitle("Project Settings")
self.guiDeco = self.theParent.theTheme.loadDecoration("settings", (64,64))
self.outerBox.setSpacing(16)
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
self.outerBox.addLayout(self.innerBox)
self.setLayout(self.outerBox)
self.theProject.countStatus() self.theProject.countStatus()
self.setWindowTitle("Project Settings")
self.tabMain = GuiProjectEditMain(self.theParent, self.theProject) self.tabMain = GuiProjectEditMain(self.theParent, self.theProject)
self.tabStatus = GuiProjectEditStatus(self.theParent, self.theProject.statusItems) self.tabStatus = GuiProjectEditStatus(self.theParent, self.theProject.statusItems)
self.tabImport = GuiProjectEditStatus(self.theParent, self.theProject.importItems) self.tabImport = GuiProjectEditStatus(self.theParent, self.theProject.importItems)
self.tabReplace = GuiProjectEditReplace(self.theParent, self.theProject) self.tabReplace = GuiProjectEditReplace(self.theParent, self.theProject)
self.tabWidget = QTabWidget() self.addTab(self.tabMain, "Settings")
self.tabWidget.addTab(self.tabMain, "Settings") self.addTab(self.tabStatus, "Status")
self.tabWidget.addTab(self.tabStatus, "Status") self.addTab(self.tabImport, "Importance")
self.tabWidget.addTab(self.tabImport, "Importance") self.addTab(self.tabReplace,"Auto-Replace")
self.tabWidget.addTab(self.tabReplace,"Auto-Replace")
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doSave) self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self._doClose) self.buttonBox.rejected.connect(self._doClose)
self.addControls(self.buttonBox)
self.innerBox.addWidget(self.tabWidget)
self.innerBox.addWidget(self.buttonBox)
self.show() self.show()
@@ -94,7 +83,7 @@ class GuiProjectEditor(QDialog):
projName = self.tabMain.editName.text() projName = self.tabMain.editName.text()
bookTitle = self.tabMain.editTitle.text() bookTitle = self.tabMain.editTitle.text()
bookAuthors = self.tabMain.editAuthors.toPlainText() bookAuthors = self.tabMain.editAuthors.toPlainText()
doBackup = self.tabMain.doBackup.isChecked() doBackup = not self.tabMain.doBackup.isChecked()
self.theProject.setProjectName(projName) self.theProject.setProjectName(projName)
self.theProject.setBookTitle(bookTitle) self.theProject.setBookTitle(bookTitle)
self.theProject.setBookAuthors(bookAuthors) self.theProject.setBookAuthors(bookAuthors)
@@ -130,37 +119,39 @@ class GuiProjectEditMain(QWidget):
self.theParent = theParent self.theParent = theParent
self.theProject = theProject self.theProject = theProject
self.mainForm = QFormLayout() self.mainForm = QGridLayout()
self.backupBox = QHBoxLayout() self.backupBox = QHBoxLayout()
self.editName = QLineEdit()
self.editTitle = QLineEdit()
self.editAuthors = QPlainTextEdit()
self.doBackup = QCheckBox(self)
self.editName = QLineEdit()
self.editName.setMaxLength(200) self.editName.setMaxLength(200)
self.editTitle.setMaxLength(200)
self.mainForm.addRow("Working Title", self.editName)
self.mainForm.addRow("Book Title", self.editTitle)
self.mainForm.addRow("Book Authors", self.editAuthors)
self.mainForm.addRow(self.backupBox)
self.backupBox.addStretch(1)
self.backupBox.addWidget(QLabel("Backup on Close"))
self.backupBox.addWidget(self.doBackup)
self.editName.setText(self.theProject.projName) self.editName.setText(self.theProject.projName)
self.editTitle = QLineEdit()
self.editTitle.setMaxLength(200)
self.editTitle.setText(self.theProject.bookTitle) self.editTitle.setText(self.theProject.bookTitle)
self.editAuthors = QPlainTextEdit()
bookAuthors = "" bookAuthors = ""
for bookAuthor in self.theProject.bookAuthors: for bookAuthor in self.theProject.bookAuthors:
bookAuthors += bookAuthor+"\n" bookAuthors += bookAuthor+"\n"
self.editAuthors.setPlainText(bookAuthors) self.editAuthors.setPlainText(bookAuthors)
if self.theProject.doBackup: self.editAuthors.setMaximumHeight(120)
self.doBackup.setCheckState(Qt.Checked)
else: self.doBackup = QSwitch(self)
self.doBackup.setCheckState(Qt.Unchecked) self.doBackup.setChecked(not self.theProject.doBackup)
self.backupBox.addStretch(1)
self.backupBox.addWidget(QLabel("Disable backup on close"))
self.backupBox.addWidget(self.doBackup)
self.mainForm.addWidget(QLabel("Working title"), 0, 0, 1, 1, Qt.AlignTop)
self.mainForm.addWidget(self.editName, 0, 1, 1, 1, Qt.AlignTop)
self.mainForm.addWidget(QLabel("Book title"), 1, 0, 1, 1, Qt.AlignTop)
self.mainForm.addWidget(self.editTitle, 1, 1, 1, 1, Qt.AlignTop)
self.mainForm.addWidget(QLabel("Book authors"), 2, 0, 1, 1, Qt.AlignTop)
self.mainForm.addWidget(self.editAuthors, 2, 1, 1, 1, Qt.AlignTop)
self.mainForm.addLayout(self.backupBox, 3, 0, 1, 2, Qt.AlignTop)
self.setLayout(self.mainForm) self.setLayout(self.mainForm)
self.editAuthors.setMaximumHeight(120)
return return
-4
View File
@@ -99,10 +99,6 @@ class GuiIcons:
DECO_MAP = { DECO_MAP = {
"nwicon" : ["icons", "novelWriter.svg"], "nwicon" : ["icons", "novelWriter.svg"],
"export" : ["graphics", "export.svg"],
"merge" : ["graphics", "merge.svg"],
"settings" : ["graphics", "gear.svg"],
"split" : ["graphics", "split.svg"],
} }
def __init__(self, theParent): def __init__(self, theParent):
+2 -2
View File
@@ -276,7 +276,7 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef, nwTemp):
qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay) qtbot.keyClick(projEdit.tabMain.editAuthors, c, delay=keyDelay)
# Test Status Tab # Test Status Tab
projEdit.tabWidget.setCurrentWidget(projEdit.tabStatus) projEdit._tabBox.setCurrentWidget(projEdit.tabStatus)
projEdit.tabStatus.listBox.item(2).setSelected(True) projEdit.tabStatus.listBox.item(2).setSelected(True)
qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton) qtbot.mouseClick(projEdit.tabStatus.delButton, Qt.LeftButton)
qtbot.mouseClick(projEdit.tabStatus.newButton, Qt.LeftButton) qtbot.mouseClick(projEdit.tabStatus.newButton, Qt.LeftButton)
@@ -288,7 +288,7 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef, nwTemp):
qtbot.mouseClick(projEdit.tabStatus.saveButton, Qt.LeftButton) qtbot.mouseClick(projEdit.tabStatus.saveButton, Qt.LeftButton)
# Auto-Replace Tab # Auto-Replace Tab
projEdit.tabWidget.setCurrentWidget(projEdit.tabReplace) projEdit._tabBox.setCurrentWidget(projEdit.tabReplace)
qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton) qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton)
projEdit.tabReplace.listBox.topLevelItem(0).setSelected(True) projEdit.tabReplace.listBox.topLevelItem(0).setSelected(True)