Add a separate class to handle icons
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Main Window Elements
|
# Main Window Elements
|
||||||
|
from nw.gui.icons import GuiIcons
|
||||||
from nw.gui.mainmenu import GuiMainMenu
|
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
|
||||||
@@ -27,6 +28,7 @@ from nw.gui.tools.dochighlight import GuiDocHighlighter
|
|||||||
from nw.gui.tools.wordcounter import WordCounter
|
from nw.gui.tools.wordcounter import WordCounter
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"GuiIcons",
|
||||||
"GuiMainMenu",
|
"GuiMainMenu",
|
||||||
"GuiMainStatus",
|
"GuiMainStatus",
|
||||||
"GuiTheme",
|
"GuiTheme",
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import nw
|
|||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtSvg import QSvgWidget
|
|
||||||
from PyQt5.QtGui import (
|
from PyQt5.QtGui import (
|
||||||
QIcon, QPixmap, QColor, QBrush, QStandardItemModel, QFont
|
QIcon, QPixmap, QColor, QBrush, QStandardItemModel, QFont
|
||||||
)
|
)
|
||||||
@@ -46,10 +45,7 @@ class GuiConfigEditor(QDialog):
|
|||||||
self.innerBox = QVBoxLayout()
|
self.innerBox = QVBoxLayout()
|
||||||
|
|
||||||
self.setWindowTitle("Preferences")
|
self.setWindowTitle("Preferences")
|
||||||
|
self.guiDeco = self.theParent.theTheme.loadDecoration("settings",(64,64))
|
||||||
self.gradPath = path.abspath(path.join(self.mainConf.graphPath,"gear.svg"))
|
|
||||||
self.svgGradient = QSvgWidget(path.join(self.gradPath))
|
|
||||||
self.svgGradient.setFixedSize(QSize(64,64))
|
|
||||||
|
|
||||||
self.theProject.countStatus()
|
self.theProject.countStatus()
|
||||||
self.tabMain = GuiConfigEditGeneral(self.theParent)
|
self.tabMain = GuiConfigEditGeneral(self.theParent)
|
||||||
@@ -60,7 +56,7 @@ class GuiConfigEditor(QDialog):
|
|||||||
self.tabWidget.addTab(self.tabEditor, "Editor")
|
self.tabWidget.addTab(self.tabEditor, "Editor")
|
||||||
|
|
||||||
self.setLayout(self.outerBox)
|
self.setLayout(self.outerBox)
|
||||||
self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop)
|
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
|
||||||
self.outerBox.addLayout(self.innerBox)
|
self.outerBox.addLayout(self.innerBox)
|
||||||
|
|
||||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||||
|
|||||||
@@ -16,8 +16,7 @@ import nw
|
|||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtSvg import QSvgWidget
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialog, QHBoxLayout, QVBoxLayout, QWidget, QTabWidget, QGridLayout,
|
QDialog, QHBoxLayout, QVBoxLayout, QWidget, QTabWidget, QGridLayout,
|
||||||
QGroupBox, QCheckBox, QLabel, QComboBox, QLineEdit, QPushButton,
|
QGroupBox, QCheckBox, QLabel, QComboBox, QLineEdit, QPushButton,
|
||||||
@@ -50,9 +49,7 @@ class GuiExport(QDialog):
|
|||||||
self.setWindowTitle("Export Project")
|
self.setWindowTitle("Export Project")
|
||||||
self.setLayout(self.outerBox)
|
self.setLayout(self.outerBox)
|
||||||
|
|
||||||
self.gradPath = path.abspath(path.join(self.mainConf.graphPath,"export.svg"))
|
self.guiDeco = self.theParent.theTheme.loadDecoration("export",(64,64))
|
||||||
self.svgGradient = QSvgWidget(self.gradPath)
|
|
||||||
self.svgGradient.setFixedSize(QSize(64,64))
|
|
||||||
|
|
||||||
self.theProject.countStatus()
|
self.theProject.countStatus()
|
||||||
self.tabMain = GuiExportMain(self.theParent, self.theProject, self.optState)
|
self.tabMain = GuiExportMain(self.theParent, self.theProject, self.optState)
|
||||||
@@ -62,7 +59,7 @@ class GuiExport(QDialog):
|
|||||||
self.tabWidget.addTab(self.tabMain, "Settings")
|
self.tabWidget.addTab(self.tabMain, "Settings")
|
||||||
self.tabWidget.addTab(self.tabPandoc, "Pandoc")
|
self.tabWidget.addTab(self.tabPandoc, "Pandoc")
|
||||||
|
|
||||||
self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop)
|
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
|
||||||
self.outerBox.addLayout(self.innerBox)
|
self.outerBox.addLayout(self.innerBox)
|
||||||
|
|
||||||
self.doExportForm = QGridLayout()
|
self.doExportForm = QGridLayout()
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ import nw
|
|||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtSvg import QSvgWidget
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout,
|
QDialog, QHBoxLayout, QVBoxLayout, QGroupBox, QFormLayout,
|
||||||
QLineEdit, QPushButton, QComboBox
|
QLineEdit, QPushButton, QComboBox
|
||||||
@@ -42,13 +41,10 @@ class GuiItemEditor(QDialog):
|
|||||||
self.innerBox = QVBoxLayout()
|
self.innerBox = QVBoxLayout()
|
||||||
|
|
||||||
self.setWindowTitle("Item Settings")
|
self.setWindowTitle("Item Settings")
|
||||||
|
self.guiDeco = self.theParent.theTheme.loadDecoration("settings",(64,64))
|
||||||
self.gradPath = path.abspath(path.join(self.mainConf.graphPath,"gear.svg"))
|
|
||||||
self.svgGradient = QSvgWidget(self.gradPath)
|
|
||||||
self.svgGradient.setFixedSize(QSize(64,64))
|
|
||||||
|
|
||||||
self.setLayout(self.outerBox)
|
self.setLayout(self.outerBox)
|
||||||
self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop)
|
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
|
||||||
self.outerBox.addLayout(self.innerBox)
|
self.outerBox.addLayout(self.innerBox)
|
||||||
|
|
||||||
self.mainGroup = QGroupBox("Item Settings")
|
self.mainGroup = QGroupBox("Item Settings")
|
||||||
|
|||||||
@@ -15,9 +15,8 @@ import nw
|
|||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush, QStandardItemModel
|
from PyQt5.QtGui import QIcon, QPixmap, QColor, QBrush
|
||||||
from PyQt5.QtSvg import QSvgWidget
|
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit,
|
QDialog, QHBoxLayout, QVBoxLayout, QFormLayout, QLineEdit, QPlainTextEdit,
|
||||||
QLabel, QWidget, QTabWidget, QDialogButtonBox, QListWidget,
|
QLabel, QWidget, QTabWidget, QDialogButtonBox, QListWidget,
|
||||||
@@ -45,9 +44,7 @@ class GuiProjectEditor(QDialog):
|
|||||||
self.setWindowTitle("Project Settings")
|
self.setWindowTitle("Project Settings")
|
||||||
self.setLayout(self.outerBox)
|
self.setLayout(self.outerBox)
|
||||||
|
|
||||||
self.gradPath = path.abspath(path.join(self.mainConf.graphPath,"gear.svg"))
|
self.guiDeco = self.theParent.theTheme.loadDecoration("settings",(64,64))
|
||||||
self.svgGradient = QSvgWidget(self.gradPath)
|
|
||||||
self.svgGradient.setFixedSize(QSize(64,64))
|
|
||||||
|
|
||||||
self.theProject.countStatus()
|
self.theProject.countStatus()
|
||||||
self.tabMain = GuiProjectEditMain(self.theParent, self.theProject)
|
self.tabMain = GuiProjectEditMain(self.theParent, self.theProject)
|
||||||
@@ -61,7 +58,7 @@ class GuiProjectEditor(QDialog):
|
|||||||
self.tabWidget.addTab(self.tabImport, "Importance")
|
self.tabWidget.addTab(self.tabImport, "Importance")
|
||||||
self.tabWidget.addTab(self.tabReplace,"Auto-Replace")
|
self.tabWidget.addTab(self.tabReplace,"Auto-Replace")
|
||||||
|
|
||||||
self.outerBox.addWidget(self.svgGradient, 0, Qt.AlignTop)
|
self.outerBox.addWidget(self.guiDeco, 0, Qt.AlignTop)
|
||||||
self.outerBox.addLayout(self.innerBox)
|
self.outerBox.addLayout(self.innerBox)
|
||||||
|
|
||||||
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||||
|
|||||||
+151
@@ -0,0 +1,151 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""novelWriter Icons Class
|
||||||
|
|
||||||
|
novelWriter – Icons Class
|
||||||
|
===========================
|
||||||
|
This class manages the GUI icons
|
||||||
|
|
||||||
|
File History:
|
||||||
|
Created: 2019-11-08 [0.4.0]
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import nw
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
from PyQt5.QtCore import QSize
|
||||||
|
from PyQt5.QtSvg import QSvgWidget
|
||||||
|
from PyQt5.QtGui import QIcon
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class GuiIcons:
|
||||||
|
|
||||||
|
# Icon keys should either be a .svg or .png file under the gui
|
||||||
|
# theme folder, or have a fallback that is either compatible with
|
||||||
|
# QIcon.fromTheme, as specified here:
|
||||||
|
# https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
|
||||||
|
# or, if there is no fallback, the variable should be None.
|
||||||
|
ICON_MAP = {
|
||||||
|
"root" : "drive-harddisk",
|
||||||
|
"folder" : "folder",
|
||||||
|
"document" : "x-office-document",
|
||||||
|
"trash" : "user-trash",
|
||||||
|
"orphan" : "dialog-warning",
|
||||||
|
"save" : "document-save",
|
||||||
|
"add" : "list-add",
|
||||||
|
"remove" : "list-remove",
|
||||||
|
"close" : "edit-delete",
|
||||||
|
"search" : "edit-find",
|
||||||
|
"replace" : "edit-find-replace",
|
||||||
|
"time" : None,
|
||||||
|
}
|
||||||
|
|
||||||
|
DECO_MAP = {
|
||||||
|
"export" : "export.svg",
|
||||||
|
"settings" : "settings.svg",
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, theParent):
|
||||||
|
|
||||||
|
self.mainConf = nw.CONFIG
|
||||||
|
self.theParent = theParent
|
||||||
|
|
||||||
|
# Storage
|
||||||
|
self.qIcons = {}
|
||||||
|
|
||||||
|
# Look for files in
|
||||||
|
self.priPath = "" # The gui theme's icon folder
|
||||||
|
self.secPath = "" # The main assets icon folder
|
||||||
|
self.prefDark = False # Load dark icons, if available
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def initIcons(self, priPath):
|
||||||
|
|
||||||
|
self.priPath = priPath
|
||||||
|
self.secPath = self.mainConf.iconPath
|
||||||
|
self.prefDark = self.mainConf.guiDark
|
||||||
|
|
||||||
|
for iconKey in self.ICON_MAP.keys():
|
||||||
|
self.qIcons[iconKey] = self._loadIcon(iconKey)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def loadDecoration(self, decoKey, decoSize=None):
|
||||||
|
|
||||||
|
if decoKey not in self.DECO_MAP:
|
||||||
|
logger.error("Decoration with name '%s' does not exist" % decoKey)
|
||||||
|
return QSvgWidget()
|
||||||
|
|
||||||
|
svgPath = path.join(self.mainConf.graphPath, self.DECO_MAP[decoKey])
|
||||||
|
if not path.isfile(svgPath):
|
||||||
|
logger.error("Decoration file '%s' not in assets folder" % self.DECO_MAP[decoKey])
|
||||||
|
return QSvgWidget()
|
||||||
|
|
||||||
|
svgDeco = QSvgWidget(svgPath)
|
||||||
|
if decoSize is not None:
|
||||||
|
svgDeco.setFixedSize(QSize(decoSize[0],decoSize[1]))
|
||||||
|
|
||||||
|
return svgDeco
|
||||||
|
|
||||||
|
def getIcon(self, iconKey, iconSize=None):
|
||||||
|
if iconKey in self.qIcons:
|
||||||
|
return self.qIcons[iconKey]
|
||||||
|
return QIcon()
|
||||||
|
|
||||||
|
##
|
||||||
|
# Internal Functions
|
||||||
|
##
|
||||||
|
|
||||||
|
def _loadIcon(self, iconKey):
|
||||||
|
|
||||||
|
if iconKey not in self.ICON_MAP:
|
||||||
|
logger.error("Icon with name '%s' does not exist" % iconKey)
|
||||||
|
return QIcon()
|
||||||
|
|
||||||
|
if self.prefDark:
|
||||||
|
iconSuffix = "dark"
|
||||||
|
else:
|
||||||
|
iconSuffix = "light"
|
||||||
|
|
||||||
|
iconNames = []
|
||||||
|
iconNames.append("%s-%s.svg" % (iconKey, iconSuffix))
|
||||||
|
iconNames.append("%s-%s.png" % (iconKey, iconSuffix))
|
||||||
|
iconNames.append("%s.svg" % iconKey)
|
||||||
|
iconNames.append("%s.png" % iconKey)
|
||||||
|
|
||||||
|
# Check theme folder
|
||||||
|
loadFrom = None
|
||||||
|
for iconName in iconNames:
|
||||||
|
checkPath = path.join(self.priPath, iconName)
|
||||||
|
if path.isfile(checkPath):
|
||||||
|
loadFrom = checkPath
|
||||||
|
logger.verbose("Loading icon '%s' from theme" % iconName)
|
||||||
|
break
|
||||||
|
if loadFrom is not None:
|
||||||
|
return QIcon(loadFrom)
|
||||||
|
|
||||||
|
# Check assets folder
|
||||||
|
for iconName in iconNames:
|
||||||
|
checkPath = path.join(self.secPath, iconName)
|
||||||
|
if path.isfile(checkPath):
|
||||||
|
loadFrom = checkPath
|
||||||
|
logger.verbose("Loading icon '%s' from assets" % iconName)
|
||||||
|
break
|
||||||
|
if loadFrom is not None:
|
||||||
|
return QIcon(loadFrom)
|
||||||
|
|
||||||
|
# If we're still here, try to set from system theme
|
||||||
|
if self.ICON_MAP[iconKey] is not None:
|
||||||
|
logger.verbose("Loading icon '%s' from system theme" % iconKey)
|
||||||
|
return QIcon().fromTheme(self.ICON_MAP[iconKey])
|
||||||
|
|
||||||
|
# Give up and return an empty icomn
|
||||||
|
logger.warning("Did not load an icon for '%s'" % iconKey)
|
||||||
|
|
||||||
|
return QIcon()
|
||||||
|
|
||||||
|
# END Class GuiIcons
|
||||||
+6
-44
@@ -20,34 +20,17 @@ from PyQt5.QtWidgets import qApp
|
|||||||
from PyQt5.QtGui import QPalette, QColor, QIcon
|
from PyQt5.QtGui import QPalette, QColor, QIcon
|
||||||
|
|
||||||
from nw.constants import nwAlert
|
from nw.constants import nwAlert
|
||||||
|
from nw.gui.icons import GuiIcons
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class GuiTheme:
|
class GuiTheme:
|
||||||
|
|
||||||
# Icons should either have a valid icon name by using Qt internal
|
|
||||||
# QIcon.fromTheme, as specified here:
|
|
||||||
# https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html
|
|
||||||
# If there is no fallback, the variable should be None.
|
|
||||||
ICON_MAP = {
|
|
||||||
"root" : "drive-harddisk",
|
|
||||||
"folder" : "folder",
|
|
||||||
"document" : "x-office-document",
|
|
||||||
"trash" : "user-trash",
|
|
||||||
"orphan" : "dialog-warning",
|
|
||||||
"save" : "document-save",
|
|
||||||
"add" : "list-add",
|
|
||||||
"remove" : "list-remove",
|
|
||||||
"close" : "edit-delete",
|
|
||||||
"search" : "edit-find",
|
|
||||||
"replace" : "edit-find-replace",
|
|
||||||
"time" : None,
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, theParent):
|
def __init__(self, theParent):
|
||||||
|
|
||||||
self.mainConf = nw.CONFIG
|
self.mainConf = nw.CONFIG
|
||||||
self.theParent = theParent
|
self.theParent = theParent
|
||||||
|
self.theIcons = GuiIcons(self.theParent)
|
||||||
self.guiPalette = QPalette()
|
self.guiPalette = QPalette()
|
||||||
self.guiPath = "gui"
|
self.guiPath = "gui"
|
||||||
self.iconPath = "icons"
|
self.iconPath = "icons"
|
||||||
@@ -96,9 +79,6 @@ class GuiTheme:
|
|||||||
self.colTagErr = [ 0, 0, 0]
|
self.colTagErr = [ 0, 0, 0]
|
||||||
self.colRepTag = [ 0, 0, 0]
|
self.colRepTag = [ 0, 0, 0]
|
||||||
|
|
||||||
## Icons
|
|
||||||
self.themeIcons = {}
|
|
||||||
|
|
||||||
# Changeable Settings
|
# Changeable Settings
|
||||||
self.guiTheme = None
|
self.guiTheme = None
|
||||||
self.guiSyntax = None
|
self.guiSyntax = None
|
||||||
@@ -110,6 +90,9 @@ class GuiTheme:
|
|||||||
|
|
||||||
self.updateTheme()
|
self.updateTheme()
|
||||||
|
|
||||||
|
self.getIcon = self.theIcons.getIcon
|
||||||
|
self.loadDecoration = self.theIcons.loadDecoration
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -126,8 +109,7 @@ class GuiTheme:
|
|||||||
self.confFile = path.join(self.themePath,self.confName)
|
self.confFile = path.join(self.themePath,self.confName)
|
||||||
self.cssFile = path.join(self.themePath,self.cssName)
|
self.cssFile = path.join(self.themePath,self.cssName)
|
||||||
|
|
||||||
for iconName in self.ICON_MAP:
|
self.theIcons.initIcons(path.join(self.themePath,self.iconPath))
|
||||||
self.themeIcons[iconName] = QIcon.fromTheme(self.ICON_MAP[iconName])
|
|
||||||
|
|
||||||
self.loadTheme()
|
self.loadTheme()
|
||||||
self.loadSyntax()
|
self.loadSyntax()
|
||||||
@@ -149,21 +131,6 @@ class GuiTheme:
|
|||||||
logger.error("Could not load theme css file")
|
logger.error("Could not load theme css file")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Icon Files
|
|
||||||
iconsDir = path.join(self.themePath,self.iconPath)
|
|
||||||
if path.isdir(iconsDir):
|
|
||||||
for iconName in self.ICON_MAP:
|
|
||||||
iconFile = path.join(iconsDir,iconName+".svg")
|
|
||||||
if path.isfile(iconFile):
|
|
||||||
self.themeIcons[iconName] = QIcon(iconFile)
|
|
||||||
logger.verbose("Loaded theme icon '%s'" % (iconName+".svg"))
|
|
||||||
continue
|
|
||||||
iconFile = path.join(iconsDir,iconName+".png")
|
|
||||||
if path.isfile(iconFile):
|
|
||||||
self.themeIcons[iconName] = QIcon(iconFile)
|
|
||||||
logger.verbose("Loaded theme icon '%s'" % (iconName+".png"))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Config File
|
# Config File
|
||||||
confParser = configparser.ConfigParser()
|
confParser = configparser.ConfigParser()
|
||||||
try:
|
try:
|
||||||
@@ -307,11 +274,6 @@ class GuiTheme:
|
|||||||
|
|
||||||
return self.syntaxList
|
return self.syntaxList
|
||||||
|
|
||||||
def getIcon(self, iconName, iconSize=None):
|
|
||||||
if iconName in self.themeIcons:
|
|
||||||
return self.themeIcons[iconName]
|
|
||||||
return QIcon()
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|||||||
Reference in New Issue
Block a user