Gui sizes should now scale between high and low DPI screens

This commit is contained in:
Veronica K. B. Olsen
2020-06-05 16:18:20 +02:00
parent 0a3751046b
commit d95e8caa50
11 changed files with 167 additions and 100 deletions
+47 -10
View File
@@ -205,12 +205,13 @@ class Config:
"""Used to scale fixed gui sizes by the screen scale factor.
This function returns an int, which is always rounded down.
"""
return int(self.guiScale*theSize)
return int(theSize*self.guiScale)
def pxFloat(self, theSize):
"""Used to scale fixed gui sizes by the screen scale factor.
def rpxInt(self, theSize):
"""Used to un-scale fixed gui sizes by the screen scale factor.
This function returns an int, which is always rounded down.
"""
return self.guiScale*theSize
return int(theSize/self.guiScale)
##
# Config Actions
@@ -663,7 +664,7 @@ class Config:
return True
##
# Setters and Getters
# Setters
##
def setConfPath(self, newPath):
@@ -693,6 +694,8 @@ class Config:
return True
def setWinSize(self, newWidth, newHeight):
newWidth = int(newWidth/self.guiScale)
newHeight = int(newHeight/self.guiScale)
if abs(self.winGeometry[0] - newWidth) > 5:
self.winGeometry[0] = newWidth
self.confChanged = True
@@ -702,27 +705,27 @@ class Config:
return True
def setTreeColWidths(self, colWidths):
self.treeColWidth = colWidths
self.treeColWidth = [int(x/self.guiScale) for x in colWidths]
self.confChanged = True
return True
def setProjColWidths(self, colWidths):
self.projColWidth = colWidths
self.projColWidth = [int(x/self.guiScale) for x in colWidths]
self.confChanged = True
return True
def setMainPanePos(self, panePos):
self.mainPanePos = panePos
self.mainPanePos = [int(x/self.guiScale) for x in panePos]
self.confChanged = True
return True
def setDocPanePos(self, panePos):
self.docPanePos = panePos
self.docPanePos = [int(x/self.guiScale) for x in panePos]
self.confChanged = True
return True
def setOutlinePanePos(self, panePos):
self.outlnPanePos = panePos
self.outlnPanePos = [int(x/self.guiScale) for x in panePos]
self.confChanged = True
return True
@@ -742,6 +745,40 @@ class Config:
self.errData = []
return errMessage
##
# Getters
##
def getWinSize(self):
return [int(x*self.guiScale) for x in self.winGeometry]
def getTreeColWidths(self):
return [int(x*self.guiScale) for x in self.treeColWidth]
def getProjColWidths(self):
return [int(x*self.guiScale) for x in self.projColWidth]
def getMainPanePos(self):
return [int(x*self.guiScale) for x in self.mainPanePos]
def getDocPanePos(self):
return [int(x*self.guiScale) for x in self.docPanePos]
def getOutlinePanePos(self):
return [int(x*self.guiScale) for x in self.outlnPanePos]
def getTextWidth(self):
return self.pxInt(self.textWidth)
def getTextMargin(self):
return self.pxInt(self.textMargin)
def getTabWidth(self):
return self.pxInt(self.tabWidth)
def getZenWidth(self):
return self.pxInt(self.zenWidth)
##
# Internal Functions
##
+33 -17
View File
@@ -213,14 +213,11 @@ class NWProject():
self.bookAuthors = []
self.autoReplace = {}
self.titleFormat = {
"title" : r"%title%",
"chapter" : r"Chapter %ch%: %title%",
"unnumbered" : r"%title%",
"scene" : r"* * *",
"section" : r"",
"withSynopsis" : False,
"withComments" : False,
"withKeywords" : False,
"title" : r"%title%",
"chapter" : r"Chapter %ch%: %title%",
"unnumbered" : r"%title%",
"scene" : r"* * *",
"section" : r"",
}
self.spellCheck = False
self.autoOutline = True
@@ -835,10 +832,8 @@ class NWProject():
"""Set the formatting of titles in the project.
"""
for valKey, valEntry in titleFormat.items():
if valKey in ("title","chapter","unnumbered","scene","section"):
if valKey in self.titleFormat:
self.titleFormat[valKey] = checkString(valEntry, self.titleFormat[valKey], False)
elif valKey in ("withSynopsis","withComments","withKeywords"):
self.titleFormat[valKey] = checkBool(valEntry, False, False)
return
def setProjectChanged(self, bValue):
@@ -2018,6 +2013,7 @@ class OptionState():
def __init__(self, theProject):
self.mainConf = nw.CONFIG
self.theProject = theProject
self.theState = {}
self.stringOpt = ()
@@ -2026,6 +2022,10 @@ class OptionState():
return
##
# Load and Save Cache
##
def loadSettings(self):
"""Load the options dictionary from the project settings file.
"""
@@ -2038,7 +2038,7 @@ class OptionState():
if path.isfile(stateFile):
logger.debug("Loading GUI options file")
try:
with open(stateFile,mode="r",encoding="utf8") as inFile:
with open(stateFile, mode="r", encoding="utf8") as inFile:
theJson = inFile.read()
theState = json.loads(theJson)
except Exception as e:
@@ -2060,7 +2060,7 @@ class OptionState():
logger.debug("Saving GUI options file")
try:
with open(stateFile,mode="w+",encoding="utf8") as outFile:
with open(stateFile, mode="w+", encoding="utf8") as outFile:
outFile.write(json.dumps(self.theState, indent=2))
except Exception as e:
logger.error("Failed to save GUI options file")
@@ -2069,6 +2069,10 @@ class OptionState():
return True
##
# Setters
##
def setValue(self, setGroup, setName, setValue):
"""Saves a value, with a given group and name.
"""
@@ -2077,6 +2081,10 @@ class OptionState():
self.theState[setGroup][setName] = setValue
return True
##
# Getters
##
def getValue(self, getGroup, getName, defaultValue):
"""Return an arbitrary type value, if it exists. Otherwise,
return the default value.
@@ -2085,7 +2093,8 @@ class OptionState():
if getName in self.theState[getGroup]:
try:
return self.theState[getGroup][getName]
except:
except Exception as e:
logger.warning(str(e))
return defaultValue
return defaultValue
@@ -2109,7 +2118,8 @@ class OptionState():
if getName in self.theState[getGroup]:
try:
return int(self.theState[getGroup][getName])
except:
except Exception as e:
logger.warning(str(e))
return defaultValue
return defaultValue
@@ -2121,7 +2131,8 @@ class OptionState():
if getName in self.theState[getGroup]:
try:
return float(self.theState[getGroup][getName])
except:
except Exception as e:
logger.warning(str(e))
return defaultValue
return defaultValue
@@ -2133,10 +2144,15 @@ class OptionState():
if getName in self.theState[getGroup]:
try:
return bool(self.theState[getGroup][getName])
except:
except Exception as e:
logger.warning(str(e))
return defaultValue
return defaultValue
##
# Validators
##
def validIntRange(self, theValue, intA, intB, intDefault):
"""Check that an int is in a given range. If it isn't, return
the default value.
+1 -6
View File
@@ -64,7 +64,7 @@ class GuiAbout(QDialog):
self.lblVers = QLabel("v%s" % nw.__version__)
self.lblDate = QLabel(datetime.strptime(nw.__date__, "%Y-%m-%d").strftime("%x"))
self.leftBox = QVBoxLayout()
self.leftBox = QVBoxLayout()
self.leftBox.setSpacing(self.mainConf.pxInt(4))
self.leftBox.addWidget(self.guiDeco, 0, Qt.AlignCenter)
self.leftBox.addWidget(self.lblName, 0, Qt.AlignCenter)
@@ -78,10 +78,6 @@ class GuiAbout(QDialog):
self.pageAbout.setOpenExternalLinks(True)
self.pageAbout.document().setDocumentMargin(self.mainConf.pxInt(16))
# self.pageCredit = QTextBrowser()
# self.pageCredit.setOpenExternalLinks(True)
# self.pageCredit.document().setDocumentMargin(16)
self.pageLicense = QTextBrowser()
self.pageLicense.setOpenExternalLinks(True)
self.pageLicense.document().setDocumentMargin(self.mainConf.pxInt(16))
@@ -89,7 +85,6 @@ class GuiAbout(QDialog):
# Main Tab Area
self.tabBox = QTabWidget()
self.tabBox.addTab(self.pageAbout, "About")
# self.tabBox.addTab(self.pageCredit, "Credit")
self.tabBox.addTab(self.pageLicense, "License")
self.innerBox.addWidget(self.tabBox)
+47 -30
View File
@@ -77,17 +77,13 @@ class GuiBuildNovel(QDialog):
self.htmlStyle = [] # List of html styles
self.nwdText = [] # List of markdown documents
x800 = self.mainConf.pxInt(800)
x900 = self.mainConf.pxInt(900)
xFmt = self.mainConf.pxInt(220)
self.setWindowTitle("Build Novel Project")
self.setMinimumWidth(x900)
self.setMinimumHeight(x800)
self.setMinimumWidth(self.mainConf.pxInt(900))
self.setMinimumHeight(self.mainConf.pxInt(800))
self.resize(
self.optState.getInt("GuiBuildNovel", "winWidth", x900),
self.optState.getInt("GuiBuildNovel", "winHeight", x800)
self.mainConf.pxInt(self.optState.getInt("GuiBuildNovel", "winWidth", 900)),
self.mainConf.pxInt(self.optState.getInt("GuiBuildNovel", "winHeight", 800))
)
self.outerBox = QHBoxLayout()
@@ -116,6 +112,7 @@ class GuiBuildNovel(QDialog):
r"be centred automatically and only appear between sections of "
r"the same type."
)
xFmt = self.mainConf.pxInt(220)
self.fmtTitle = QLineEdit()
self.fmtTitle.setMaxLength(200)
@@ -240,26 +237,32 @@ class GuiBuildNovel(QDialog):
self.includeSynopsis.setToolTip(
"Include synopsis comments in the output."
)
self.includeSynopsis.setChecked(self.theProject.titleFormat["withSynopsis"])
self.includeSynopsis.setChecked(
self.optState.getBool("GuiBuildNovel", "incSynopsis", False)
)
self.includeComments = QSwitch()
self.includeComments.setToolTip(
"Include plain comments in the output."
)
self.includeComments.setChecked(self.theProject.titleFormat["withComments"])
self.includeComments.setChecked(
self.optState.getBool("GuiBuildNovel", "incComments", False)
)
self.includeKeywords = QSwitch()
self.includeKeywords.setToolTip(
"Include meta keywords (tags, references) in the output."
)
self.includeKeywords.setChecked(self.theProject.titleFormat["withKeywords"])
self.includeKeywords.setChecked(
self.optState.getBool("GuiBuildNovel", "incKeywords", False)
)
self.includeBody = QSwitch()
self.includeBody.setToolTip(
"Include body text in the output."
)
self.includeBody.setChecked(
self.optState.getBool("GuiBuildNovel", "includeBody", True)
self.optState.getBool("GuiBuildNovel", "incBodyText", True)
)
self.textForm.addWidget(QLabel("Include synopsis"), 0, 0, 1, 1, Qt.AlignLeft)
@@ -851,27 +854,41 @@ class GuiBuildNovel(QDialog):
# Formatting
self.theProject.setTitleFormat({
"title" : self.fmtTitle.text().strip(),
"chapter" : self.fmtChapter.text().strip(),
"unnumbered" : self.fmtUnnumbered.text().strip(),
"scene" : self.fmtScene.text().strip(),
"section" : self.fmtSection.text().strip(),
"withSynopsis" : self.includeSynopsis.isChecked(),
"withComments" : self.includeComments.isChecked(),
"withKeywords" : self.includeKeywords.isChecked(),
"title" : self.fmtTitle.text().strip(),
"chapter" : self.fmtChapter.text().strip(),
"unnumbered" : self.fmtUnnumbered.text().strip(),
"scene" : self.fmtScene.text().strip(),
"section" : self.fmtSection.text().strip(),
})
winWidth = self.mainConf.pxInt(self.width())
winHeight = self.mainConf.pxInt(self.height())
justifyText = self.justifyText.isChecked()
noStyling = self.noStyling.isChecked()
textFont = self.textFont.text()
textSize = self.textSize.value()
novelFiles = self.novelFiles.isChecked()
noteFiles = self.noteFiles.isChecked()
ignoreFlag = self.ignoreFlag.isChecked()
incSynopsis = self.includeSynopsis.isChecked()
incComments = self.includeComments.isChecked()
incKeywords = self.includeKeywords.isChecked()
incBodyText = self.includeBody.isChecked()
# GUI Settings
self.optState.setValue("GuiBuildNovel", "winWidth", self.width())
self.optState.setValue("GuiBuildNovel", "winHeight", self.height())
self.optState.setValue("GuiBuildNovel", "justifyText", self.justifyText.isChecked())
self.optState.setValue("GuiBuildNovel", "noStyling", self.noStyling.isChecked())
self.optState.setValue("GuiBuildNovel", "textFont", self.textFont.text())
self.optState.setValue("GuiBuildNovel", "textSize", self.textSize.value())
self.optState.setValue("GuiBuildNovel", "addNovel", self.novelFiles.isChecked())
self.optState.setValue("GuiBuildNovel", "addNotes", self.noteFiles.isChecked())
self.optState.setValue("GuiBuildNovel", "ignoreFlag", self.ignoreFlag.isChecked())
self.optState.setValue("GuiBuildNovel", "includeBody", self.includeBody.isChecked())
self.optState.setValue("GuiBuildNovel", "winWidth", winWidth)
self.optState.setValue("GuiBuildNovel", "winHeight", winHeight)
self.optState.setValue("GuiBuildNovel", "justifyText", justifyText)
self.optState.setValue("GuiBuildNovel", "noStyling", noStyling)
self.optState.setValue("GuiBuildNovel", "textFont", textFont)
self.optState.setValue("GuiBuildNovel", "textSize", textSize)
self.optState.setValue("GuiBuildNovel", "addNovel", novelFiles)
self.optState.setValue("GuiBuildNovel", "addNotes", noteFiles)
self.optState.setValue("GuiBuildNovel", "ignoreFlag", ignoreFlag)
self.optState.setValue("GuiBuildNovel", "incSynopsis", incSynopsis)
self.optState.setValue("GuiBuildNovel", "incComments", incComments)
self.optState.setValue("GuiBuildNovel", "incKeywords", incKeywords)
self.optState.setValue("GuiBuildNovel", "incBodyText", incBodyText)
self.optState.saveSettings()
return
+11 -11
View File
@@ -81,7 +81,7 @@ class GuiDocEditor(QTextEdit):
# Core Elements
self.qDocument = self.document()
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
self.qDocument.setDocumentMargin(self.mainConf.getTextMargin())
self.qDocument.contentsChange.connect(self._docChange)
# Document Title
@@ -192,14 +192,13 @@ class GuiDocEditor(QTextEdit):
self.setPalette(docPalette)
# Set default text margins
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
self.qDocument.setDocumentMargin(self.mainConf.getTextMargin())
# Also set the document text options for the document text flow
theOpt = QTextOption()
if self.mainConf.tabWidth is not None:
if self.mainConf.verQtValue >= 51000:
theOpt.setTabStopDistance(self.mainConf.tabWidth)
if self.mainConf.verQtValue >= 51000:
theOpt.setTabStopDistance(self.mainConf.getTabWidth())
if self.mainConf.doJustify:
theOpt.setAlignment(Qt.AlignJustify)
if self.mainConf.showTabsNSpaces:
@@ -319,6 +318,7 @@ class GuiDocEditor(QTextEdit):
Config.textFixedW is enabled or we're in Zen mode. Otherwise,
just ensure the margins are set correctly.
"""
cM = self.mainConf.getTextMargin()
if self.mainConf.textFixedW or self.theParent.isZenMode:
vBar = self.verticalScrollBar()
if vBar.isVisible():
@@ -326,20 +326,20 @@ class GuiDocEditor(QTextEdit):
else:
sW = 0
if self.theParent.isZenMode:
tW = self.mainConf.zenWidth
tW = self.mainConf.getZenWidth()
else:
tW = self.mainConf.textWidth
tW = self.mainConf.getTextWidth()
wW = self.width()
tM = int((wW - sW - tW)/2)
if tM < self.mainConf.textMargin:
tM = self.mainConf.textMargin
if tM < cM:
tM = cM
else:
tM = self.mainConf.textMargin
tM = cM
tB = self.lineWidth()
tW = self.width() - 2*tB
tH = self.docTitle.height()
tT = self.mainConf.textMargin - tH
tT = cM - tH
self.docTitle.setGeometry(tB, tB, tW, tH)
self.setViewportMargins(0, tH, 0, 0)
+2 -2
View File
@@ -105,7 +105,7 @@ class GuiDocViewer(QTextBrowser):
docPalette.setColor(QPalette.Text, QColor(*self.theTheme.colText))
self.setPalette(docPalette)
self.qDocument.setDocumentMargin(self.mainConf.textMargin)
self.qDocument.setDocumentMargin(self.mainConf.getTextMargin())
theOpt = QTextOption()
if self.mainConf.doJustify:
theOpt.setAlignment(Qt.AlignJustify)
@@ -216,7 +216,7 @@ class GuiDocViewer(QTextBrowser):
tB = self.lineWidth()
tW = self.width() - 2*tB
tH = self.docTitle.height()
tT = self.mainConf.textMargin - tH
tT = self.mainConf.getTextMargin() - tH
self.docTitle.setGeometry(tB, tB, tW, tH)
self.setViewportMargins(0, tH, 0, 0)
+3 -3
View File
@@ -271,7 +271,7 @@ class GuiOutline(QTreeWidget):
tmpWidth = self.optState.getValue("GuiOutline", "columnWidth", {})
for hName in tmpWidth:
try:
self.colWidth[nwOutline[hName]] = tmpWidth[hName]
self.colWidth[nwOutline[hName]] = self.mainConf.pxInt(tmpWidth[hName])
except:
logger.warning("Ignored unknown outline column '%s'" % str(hName))
@@ -301,7 +301,7 @@ class GuiOutline(QTreeWidget):
colHidden = {}
for hItem in nwOutline:
colWidth[hItem.name] = self.colWidth[hItem]
colWidth[hItem.name] = self.mainConf.rpxInt(self.colWidth[hItem])
colHidden[hItem.name] = self.colHidden[hItem]
for iCol in range(self.columnCount()):
@@ -309,7 +309,7 @@ class GuiOutline(QTreeWidget):
treeOrder.append(hName)
iLog = self.treeHead.logicalIndex(iCol)
logWidth = self.columnWidth(iLog)
logWidth = self.mainConf.rpxInt(self.columnWidth(iLog))
logHidden = self.isColumnHidden(iLog)
colHidden[hName] = logHidden
+2 -1
View File
@@ -270,8 +270,9 @@ class GuiProjectLoad(QDialog):
newItem.setSelected(True)
hasSelection = True
projColWidth = self.mainConf.getProjColWidths()
for i in range(3):
self.listBox.setColumnWidth(i, self.mainConf.projColWidth[i])
self.listBox.setColumnWidth(i, projColWidth[i])
return
+3 -2
View File
@@ -112,8 +112,9 @@ class GuiProjectTree(QTreeWidget):
# self.setSelectionBehavior(QAbstractItemView.SelectRows)
# Get user's column width preferences for NAME and COUNT
if len(self.mainConf.treeColWidth) <= 4:
for colN, colW in enumerate(self.mainConf.treeColWidth):
treeColWidth = self.mainConf.getTreeColWidths()
if len(treeColWidth) <= 4:
for colN, colW in enumerate(treeColWidth):
self.setColumnWidth(colN, colW)
# The last column should just auto-scale
+15 -15
View File
@@ -64,16 +64,16 @@ class GuiSessionLogView(QDialog):
self.setMinimumWidth(self.mainConf.pxInt(420))
self.setMinimumHeight(self.mainConf.pxInt(400))
widthCol0 = self.optState.getInt("GuiSession", "widthCol0", self.mainConf.pxInt(180))
widthCol1 = self.optState.getInt("GuiSession", "widthCol1", self.mainConf.pxInt(80))
widthCol2 = self.optState.getInt("GuiSession", "widthCol2", self.mainConf.pxInt(80))
wCol0 = self.mainConf.pxInt(self.optState.getInt("GuiSession", "widthCol0", 180))
wCol1 = self.mainConf.pxInt(self.optState.getInt("GuiSession", "widthCol1", 80))
wCol2 = self.mainConf.pxInt(self.optState.getInt("GuiSession", "widthCol2", 80))
self.listBox = QTreeWidget()
self.listBox.setHeaderLabels(["Session Start","Length","Words",""])
self.listBox.setIndentation(0)
self.listBox.setColumnWidth(0, widthCol0)
self.listBox.setColumnWidth(1, widthCol1)
self.listBox.setColumnWidth(2, widthCol2)
self.listBox.setColumnWidth(0, wCol0)
self.listBox.setColumnWidth(1, wCol1)
self.listBox.setColumnWidth(2, wCol2)
self.listBox.setColumnWidth(3, 0)
hHeader = self.listBox.headerItem()
@@ -220,20 +220,20 @@ class GuiSessionLogView(QDialog):
def _doClose(self):
widthCol0 = self.listBox.columnWidth(0)
widthCol1 = self.listBox.columnWidth(1)
widthCol2 = self.listBox.columnWidth(2)
widthCol0 = self.mainConf.rpxInt(self.listBox.columnWidth(0))
widthCol1 = self.mainConf.rpxInt(self.listBox.columnWidth(1))
widthCol2 = self.mainConf.rpxInt(self.listBox.columnWidth(2))
sortCol = self.listBox.sortColumn()
sortOrder = self.listBox.header().sortIndicatorOrder()
hideZeros = self.hideZeros.isChecked()
hideNegative = self.hideNegative.isChecked()
self.optState.setValue("GuiSession", "widthCol0", widthCol0)
self.optState.setValue("GuiSession", "widthCol1", widthCol1)
self.optState.setValue("GuiSession", "widthCol2", widthCol2)
self.optState.setValue("GuiSession", "sortCol", sortCol)
self.optState.setValue("GuiSession", "sortOrder", sortOrder)
self.optState.setValue("GuiSession", "hideZeros", hideZeros)
self.optState.setValue("GuiSession", "widthCol0", widthCol0)
self.optState.setValue("GuiSession", "widthCol1", widthCol1)
self.optState.setValue("GuiSession", "widthCol2", widthCol2)
self.optState.setValue("GuiSession", "sortCol", sortCol)
self.optState.setValue("GuiSession", "sortOrder", sortOrder)
self.optState.setValue("GuiSession", "hideZeros", hideZeros)
self.optState.setValue("GuiSession", "hideNegative", hideNegative)
self.optState.saveSettings()
+3 -3
View File
@@ -81,7 +81,7 @@ class GuiMain(QMainWindow):
self.isZenMode = False
# Prepare main window
self.resize(*self.mainConf.winGeometry)
self.resize(*self.mainConf.getWinSize())
self._setWindowTitle()
self.setWindowIcon(QIcon(self.mainConf.appIcon))
@@ -139,7 +139,7 @@ class GuiMain(QMainWindow):
self.splitOutline = QSplitter(Qt.Vertical)
self.splitOutline.addWidget(self.projView)
self.splitOutline.addWidget(self.projMeta)
self.splitOutline.setSizes(self.mainConf.outlnPanePos)
self.splitOutline.setSizes(self.mainConf.getOutlinePanePos())
self.tabWidget = QTabWidget()
self.tabWidget.setTabPosition(QTabWidget.East)
@@ -154,7 +154,7 @@ class GuiMain(QMainWindow):
self.splitMain.setOpaqueResize(False)
self.splitMain.addWidget(self.treePane)
self.splitMain.addWidget(self.tabWidget)
self.splitMain.setSizes(self.mainConf.mainPanePos)
self.splitMain.setSizes(self.mainConf.getMainPanePos())
self.setCentralWidget(self.splitMain)