diff --git a/nw/assets/icons/fallback/check-dark.svg b/nw/assets/icons/fallback/check-dark.svg new file mode 100644 index 00000000..86e45c5d --- /dev/null +++ b/nw/assets/icons/fallback/check-dark.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/nw/assets/icons/fallback/check.svg b/nw/assets/icons/fallback/check.svg new file mode 100644 index 00000000..f815ea12 --- /dev/null +++ b/nw/assets/icons/fallback/check.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/nw/assets/icons/fallback/cross-dark.svg b/nw/assets/icons/fallback/cross-dark.svg new file mode 100644 index 00000000..64410dfb --- /dev/null +++ b/nw/assets/icons/fallback/cross-dark.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/nw/assets/icons/fallback/cross.svg b/nw/assets/icons/fallback/cross.svg new file mode 100644 index 00000000..ff91c26a --- /dev/null +++ b/nw/assets/icons/fallback/cross.svg @@ -0,0 +1,55 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/nw/assets/icons/typicons_colour_dark/icons.conf b/nw/assets/icons/typicons_colour_dark/icons.conf index db622835..f3c96935 100644 --- a/nw/assets/icons/typicons_colour_dark/icons.conf +++ b/nw/assets/icons/typicons_colour_dark/icons.conf @@ -37,3 +37,5 @@ search-replace = search-replace.svg clear = backspace.svg save = download.svg edit = pencil.svg +check = tick.svg +cross = times.svg diff --git a/nw/assets/icons/typicons_colour_dark/tick.svg b/nw/assets/icons/typicons_colour_dark/tick.svg new file mode 100644 index 00000000..ced8362e --- /dev/null +++ b/nw/assets/icons/typicons_colour_dark/tick.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/nw/assets/icons/typicons_colour_light/icons.conf b/nw/assets/icons/typicons_colour_light/icons.conf index 9ee1d84a..d3df7d01 100644 --- a/nw/assets/icons/typicons_colour_light/icons.conf +++ b/nw/assets/icons/typicons_colour_light/icons.conf @@ -37,3 +37,5 @@ search-replace = search-replace.svg clear = backspace.svg save = download.svg edit = pencil.svg +check = tick.svg +cross = times.svg diff --git a/nw/assets/icons/typicons_colour_light/tick.svg b/nw/assets/icons/typicons_colour_light/tick.svg new file mode 100644 index 00000000..82ced41d --- /dev/null +++ b/nw/assets/icons/typicons_colour_light/tick.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/nw/assets/icons/typicons_grey_dark/icons.conf b/nw/assets/icons/typicons_grey_dark/icons.conf index 3753f2d2..75268e23 100644 --- a/nw/assets/icons/typicons_grey_dark/icons.conf +++ b/nw/assets/icons/typicons_grey_dark/icons.conf @@ -36,3 +36,5 @@ search-replace = search-replace.svg clear = backspace.svg save = download.svg edit = pencil.svg +check = tick.svg +cross = times.svg diff --git a/nw/assets/icons/typicons_grey_dark/tick.svg b/nw/assets/icons/typicons_grey_dark/tick.svg new file mode 100644 index 00000000..86e45c5d --- /dev/null +++ b/nw/assets/icons/typicons_grey_dark/tick.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/nw/assets/icons/typicons_grey_light/icons.conf b/nw/assets/icons/typicons_grey_light/icons.conf index 1479df9e..766aed98 100644 --- a/nw/assets/icons/typicons_grey_light/icons.conf +++ b/nw/assets/icons/typicons_grey_light/icons.conf @@ -36,3 +36,5 @@ search-replace = search-replace.svg clear = backspace.svg save = download.svg edit = pencil.svg +check = tick.svg +cross = times.svg diff --git a/nw/assets/icons/typicons_grey_light/tick.svg b/nw/assets/icons/typicons_grey_light/tick.svg new file mode 100644 index 00000000..f815ea12 --- /dev/null +++ b/nw/assets/icons/typicons_grey_light/tick.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/nw/gui/elements/docdetails.py b/nw/gui/elements/docdetails.py index e72f6486..84418802 100644 --- a/nw/gui/elements/docdetails.py +++ b/nw/gui/elements/docdetails.py @@ -29,7 +29,7 @@ import logging import nw from PyQt5.QtCore import Qt -from PyQt5.QtGui import QFont +from PyQt5.QtGui import QFont, QIcon, QPixmap, QFontMetrics from PyQt5.QtWidgets import QFrame, QGridLayout, QLabel from nw.constants import ( @@ -47,30 +47,37 @@ class GuiDocDetails(QFrame): self.mainConf = nw.CONFIG self.theParent = theParent self.theProject = theProject + self.theTheme = theParent.theTheme self.mainBox = QGridLayout(self) self.mainBox.setVerticalSpacing(1) self.mainBox.setHorizontalSpacing(6) self.setLayout(self.mainBox) + self.pS = 0.9*self.theTheme.fontPointSize + self.iPx = self.theTheme.textIconSize + self.sPx = int(round(0.8*self.theTheme.textIconSize)) + + self.expCheck = self.theTheme.getPixmap("check", (self.iPx, self.iPx)) + self.expCross = self.theTheme.getPixmap("cross", (self.iPx, self.iPx)) + self.fntLabel = QFont() - self.fntLabel.setPointSize(10) self.fntLabel.setBold(True) + self.fntLabel.setPointSizeF(self.pS) self.fntFixed = QFont() self.fntFixed.setFamily("Monospace") - self.fntFixed.setPointSize(10) + self.fntFixed.setPointSizeF(self.pS) self.fntValue = QFont() - self.fntValue.setPointSize(10) + self.fntValue.setPointSizeF(self.pS) # Label - self.labelName = QLabel("Label ") + self.labelName = QLabel("Label") self.labelName.setFont(self.fntLabel) self.labelName.setAlignment(Qt.AlignLeft | Qt.AlignBaseline) self.labelFlag = QLabel("") - self.labelFlag.setFont(self.fntFixed) self.labelFlag.setAlignment(Qt.AlignRight | Qt.AlignBaseline) self.labelData = QLabel("") @@ -79,12 +86,11 @@ class GuiDocDetails(QFrame): self.labelData.setWordWrap(True) # Status - self.statusName = QLabel("Status ") + self.statusName = QLabel("Status") self.statusName.setFont(self.fntLabel) self.statusName.setAlignment(Qt.AlignLeft) self.statusFlag = QLabel("") - self.statusFlag.setFont(self.fntFixed) self.statusFlag.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.statusData = QLabel("") @@ -92,7 +98,7 @@ class GuiDocDetails(QFrame): self.statusData.setAlignment(Qt.AlignLeft) # Class - self.className = QLabel("Class ") + self.className = QLabel("Class") self.className.setFont(self.fntLabel) self.className.setAlignment(Qt.AlignLeft) @@ -105,7 +111,7 @@ class GuiDocDetails(QFrame): self.classData.setAlignment(Qt.AlignLeft) # Layout - self.layoutName = QLabel("Layout ") + self.layoutName = QLabel("Layout") self.layoutName.setFont(self.fntLabel) self.layoutName.setAlignment(Qt.AlignLeft) @@ -173,6 +179,12 @@ class GuiDocDetails(QFrame): self.mainBox.setColumnStretch(3,0) self.mainBox.setColumnStretch(4,0) + # Make sure the columns for flags and counts don't resize too often + flagWidth = QFontMetrics(self.fntFixed).boundingRect("Mm").width() + countWidth = QFontMetrics(self.fntValue).boundingRect("99,999").width() + self.mainBox.setColumnMinimumWidth(1, flagWidth) + self.mainBox.setColumnMinimumWidth(4, countWidth) + logger.debug("DocDetails initialisation complete") return @@ -214,14 +226,12 @@ class GuiDocDetails(QFrame): if nwItem.itemType == nwItemType.FILE: if nwItem.isExported: - exportFlag = nwUnicode.U_CHECK + self.labelFlag.setPixmap(self.expCheck) else: - exportFlag = " " + self.labelFlag.setPixmap(self.expCross) else: - exportFlag = "-" - - self.labelFlag.setText(exportFlag) - self.statusFlag.setPixmap(flagIcon.pixmap(10, 10)) + self.labelFlag.setPixmap(QPixmap(1,1)) + self.statusFlag.setPixmap(flagIcon.pixmap(self.sPx, self.sPx)) self.classFlag.setText(nwLabels.CLASS_FLAG[nwItem.itemClass]) if nwItem.itemLayout == nwItemLayout.NO_LAYOUT: self.layoutFlag.setText("-") diff --git a/nw/gui/elements/doctitlebar.py b/nw/gui/elements/doctitlebar.py index 38425961..8c5208e4 100644 --- a/nw/gui/elements/doctitlebar.py +++ b/nw/gui/elements/doctitlebar.py @@ -52,19 +52,20 @@ class GuiDocTitleBar(QLabel): self.setText("") self.setIndent(0) self.setMargin(0) - self.setContentsMargins(0,0,0,0) + self.setContentsMargins(0, 0, 0, 0) self.setAutoFillBackground(True) self.setAlignment(Qt.AlignCenter) self.setWordWrap(True) self.setFrameShape(QFrame.NoFrame) self.setLineWidth(0) + lblPalette = self.palette() lblPalette.setColor(QPalette.Window, QColor(*self.theTheme.colBack)) lblPalette.setColor(QPalette.Text, QColor(*self.theTheme.colText)) self.setPalette(lblPalette) lblFont = self.font() - lblFont.setPointSizeF(0.9*self.theTheme.defFontSize) + lblFont.setPointSizeF(0.9*self.theTheme.fontPointSize) self.setFont(lblFont) logger.debug("DocTitleBar initialisation complete") diff --git a/nw/gui/elements/doctree.py b/nw/gui/elements/doctree.py index 6da9e5d7..5fbfc83d 100644 --- a/nw/gui/elements/doctree.py +++ b/nw/gui/elements/doctree.py @@ -29,7 +29,7 @@ import logging import nw from PyQt5.QtCore import Qt, QSize -from PyQt5.QtGui import QFont, QColor +from PyQt5.QtGui import QFont, QColor, QIcon from PyQt5.QtWidgets import ( qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMessageBox ) @@ -45,8 +45,9 @@ class GuiDocTree(QTreeWidget): C_NAME = 0 C_COUNT = 1 - C_FLAGS = 2 - C_HANDLE = 3 + C_EXPORT = 2 + C_FLAGS = 3 + C_HANDLE = 4 def __init__(self, theParent, theProject): QTreeWidget.__init__(self, theParent) @@ -64,15 +65,20 @@ class GuiDocTree(QTreeWidget): self.clearTree() # Build GUI - self.setIconSize(QSize(13,13)) + iPx = self.theTheme.textIconSize + self.setIconSize(QSize(iPx, iPx)) self.setExpandsOnDoubleClick(True) - self.setIndentation(13) - self.setColumnCount(4) - self.setHeaderLabels(["Label","Words","Flags","Handle"]) + self.setIndentation(iPx) + self.setColumnCount(5) + self.setHeaderLabels(["Label", "Words", "Inc", "Flags", "Handle"]) self.hideColumn(self.C_HANDLE) treeHead = self.headerItem() - treeHead.setTextAlignment(self.C_COUNT,Qt.AlignRight) + treeHead.setTextAlignment(self.C_COUNT, Qt.AlignRight) + treeHead.setToolTip(self.C_NAME, "Item label") + treeHead.setToolTip(self.C_COUNT, "Word count") + treeHead.setToolTip(self.C_EXPORT, "Include in build") + treeHead.setToolTip(self.C_FLAGS, "Status, class, and layout flags") # Allow Move by Drag & Drop self.setDragEnabled(True) @@ -87,11 +93,15 @@ class GuiDocTree(QTreeWidget): # self.setSelectionMode(QAbstractItemView.ExtendedSelection) # self.setSelectionBehavior(QAbstractItemView.SelectRows) - for colN in range(len(self.mainConf.treeColWidth)): - self.setColumnWidth(colN,self.mainConf.treeColWidth[colN]) + for colN, colW in enumerate(self.mainConf.treeColWidth): + self.setColumnWidth(colN, colW) - self.fontFlags = QFont("Monospace",10) - self.fontCount = QFont("Monospace",10) + self.resizeColumnToContents(self.C_EXPORT) + self.resizeColumnToContents(self.C_FLAGS) + + self.fntFixed = QFont() + self.fntFixed.setFamily("Monospace") + self.fntFixed.setPointSizeF(0.9*self.theTheme.fontPointSize) logger.debug("DocTree initialisation complete") @@ -271,7 +281,6 @@ class GuiDocTree(QTreeWidget): retVals = [ self.columnWidth(0), self.columnWidth(1), - self.columnWidth(2), ] return retVals @@ -422,30 +431,30 @@ class GuiDocTree(QTreeWidget): tHandle = nwItem.itemHandle pHandle = nwItem.parHandle - stExport = " " - stClass = nwLabels.CLASS_FLAG[nwItem.itemClass] - stLayout = "" + expIcon = QIcon() + stClass = nwLabels.CLASS_FLAG[nwItem.itemClass] + stLayout = "" if nwItem.itemType == nwItemType.FILE: stLayout = "."+nwLabels.LAYOUT_FLAG[nwItem.itemLayout] if nwItem.isExported: - stExport = nwUnicode.U_CHECK - else: - stExport = "-" - - tStatus = stExport+" "+stClass+stLayout + expIcon = self.theTheme.getIcon("check") + else: + expIcon = self.theTheme.getIcon("cross") + tStatus = stClass+stLayout iStatus = nwItem.itemStatus if tClass == nwItemClass.NOVEL: - iStatus = self.theProject.statusItems.checkEntry(iStatus) # Make sure it's valid + iStatus = self.theProject.statusItems.checkEntry(iStatus) # Make sure it's valid flagIcon = self.theParent.statusIcons[iStatus] else: - iStatus = self.theProject.importItems.checkEntry(iStatus) # Make sure it's valid + iStatus = self.theProject.importItems.checkEntry(iStatus) # Make sure it's valid flagIcon = self.theParent.importIcons[iStatus] trItem.setText(self.C_NAME, tName) - trItem.setText(self.C_FLAGS,tStatus) - trItem.setIcon(self.C_FLAGS,flagIcon) + trItem.setIcon(self.C_EXPORT, expIcon) + trItem.setText(self.C_FLAGS, tStatus) + trItem.setIcon(self.C_FLAGS, flagIcon) return @@ -569,12 +578,14 @@ class GuiDocTree(QTreeWidget): newItem.setText(self.C_NAME, "") newItem.setText(self.C_COUNT, "0") + newItem.setText(self.C_EXPORT, "") newItem.setText(self.C_FLAGS, "") newItem.setText(self.C_HANDLE, tHandle) # newItem.setForeground(self.C_COUNT,QColor(*self.theParent.theTheme.treeWCount)) newItem.setTextAlignment(self.C_COUNT, Qt.AlignRight) - newItem.setFont(self.C_FLAGS, self.fontFlags) + # newItem.setTextAlignment(self.C_EXPORT, Qt.AlignHCenter) + newItem.setFont(self.C_FLAGS, self.fntFixed) self.theMap[tHandle] = newItem if pHandle is None: @@ -627,6 +638,7 @@ class GuiDocTree(QTreeWidget): newItem = QTreeWidgetItem([""]*4) newItem.setText(self.C_NAME, "Orphaned Files") newItem.setText(self.C_COUNT, "") + newItem.setText(self.C_EXPORT, "") newItem.setText(self.C_FLAGS, "") newItem.setText(self.C_HANDLE, "") self.addTopLevelItem(newItem) diff --git a/nw/gui/icons.py b/nw/gui/icons.py index db5d6e9e..f1a33145 100644 --- a/nw/gui/icons.py +++ b/nw/gui/icons.py @@ -93,6 +93,8 @@ class GuiIcons: "clear" : (QStyle.SP_LineEditClearButton, "clear_left"), "save" : (QStyle.SP_DialogSaveButton, "document-save"), "edit" : (None, None), + "check" : (None, None), + "cross" : (None, None), ## Other Icons "warning" : (QStyle.SP_MessageBoxWarning, "dialog-warning"), diff --git a/nw/gui/statusbar.py b/nw/gui/statusbar.py index d268ab74..5fc4c873 100644 --- a/nw/gui/statusbar.py +++ b/nw/gui/statusbar.py @@ -48,6 +48,7 @@ class GuiMainStatus(QStatusBar): self.mainConf = nw.CONFIG self.theParent = theParent + self.theTheme = theParent.theTheme self.refTime = None self.charCount = 0 @@ -56,11 +57,15 @@ class GuiMainStatus(QStatusBar): self.projWords = 0 self.sessWords = 0 - self.monoFont = QFont("Monospace",10) + self.fntFixed = QFont() + self.fntFixed.setFamily("Monospace") + self.fntFixed.setPointSizeF(0.95*self.theTheme.fontPointSize) - colNone = QColor(*self.theParent.theTheme.statNone) - colTrue = QColor(*self.theParent.theTheme.statUnsaved) - colFalse = QColor(*self.theParent.theTheme.statSaved) + colNone = QColor(*self.theTheme.statNone) + colTrue = QColor(*self.theTheme.statUnsaved) + colFalse = QColor(*self.theTheme.statSaved) + + iPx = self.theTheme.textIconSize # Permanent Widgets # ================= @@ -68,14 +73,14 @@ class GuiMainStatus(QStatusBar): ## The Spell Checker Language self.langIcon = QLabel("") self.langText = QLabel("None") - self.langIcon.setPixmap(self.theParent.theTheme.getPixmap("status_lang",(14,14))) + self.langIcon.setPixmap(self.theTheme.getPixmap("status_lang", (iPx, iPx))) self.langIcon.setContentsMargins(0, 0, 0, 0) self.langText.setContentsMargins(0, 0, 8, 0) self.addPermanentWidget(self.langIcon) self.addPermanentWidget(self.langText) ## The Editor Status - self.docIcon = StatusLED(colNone, colTrue, colFalse, 14, 14, self) + self.docIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self) self.docText = QLabel("Editor") self.docIcon.setContentsMargins(0, 0, 0, 0) self.docText.setContentsMargins(0, 0, 8, 0) @@ -83,7 +88,7 @@ class GuiMainStatus(QStatusBar): self.addPermanentWidget(self.docText) ## The Project Status - self.projIcon = StatusLED(colNone, colTrue, colFalse, 14, 14, self) + self.projIcon = StatusLED(colNone, colTrue, colFalse, iPx, iPx, self) self.projText = QLabel("Project") self.projIcon.setContentsMargins(0, 0, 0, 0) self.projText.setContentsMargins(0, 0, 8, 0) @@ -93,7 +98,7 @@ class GuiMainStatus(QStatusBar): ## The Project and Session Stats self.statsIcon = QLabel() self.statsText = QLabel("") - self.statsIcon.setPixmap(self.theParent.theTheme.getPixmap("status_stats",(14,14))) + self.statsIcon.setPixmap(self.theTheme.getPixmap("status_stats", (iPx, iPx))) self.statsIcon.setContentsMargins(0, 0, 0, 0) self.statsText.setContentsMargins(0, 0, 8, 0) self.addPermanentWidget(self.statsIcon) @@ -102,10 +107,10 @@ class GuiMainStatus(QStatusBar): ## The Session Clock self.timeIcon = QLabel() self.timeText = QLabel("") - self.timeIcon.setPixmap(self.theParent.theTheme.getPixmap("status_time",(14,14))) + self.timeIcon.setPixmap(self.theTheme.getPixmap("status_time", (iPx, iPx))) self.timeText.setToolTip("Session Time") self.timeText.setAlignment(Qt.AlignVCenter | Qt.AlignRight) - self.timeText.setFont(self.monoFont) + self.timeText.setFont(self.fntFixed) self.timeIcon.setContentsMargins(0, 0, 0, 0) self.timeText.setContentsMargins(0, 0, 0, 0) self.addPermanentWidget(self.timeIcon) diff --git a/nw/gui/theme.py b/nw/gui/theme.py index 04a00c0e..cf29e4b0 100644 --- a/nw/gui/theme.py +++ b/nw/gui/theme.py @@ -32,7 +32,7 @@ import nw from os import path, listdir from PyQt5.QtWidgets import qApp -from PyQt5.QtGui import QPalette, QColor, QIcon +from PyQt5.QtGui import QPalette, QColor, QIcon, QFontMetrics from nw.constants import nwAlert from nw.gui.icons import GuiIcons @@ -119,8 +119,20 @@ class GuiTheme: self.loadDecoration = self.theIcons.loadDecoration # Extract Other Info - self.defFont = qApp.font() - self.defFontSize = self.defFont.pointSizeF() + self.guiDPI = qApp.primaryScreen().physicalDotsPerInch() + self.guiFont = qApp.font() + + qMetric = QFontMetrics(self.guiFont) + self.fontPointSize = self.guiFont.pointSizeF() + self.fontPixelSize = int(round(qMetric.height())) + self.baseIconSize = int(round(qMetric.ascent())) + self.textIconSize = int(round(qMetric.ascent() + qMetric.leading())) + + logger.verbose("GUI Font Family: %s" % self.guiFont.family()) + logger.verbose("GUI Font Point Size: %.2f" % self.fontPointSize) + logger.verbose("GUI Font Pixel Size: %d" % self.fontPixelSize) + logger.verbose("GUI Base Icon Size: %d" % self.baseIconSize) + logger.verbose("GUI Text Icon Size: %d" % self.textIconSize) return