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.theme import GuiTheme
# Qt Additions
from nw.gui.additions.qconfiglayout import QConfigLayout
from nw.gui.additions.qswitch import QSwitch
# Dialogs
from nw.gui.dialogs.configeditor import GuiConfigEditor
from nw.gui.dialogs.docmerge import GuiDocMerge
@@ -42,8 +38,6 @@ __all__ = [
"GuiMainMenu",
"GuiMainStatus",
"GuiTheme",
"QConfigLayout",
"QSwitch",
"GuiConfigEditor",
"GuiDocMerge",
"GuiDocSplit",
+4
View File
@@ -1,8 +1,12 @@
# -*- coding: utf-8 -*-
from nw.gui.additions.pageddialog import PagedDialog
from nw.gui.additions.qconfiglayout import QConfigLayout
from nw.gui.additions.qconfiglayout import QHelpLabel
from nw.gui.additions.qswitch import QSwitch
__all__ = [
"PagedDialog",
"QConfigLayout",
"QHelpLabel",
"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)
if helpText is not None:
qHelp = QLabel(str(helpText))
qHelp = QHelpLabel(str(helpText), self._helpCol, self._fontScale)
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.addWidget(qLabel)
labelBox.addWidget(qHelp)
@@ -176,3 +168,25 @@ class QConfigLayout(QGridLayout):
return self._nextRow - 1
# 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
)
from nw.gui.additions import QSwitch, QConfigLayout
from nw.gui.additions import QSwitch, QConfigLayout, PagedDialog
from nw.core import NWSpellCheck, NWSpellSimple, NWSpellEnchant
from nw.constants import nwAlert, nwQuotes
logger = logging.getLogger(__name__)
class GuiConfigEditor(QDialog):
class GuiConfigEditor(PagedDialog):
def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent)
PagedDialog.__init__(self, theParent)
logger.debug("Initialising ConfigEditor ...")
self.mainConf = nw.CONFIG
self.theParent = theParent
self.theProject = theProject
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
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.tabLayout = GuiConfigEditLayoutTab(self.theParent)
self.tabEditing = GuiConfigEditEditingTab(self.theParent)
self.tabAutoRep = GuiConfigEditAutoReplaceTab(self.theParent)
self.tabWidget = QTabWidget()
self.tabWidget.setMinimumWidth(600)
self.tabWidget.addTab(self.tabGeneral, "General")
self.tabWidget.addTab(self.tabLayout, "Layout")
self.tabWidget.addTab(self.tabEditing, "Editing")
self.tabWidget.addTab(self.tabAutoRep, "Auto-Replace")
self.addTab(self.tabGeneral, "General")
self.addTab(self.tabLayout, "Layout")
self.addTab(self.tabEditing, "Editing")
self.addTab(self.tabAutoRep, "Auto-Replace")
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self._doClose)
self.innerBox.addWidget(self.tabWidget)
self.innerBox.addWidget(self.buttonBox)
self.addControls(self.buttonBox)
self.show()
@@ -773,6 +761,7 @@ class GuiConfigEditAutoReplaceTab(QWidget):
def saveValues(self):
validEntries = True
needsRestart = False
autoSelect = self.autoSelect.isChecked()
doReplace = self.autoReplaceMain.isChecked()
@@ -827,7 +816,7 @@ class GuiConfigEditAutoReplaceTab(QWidget):
self.mainConf.confChanged = True
return validEntries, False
return validEntries, needsRestart
##
# Slots
+22 -23
View File
@@ -30,10 +30,12 @@ import nw
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton,
QListWidget, QAbstractItemView, QListWidgetItem
QDialog, QVBoxLayout, QLabel, QListWidget, QAbstractItemView,
QListWidgetItem, QDialogButtonBox
)
from nw.constants import nwAlert, nwItemType
from nw.gui.additions import QHelpLabel
from nw.core import NWDoc
logger = logging.getLogger(__name__)
@@ -50,34 +52,31 @@ class GuiDocMerge(QDialog):
self.theProject = theProject
self.sourceItem = None
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.setLayout(self.outerBox)
self.outerBox = QVBoxLayout()
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.outerBox.addLayout(self.innerBox)
self.doMergeForm = QGridLayout()
self.doMergeForm.setContentsMargins(0,0,0,0)
self.headLabel = QLabel("<b>Documents to Merge</b>")
self.helpLabel = QHelpLabel(
"Drag and drop items to change the order.", self.theParent.theTheme.helpText
)
self.listBox = QListWidget()
self.listBox.setDragDropMode(QAbstractItemView.InternalMove)
self.listBox.setMinimumWidth(400)
self.listBox.setMinimumHeight(180)
self.mergeButton = QPushButton("Merge")
self.mergeButton.clicked.connect(self._doMerge)
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doMerge)
self.buttonBox.rejected.connect(self._doClose)
self.closeButton = QPushButton("Close")
self.closeButton.clicked.connect(self._doClose)
self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3)
self.doMergeForm.addWidget(self.mergeButton, 1, 1)
self.doMergeForm.addWidget(self.closeButton, 1, 2)
self.innerBox.addLayout(self.doMergeForm)
self.outerBox.setSpacing(0)
self.outerBox.addWidget(self.headLabel)
self.outerBox.addWidget(self.helpLabel)
self.outerBox.addSpacing(8)
self.outerBox.addWidget(self.listBox)
self.outerBox.addSpacing(12)
self.outerBox.addWidget(self.buttonBox)
self.setLayout(self.outerBox)
self.rejected.connect(self._doClose)
self.show()
+22 -24
View File
@@ -30,10 +30,11 @@ import nw
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QComboBox,
QListWidget, QAbstractItemView, QListWidgetItem
QDialog, QVBoxLayout, QComboBox, QListWidget, QAbstractItemView,
QListWidgetItem, QDialogButtonBox, QLabel
)
from nw.constants import nwAlert, nwItemType, nwItemClass, nwItemLayout
from nw.gui.additions import QHelpLabel
from nw.core import NWDoc
logger = logging.getLogger(__name__)
@@ -51,22 +52,18 @@ class GuiDocSplit(QDialog):
self.optState = self.theProject.optState
self.sourceItem = None
self.outerBox = QHBoxLayout()
self.innerBox = QVBoxLayout()
self.setLayout(self.outerBox)
self.outerBox = QVBoxLayout()
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.outerBox.addLayout(self.innerBox)
self.doMergeForm = QGridLayout()
self.doMergeForm.setContentsMargins(0,0,0,0)
self.headLabel = QLabel("<b>Document Headers</b>")
self.helpLabel = QHelpLabel(
"Select the maximum level to split into files at.", self.theParent.theTheme.helpText
)
self.listBox = QListWidget()
self.listBox.setDragDropMode(QAbstractItemView.NoDragDrop)
self.listBox.setMinimumWidth(400)
self.listBox.setMinimumHeight(180)
self.splitLevel = QComboBox(self)
self.splitLevel.addItem("Split on Header Level 1 (Title)", 1)
@@ -80,18 +77,19 @@ class GuiDocSplit(QDialog):
self.splitLevel.setCurrentIndex(spIndex)
self.splitLevel.currentIndexChanged.connect(self._populateList)
self.splitButton = QPushButton("Split")
self.splitButton.clicked.connect(self._doSplit)
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doSplit)
self.buttonBox.rejected.connect(self._doClose)
self.closeButton = QPushButton("Close")
self.closeButton.clicked.connect(self._doClose)
self.doMergeForm.addWidget(self.listBox, 0, 0, 1, 3)
self.doMergeForm.addWidget(self.splitLevel, 1, 0, 1, 3)
self.doMergeForm.addWidget(self.splitButton, 2, 1)
self.doMergeForm.addWidget(self.closeButton, 2, 2)
self.innerBox.addLayout(self.doMergeForm)
self.outerBox.setSpacing(0)
self.outerBox.addWidget(self.headLabel)
self.outerBox.addWidget(self.helpLabel)
self.outerBox.addSpacing(8)
self.outerBox.addWidget(self.listBox)
self.outerBox.addWidget(self.splitLevel)
self.outerBox.addSpacing(12)
self.outerBox.addWidget(self.buttonBox)
self.setLayout(self.outerBox)
self.rejected.connect(self._doClose)
self.show()
+40 -31
View File
@@ -30,11 +30,11 @@ import nw
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QGridLayout, QLineEdit,
QComboBox, QLabel, QSpacerItem, QSizePolicy, QDialogButtonBox
QDialog, QVBoxLayout, QGridLayout, QLineEdit, QComboBox, QLabel,
QDialogButtonBox
)
from nw.gui.additions import QSwitch
from nw.gui.additions import QSwitch, QHelpLabel
from nw.constants import nwLabels, nwItemLayout, nwItemClass, nwItemType
logger = logging.getLogger(__name__)
@@ -49,31 +49,30 @@ class GuiItemEditor(QDialog):
self.mainConf = nw.CONFIG
self.theProject = theProject
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:
self._doClose()
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.mainGroup = QGroupBox("Item Settings")
self.mainForm = QGridLayout()
# Labels
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.setMinimumWidth(220)
self.editName.setMaxLength(200)
# Item Status
self.editStatus = QComboBox()
self.editLayout = QComboBox()
if self.theItem.itemClass == nwItemClass.NOVEL:
for sLabel, _, _ in self.theProject.statusItems:
self.editStatus.addItem(
@@ -85,6 +84,8 @@ class GuiItemEditor(QDialog):
self.theParent.importIcons[sLabel], sLabel, sLabel
)
# Item Layout
self.editLayout = QComboBox()
self.validLayouts = []
if self.theItem.itemType == nwItemType.FILE:
if self.theItem.itemClass == nwItemClass.NOVEL:
@@ -105,6 +106,7 @@ class GuiItemEditor(QDialog):
if itemLayout in self.validLayouts:
self.editLayout.addItem(nwLabels.LAYOUT_NAME[itemLayout],itemLayout)
# Export Switch
self.textExport = QLabel("Include when building project")
self.editExport = QSwitch()
if self.theItem.itemType == nwItemType.FILE:
@@ -114,18 +116,6 @@ class GuiItemEditor(QDialog):
self.editExport.setEnabled(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)
statusIdx = self.editStatus.findData(self.theItem.itemStatus)
if statusIdx != -1:
@@ -134,14 +124,34 @@ class GuiItemEditor(QDialog):
if layoutIdx != -1:
self.editLayout.setCurrentIndex(layoutIdx)
# Buttons
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self._doClose)
self.mainGroup.setLayout(self.mainForm)
self.innerBox.addWidget(self.mainGroup)
self.innerBox.addWidget(self.buttonBox)
# Assemble
self.mainForm = QGridLayout()
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.editName.selectAll()
@@ -175,7 +185,6 @@ class GuiItemEditor(QDialog):
def _doClose(self):
logger.verbose("ItemEditor close button clicked")
self.reject()
self.close()
return
+34 -43
View File
@@ -31,20 +31,21 @@ import nw
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush
from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit,
QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QLineEdit, QPlainTextEdit,
QLabel, QWidget, QTabWidget, QDialogButtonBox, QListWidget, QPushButton,
QListWidgetItem, QColorDialog, QAbstractItemView, QTreeWidget, QCheckBox,
QTreeWidgetItem
)
from nw.constants import nwAlert
from nw.gui.additions import QSwitch, PagedDialog
logger = logging.getLogger(__name__)
class GuiProjectEditor(QDialog):
class GuiProjectEditor(PagedDialog):
def __init__(self, theParent, theProject):
QDialog.__init__(self, theParent)
PagedDialog.__init__(self, theParent)
logger.debug("Initialising ProjectEditor ...")
@@ -52,35 +53,23 @@ class GuiProjectEditor(QDialog):
self.theParent = theParent
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.setWindowTitle("Project Settings")
self.tabMain = GuiProjectEditMain(self.theParent, self.theProject)
self.tabStatus = GuiProjectEditStatus(self.theParent, self.theProject.statusItems)
self.tabImport = GuiProjectEditStatus(self.theParent, self.theProject.importItems)
self.tabReplace = GuiProjectEditReplace(self.theParent, self.theProject)
self.tabWidget = QTabWidget()
self.tabWidget.addTab(self.tabMain, "Settings")
self.tabWidget.addTab(self.tabStatus, "Status")
self.tabWidget.addTab(self.tabImport, "Importance")
self.tabWidget.addTab(self.tabReplace,"Auto-Replace")
self.addTab(self.tabMain, "Settings")
self.addTab(self.tabStatus, "Status")
self.addTab(self.tabImport, "Importance")
self.addTab(self.tabReplace,"Auto-Replace")
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self._doClose)
self.innerBox.addWidget(self.tabWidget)
self.innerBox.addWidget(self.buttonBox)
self.addControls(self.buttonBox)
self.show()
@@ -94,7 +83,7 @@ class GuiProjectEditor(QDialog):
projName = self.tabMain.editName.text()
bookTitle = self.tabMain.editTitle.text()
bookAuthors = self.tabMain.editAuthors.toPlainText()
doBackup = self.tabMain.doBackup.isChecked()
doBackup = not self.tabMain.doBackup.isChecked()
self.theProject.setProjectName(projName)
self.theProject.setBookTitle(bookTitle)
self.theProject.setBookAuthors(bookAuthors)
@@ -130,37 +119,39 @@ class GuiProjectEditMain(QWidget):
self.theParent = theParent
self.theProject = theProject
self.mainForm = QFormLayout()
self.mainForm = QGridLayout()
self.backupBox = QHBoxLayout()
self.editName = QLineEdit()
self.editTitle = QLineEdit()
self.editAuthors = QPlainTextEdit()
self.doBackup = QCheckBox(self)
self.editName = QLineEdit()
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.editTitle = QLineEdit()
self.editTitle.setMaxLength(200)
self.editTitle.setText(self.theProject.bookTitle)
self.editAuthors = QPlainTextEdit()
bookAuthors = ""
for bookAuthor in self.theProject.bookAuthors:
bookAuthors += bookAuthor+"\n"
self.editAuthors.setPlainText(bookAuthors)
if self.theProject.doBackup:
self.doBackup.setCheckState(Qt.Checked)
else:
self.doBackup.setCheckState(Qt.Unchecked)
self.editAuthors.setMaximumHeight(120)
self.doBackup = QSwitch(self)
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.editAuthors.setMaximumHeight(120)
return
-4
View File
@@ -99,10 +99,6 @@ class GuiIcons:
DECO_MAP = {
"nwicon" : ["icons", "novelWriter.svg"],
"export" : ["graphics", "export.svg"],
"merge" : ["graphics", "merge.svg"],
"settings" : ["graphics", "gear.svg"],
"split" : ["graphics", "split.svg"],
}
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)
# Test Status Tab
projEdit.tabWidget.setCurrentWidget(projEdit.tabStatus)
projEdit._tabBox.setCurrentWidget(projEdit.tabStatus)
projEdit.tabStatus.listBox.item(2).setSelected(True)
qtbot.mouseClick(projEdit.tabStatus.delButton, 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)
# Auto-Replace Tab
projEdit.tabWidget.setCurrentWidget(projEdit.tabReplace)
projEdit._tabBox.setCurrentWidget(projEdit.tabReplace)
qtbot.mouseClick(projEdit.tabReplace.addButton, Qt.LeftButton)
projEdit.tabReplace.listBox.topLevelItem(0).setSelected(True)