Skins feature completed and ready to review and test.

Improoved UI Quality in the skins

Skins are css files located in the skins folder

Added author and contributors to the about dialog

Known issue: The app need to be restarted when return to default UI when 
changed from a skinned UI
pull/34/head
Carl Tremblay 2019-10-09 23:06:07 -04:00
rodzic f0405aea2e
commit b2df018635
4 zmienionych plików z 328 dodań i 58 usunięć

Wyświetl plik

@ -13,7 +13,7 @@
#
# 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 os
# import os
import collections
import logging
import math
@ -38,9 +38,7 @@ from .Touchstone import Touchstone
from .Analysis import Analysis, LowPassAnalysis, HighPassAnalysis, BandPassAnalysis
from .about import version as ver
from PyQt5.QtWidgets import QApplication, QPushButton, QDesktopWidget
from .skins_utils import DARK_SKIN_COLORED, DARK_SKIN_MONOCHROME, LIGHT_SKIN_COLORED,\
LIGHT_SKIN_MONOCHROME
from .skins import Skins
from .skins_utils import *
app = QtWidgets.QApplication(sys.argv)
@ -491,7 +489,8 @@ class NanoVNASaver(QtWidgets.QWidget):
"\n\n\N{COPYRIGHT SIGN} Copyright 2019 Rune B. Broberg\n" +
"This program comes with ABSOLUTELY NO WARRANTY\n" +
"This program is licensed under the GNU General Public License version 3\n\n" +
"See https://mihtjel.github.io/nanovna-saver/ for further details"))
"See https://mihtjel.github.io/nanovna-saver/ for further details\n\n" +
"AUTHOR:\nRune B. Broberg - 5Q5R\n\nCONTRIBUTORS:\nOhan Smit, Neilkatin, Carl Tremblay - VA2SAJ"))
button_grid = QtWidgets.QGridLayout()
button_grid.addWidget(btn_open_file_window, 0, 0)
@ -1123,18 +1122,9 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
# **************************
# Skins Controls
# **************************
display_skins_box = QtWidgets.QGroupBox("Skins")
display_skins_layout = QtWidgets.QFormLayout(display_skins_box)
@ -1145,14 +1135,16 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
self.skin_dropdown = QtWidgets.QComboBox()
self.skin_dropdown.addItems(["Light", "Light Colored", "Dark", "Dark Colored"])
self.skin_dropdown.addItems([DARK_SKIN_STRING_COLORED, DARK_SKIN_STRING_MONOCHROME, LIGHT_SKIN_STRING_COLORED, LIGHT_SKIN_STRING_MONOCHROME])
self.skin_dropdown.setDisabled(True)
self.skin_dropdown.currentTextChanged.connect(self.changeSkins)
skin_dropdown_label = QtWidgets.QLabel("Choose skin to display")
display_skins_layout.addRow(self.skin_dropdown, skin_dropdown_label)
layout.addWidget(display_skins_box)
# **************************
# Options Controls
# **************************
display_options_box = QtWidgets.QGroupBox("Options")
display_options_layout = QtWidgets.QFormLayout(display_options_box)
@ -1216,7 +1208,9 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
display_options_layout.addRow("Reference color", self.btnReferenceColorPicker)
layout.addWidget(display_options_box)
# **************************
# Chart Colors Controls
# **************************
color_options_box = QtWidgets.QGroupBox("Chart colors")
color_options_layout = QtWidgets.QFormLayout(color_options_box)
@ -1243,7 +1237,9 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
color_options_layout.addRow("Chart text", self.btn_text_picker)
layout.addWidget(color_options_box)
# **************************
# Font Controls
# **************************
font_options_box = QtWidgets.QGroupBox("Font")
font_options_layout = QtWidgets.QFormLayout(font_options_box)
self.font_dropdown = QtWidgets.QComboBox()
@ -1258,7 +1254,9 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
font_options_layout.addRow("Font size", self.font_dropdown)
layout.addWidget(font_options_box)
# **************************
# Bands Controls
# **************************
bands_box = QtWidgets.QGroupBox("Bands")
bands_layout = QtWidgets.QFormLayout(bands_box)
@ -1281,7 +1279,9 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
bands_layout.addRow(self.btn_manage_bands)
layout.addWidget(bands_box)
# **************************
# Charts Controls
# **************************
charts_box = QtWidgets.QGroupBox("Displayed charts")
charts_layout = QtWidgets.QGridLayout(charts_box)
@ -1345,6 +1345,10 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
self.changeChart(1, 2, chart12_selection.currentText())
layout.addWidget(charts_box)
# *********************************************************************
# Set the default value if value if not saved in the config file
# Set the default UI Skin color
# *********************************************************************
self.dark_mode_option.setChecked(self.app.settings.value("DarkMode", False, bool))
self.show_lines_option.setChecked(self.app.settings.value("ShowLines", False, bool))
@ -1382,7 +1386,20 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
p = self.btn_bands_picker.palette()
p.setColor(QtGui.QPalette.ButtonText, self.bandsColor)
self.btn_bands_picker.setPalette(p)
# ******************************************
# Initialization of Skins mode feature
# ******************************************
self.skin_mode_option.setChecked(self.app.settings.value("SkinMode", False, bool))
if self.skin_mode_option.isChecked():
saved_skin = self.app.settings.value("CurrentSkin", False)
if NanoVNA_UI.validateSkin(saved_skin):
index = self.skin_dropdown.findText(saved_skin, QtCore.Qt.MatchFixedString)
if index >= 0:
self.skin_dropdown.setCurrentIndex(index)
# NanoVNA_UI.updateUI(self)
# *************************************
# Display Settings Functions
# *************************************
def changeChart(self, x, y, chart):
found = None
for c in self.app.charts:
@ -1421,15 +1438,12 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
state = self.dark_mode_option.isChecked()
self.app.settings.setValue("DarkMode", state)
if state and not self.skin_mode_option.isChecked():
self.skin_mode_option.setDisabled(True)
for c in self.app.charts:
c.setBackgroundColor(QtGui.QColor(QtCore.Qt.black))
c.setForegroundColor(QtGui.QColor(QtCore.Qt.lightGray))
c.setTextColor(QtGui.QColor(QtCore.Qt.white))
elif not state and not self.skin_mode_option.isChecked():
self.skin_mode_option.setDisabled(False)
for c in self.app.charts:
c.setBackgroundColor(QtGui.QColor(QtCore.Qt.white))
@ -1439,12 +1453,14 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
self.skin_mode_option.setDisabled(False)
def changeSkins(self):
# TODO DropDown changeEvent update the skin
font_size = self.skin_dropdown.currentText()
if self.skin_mode_option.isChecked():
self.app.settings.setValue("CurrentSkin", self.skin_dropdown.currentText())
NanoVNA_UI.updateUI(self,self.skin_dropdown.currentText(),app)
else:
NanoVNA_UI.updateUI(self, "NULL", app)
def changeSkinMode(self):
state = self.skin_mode_option.isChecked()
self.app.settings.setValue("SkinMode", state)
if state:
self.dark_mode_option.setDisabled(True)
@ -1453,19 +1469,7 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
self.btn_text_picker.setDisabled(True)
self.use_custom_colors.setDisabled(True)
self.skin_dropdown.setDisabled(False)
# TODO
# Skins.dark(app)
# if self.color_mode_option.isChecked():
# app.setStyleSheet("file:///" + DARK_SKIN_COLORED)
# else if !self.skin_mode_option.isChecked():
# app.setStyleSheet("file:///" + DARK_SKIN_MONOCHROME)
# Skins.light(app)
# if self.color_mode_option.isChecked():
# app.setStyleSheet("file:///" + LIGHT_SKIN_COLORED)
# else:
# app.setStyleSheet("file:///" + LIGHT_SKIN_MONOCHROME)
NanoVNA_UI.updateUI(self,self.skin_dropdown.currentText(),app)
else:
self.dark_mode_option.setDisabled(False)
self.btn_background_picker.setDisabled(False)
@ -1473,6 +1477,8 @@ class DisplaySettingsWindow(QtWidgets.QWidget):
self.btn_text_picker.setDisabled(False)
self.use_custom_colors.setDisabled(False)
self.skin_dropdown.setDisabled(True)
NanoVNA_UI.updateUI(self, "NULL", app)
def changeCustomColors(self):
self.app.settings.setValue("UseCustomColors", self.use_custom_colors.isChecked())
@ -1853,6 +1859,7 @@ class BandsModel(QtCore.QAbstractTableModel):
enabled = False
color = QtGui.QColor(128, 128, 128, 48)
# TODO Regionalized bands in the app settings from a DropDown menu. You choose the bands plan from your region
# These bands correspond broadly to the Danish Amateur Radio allocation
default_bands = ["2200 m;135700;137800",
"630 m;472000;479000",

Wyświetl plik

@ -26,18 +26,15 @@ import logging
import qtpy
from qtpy.QtGui import QPalette, QColor
from PyQt5.QtWidgets import QCommonStyle
from .skins_utils import DARK_SKIN_COLORED, DARK_SKIN_MONOCHROME, LIGHT_SKIN_COLORED,\
LIGHT_SKIN_MONOCHROME
from PyQt5 import QtGui, QtCore
logger = logging.getLogger(__name__)
class Skins:
def dark(app):
def dark(app, self, _STYLESHEET):
QT_VERSION = tuple(int(v) for v in qtpy.QT_VERSION.split('.'))
_STYLESHEET = LIGHT_SKIN_MONOCHROME
darkPalette = QPalette()
default_style = QCommonStyle()
# base
darkPalette.setColor(QPalette.WindowText, QColor(180, 180, 180))
darkPalette.setColor(QPalette.Button, QColor(53, 53, 53))
@ -78,12 +75,15 @@ class Skins:
with open(_STYLESHEET) as stylesheet:
app.setStyleSheet(stylesheet.read())
for c in self.app.charts:
c.setBackgroundColor(QtGui.QColor(QtCore.Qt.black))
c.setForegroundColor(QtGui.QColor(QtCore.Qt.lightGray))
c.setTextColor(QtGui.QColor(QtCore.Qt.white))
logger.debug("Skin sucessfully set to dark palette")
def light(app):
def light(app, self, _STYLESHEET):
QT_VERSION = tuple(int(v) for v in qtpy.QT_VERSION.split('.'))
_STYLESHEET = LIGHT_SKIN_MONOCHROME
lightPalette = QPalette()
default_style = QCommonStyle()
# base
lightPalette.setColor(QPalette.WindowText, QColor(0, 0, 0))
lightPalette.setColor(QPalette.Button, QColor(240, 240, 240))
@ -118,9 +118,79 @@ class Skins:
app.setPalette(lightPalette)
if QT_VERSION < (5,):
app.setStyle(default_style)
app.setStyle('plastique')
else:
app.setStyle(default_style)
app.setStyle('Fusion')
with open(_STYLESHEET) as stylesheet:
app.setStyleSheet(stylesheet.read())
for c in self.app.charts:
c.setBackgroundColor(QtGui.QColor(QtCore.Qt.white))
c.setForegroundColor(QtGui.QColor(QtCore.Qt.lightGray))
c.setTextColor(QtGui.QColor(QtCore.Qt.black))
logger.debug("Skin sucessfully set to light palette")
def default(app, self):
# TODO Known issue: The app need to be restarted when return to default UI when you change from a skinned UI
app.setStyleSheet("")
lightPalette = QPalette()
# base
lightPalette.setColor(QPalette.WindowText, QColor(0, 0, 0))
lightPalette.setColor(QPalette.Button, QColor(240, 240, 240))
lightPalette.setColor(QPalette.Light, QColor(180, 180, 180))
lightPalette.setColor(QPalette.Midlight, QColor(200, 200, 200))
lightPalette.setColor(QPalette.Dark, QColor(225, 225, 225))
lightPalette.setColor(QPalette.Text, QColor(0, 0, 0))
lightPalette.setColor(QPalette.BrightText, QColor(0, 0, 0))
lightPalette.setColor(QPalette.ButtonText, QColor(0, 0, 0))
lightPalette.setColor(QPalette.Base, QColor(237, 237, 237))
lightPalette.setColor(QPalette.Window, QColor(240, 240, 240))
lightPalette.setColor(QPalette.Shadow, QColor(20, 20, 20))
lightPalette.setColor(QPalette.Highlight, QColor(76, 163, 224))
lightPalette.setColor(QPalette.HighlightedText, QColor(0, 0, 0))
lightPalette.setColor(QPalette.Link, QColor(0, 162, 232))
lightPalette.setColor(QPalette.AlternateBase, QColor(225, 225, 225))
lightPalette.setColor(QPalette.ToolTipBase, QColor(240, 240, 240))
lightPalette.setColor(QPalette.ToolTipText, QColor(0, 0, 0))
# disabled
lightPalette.setColor(QPalette.Disabled, QPalette.WindowText,
QColor(115, 115, 115))
lightPalette.setColor(QPalette.Disabled, QPalette.Text,
QColor(115, 115, 115))
lightPalette.setColor(QPalette.Disabled, QPalette.ButtonText,
QColor(115, 115, 115))
lightPalette.setColor(QPalette.Disabled, QPalette.Highlight,
QColor(190, 190, 190))
lightPalette.setColor(QPalette.Disabled, QPalette.HighlightedText,
QColor(115, 115, 115))
default_style = QCommonStyle()
app.setStyle(default_style)
app.setPalette(lightPalette)
self.btn_background_picker.setDisabled(True)
self.btn_foreground_picker.setDisabled(True)
self.btn_text_picker.setDisabled(True)
p = self.btn_background_picker.palette()
p.setColor(QtGui.QPalette.ButtonText, self.backgroundColor)
self.btn_background_picker.setPalette(p)
p = self.btn_foreground_picker.palette()
p.setColor(QtGui.QPalette.ButtonText, self.foregroundColor)
self.btn_foreground_picker.setPalette(p)
p = self.btn_text_picker.palette()
p.setColor(QtGui.QPalette.ButtonText, self.textColor)
self.btn_text_picker.setPalette(p)
p = self.btn_bands_picker.palette()
p.setColor(QtGui.QPalette.ButtonText, self.bandsColor)
self.btn_bands_picker.setPalette(p)
for c in self.app.charts:
c.setBackgroundColor(QtGui.QColor(QtCore.Qt.white))
c.setForegroundColor(QtGui.QColor(QtCore.Qt.lightGray))
c.setTextColor(QtGui.QColor(QtCore.Qt.black))
logger.debug("Skin sucessfully set to default palette")

Wyświetl plik

@ -0,0 +1,137 @@
QGroupBox {
background-color: palette(alternate-base);
border: 1px solid palette(midlight);
margin-top: 25px;
}
QGroupBox::title {
background-color: transparent;
}
/*
* QToolBar
*/
QToolBar {
border: none;
}
/*
* QTabBar
*/
QTabBar {
background-color: transparent;
}
QTabBar::tab {
padding: 4px 6px;
background-color: transparent;
border-bottom: 2px solid transparent;
}
QTabBar::tab:selected, QTabBar::tab:hover {
color: palette(text);
border-bottom: 2px solid palette(highlight);
}
QTabBar::tab:selected:disabled {
border-bottom: 2px solid palette(light);
}
/*
* QScrollBar
*/
QScrollBar:vertical {
background: palette(base);
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
width: 16px;
margin: 0px;
}
QScrollBar::handle:vertical {
background-color: palette(alternate-base);
border-radius: 2px;
min-height: 20px;
margin: 2px 4px 2px 4px;
}
QScrollBar::handle:vertical:hover {
background-color: palette(highlight);
}
QScrollBar::add-line:vertical {
background: none;
height: 0px;
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical {
background: none;
height: 0px;
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar:horizontal {
background: palette(base);
height: 16px;
margin: 0px;
}
QScrollBar::handle:horizontal {
background-color: palette(alternate-base);
border-radius: 2px;
min-width: 20px;
margin: 4px 2px 4px 2px;
}
QScrollBar::handle:horizontal:hover {
background-color: palette(highlight);
}
QScrollBar::add-line:horizontal {
background: none;
width: 0px;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal {
background: none;
width: 0px;
subcontrol-position: top;
subcontrol-origin: margin;
}
/*
* QScrollArea
*/
QScrollArea {
border-style: none;
}
QScrollArea #scrollAreaWidgetContents {
background-color: palette(alternate-base);
}
/*
* QSlider
*/
QSlider::handle:horizontal {
border-radius: 5px;
background-color: palette(light);
max-height: 20px;
}
QSlider::add-page:horizontal {
background: palette(base);
}
QSlider::sub-page:horizontal {
background: palette(highlight);
}
QSlider::sub-page:horizontal:disabled {
background-color: palette(light);
}

Wyświetl plik

@ -13,9 +13,14 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from os.path import join, dirname, abspath
import logging
import sys
from os.path import join, dirname, abspath
from .about import debug
from .skins import Skins
logger = logging.getLogger(__name__)
def DARK_SKIN_MONOCHROME():
if debug == True:
@ -41,7 +46,58 @@ def LIGHT_SKIN_COLORED():
else:
return sys._MEIPASS + '/skins/light-colored.css'
DARK_SKIN_MONOCHROME = DARK_SKIN_MONOCHROME()
DARK_SKIN_COLORED = DARK_SKIN_COLORED()
LIGHT_SKIN_MONOCHROME = LIGHT_SKIN_MONOCHROME()
LIGHT_SKIN_COLORED = LIGHT_SKIN_COLORED()
# DARK_SKIN_MONOCHROME = DARK_SKIN_MONOCHROME()
# DARK_SKIN_COLORED = DARK_SKIN_COLORED()
# LIGHT_SKIN_MONOCHROME = LIGHT_SKIN_MONOCHROME()
# LIGHT_SKIN_COLORED = LIGHT_SKIN_COLORED()
DARK_SKIN_STRING_COLORED = "Dark Colored"
DARK_SKIN_STRING_MONOCHROME = "Dark"
LIGHT_SKIN_STRING_COLORED = "Light Colored"
LIGHT_SKIN_STRING_MONOCHROME = "Light"
class NanoVNA_UI:
def updateUI(self, skin, app):
current_skin = self.skin_dropdown.currentText()
logger.debug("Current Skin is: " + current_skin)
logger.debug("Optionnal Skin to update: " + skin)
if skin < "NULL":
if skin == DARK_SKIN_STRING_COLORED:
current_skin = DARK_SKIN_COLORED()
logger.debug("Skin set to DARK_SKIN_COLORED")
Skins.dark(app, self, current_skin)
if skin == DARK_SKIN_STRING_MONOCHROME:
current_skin = DARK_SKIN_MONOCHROME()
Skins.dark(app, self, current_skin)
logger.debug("Skin set to DARK_SKIN_MONOCHROME")
if skin == LIGHT_SKIN_STRING_MONOCHROME:
current_skin = LIGHT_SKIN_MONOCHROME()
Skins.light(app, self, current_skin)
logger.debug("Skin set to LIGHT_SKIN_STRING_MONOCHROME")
if skin == LIGHT_SKIN_STRING_COLORED:
current_skin = LIGHT_SKIN_COLORED()
Skins.light(app, self, current_skin)
logger.debug("Skin set to LIGHT_SKIN_STRING_COLORED")
else:
Skins.default(app, self)
logger.debug("Skin set to Default")
# TODO
# Skins.dark(app)
# if self.color_mode_option.isChecked():
# app.setStyleSheet("file:///" + DARK_SKIN_COLORED)
# else if !self.skin_mode_option.isChecked():
# app.setStyleSheet("file:///" + DARK_SKIN_MONOCHROME)
# Skins.light(app)
# if self.color_mode_option.isChecked():
# app.setStyleSheet("file:///" + LIGHT_SKIN_COLORED)
# else:
# app.setStyleSheet("file:///" + LIGHT_SKIN_MONOCHROME)
def validateSkin(saved_skin):
if not saved_skin < DARK_SKIN_STRING_COLORED or not saved_skin < DARK_SKIN_STRING_MONOCHROME or not saved_skin < LIGHT_SKIN_STRING_COLORED or not saved_skin < LIGHT_SKIN_STRING_MONOCHROME:
return True
else:
return False