Merge pull request #347 from pstavirs/themes

Add Ostinato Themes
This commit is contained in:
Srivats P 2022-02-05 20:51:32 +05:30 committed by GitHub
commit 2bf2973a23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 7356 additions and 73 deletions

View File

@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "params.h"
#include "preferences.h"
#include "settings.h"
#include "thememanager.h"
#include <QApplication>
#include <QDateTime>
@ -84,6 +85,8 @@ int main(int argc, char* argv[])
appSettings->value(kDiffPathKey, kDiffPathDefaultValue).toString(),
appSettings->value(kAwkPathKey, kAwkPathDefaultValue).toString());
ThemeManager::instance()->setTheme(appSettings->value(kThemeKey).toString());
qsrand(QDateTime::currentDateTime().toTime_t());
mainWindow = new MainWindow;

View File

@ -128,12 +128,23 @@ SOURCES += \
streamstatsmodel.cpp \
streamstatswindow.cpp \
streamswidget.cpp \
thememanager.cpp \
variablefieldswidget.cpp
THEMES += \
themes/material-dark.qss \
themes/material-dark.rcc \
themes/material-light.qss \
themes/material-light.rcc \
themes/qds-dark.qss \
themes/qds-dark.rcc \
themes/qds-light.qss \
themes/qds-light.rcc \
QMAKE_DISTCLEAN += object_script.*
include(../install.pri)
include(../shared.pri)
include(../version.pri)
include(../options.pri)

View File

@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "../common/ostprotolib.h"
#include "settings.h"
#include "thememanager.h"
#include <QFileDialog>
#include <QtGlobal>
@ -40,6 +41,7 @@ Preferences::Preferences()
setupUi(this);
// Program paths
wiresharkPathEdit->setText(appSettings->value(kWiresharkPathKey,
kWiresharkPathDefaultValue).toString());
tsharkPathEdit->setText(appSettings->value(kTsharkPathKey,
@ -51,6 +53,10 @@ Preferences::Preferences()
awkPathEdit->setText(appSettings->value(kAwkPathKey,
kAwkPathDefaultValue).toString());
// Theme
theme->addItems(ThemeManager::instance()->themeList());
theme->setCurrentText(appSettings->value(kThemeKey).toString());
// TODO(only if required): kUserKey
}
@ -78,6 +84,7 @@ void Preferences::initDefaults()
void Preferences::accept()
{
// Program paths
appSettings->setValue(kWiresharkPathKey, wiresharkPathEdit->text());
appSettings->setValue(kTsharkPathKey, tsharkPathEdit->text());
appSettings->setValue(kGzipPathKey, gzipPathEdit->text());
@ -90,6 +97,9 @@ void Preferences::accept()
appSettings->value(kDiffPathKey, kDiffPathDefaultValue).toString(),
appSettings->value(kAwkPathKey, kAwkPathDefaultValue).toString());
// Theme
ThemeManager::instance()->setTheme(theme->currentText());
QDialog::accept();
}

View File

@ -1,7 +1,8 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Preferences</class>
<widget class="QDialog" name="Preferences" >
<property name="geometry" >
<widget class="QDialog" name="Preferences">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
@ -9,148 +10,149 @@
<height>220</height>
</rect>
</property>
<property name="windowTitle" >
<property name="windowTitle">
<string>Preferences</string>
</property>
<property name="windowIcon" >
<iconset resource="ostinato.qrc" >:/icons/preferences.png</iconset>
<property name="windowIcon">
<iconset resource="ostinato.qrc">
<normaloff>:/icons/preferences.png</normaloff>:/icons/preferences.png</iconset>
</property>
<layout class="QVBoxLayout" >
<layout class="QVBoxLayout">
<item>
<widget class="QFrame" name="frame" >
<property name="frameShape" >
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow" >
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>'wireshark' Path</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>wiresharkPathEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="QLineEdit" name="wiresharkPathEdit" >
<property name="enabled" >
<item row="0" column="1">
<widget class="QLineEdit" name="wiresharkPathEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2" >
<widget class="QToolButton" name="wiresharkPathButton" >
<property name="text" >
<item row="0" column="2">
<widget class="QToolButton" name="wiresharkPathButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>'tshark' Path</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>tsharkPathEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QLineEdit" name="tsharkPathEdit" >
<property name="enabled" >
<item row="1" column="1">
<widget class="QLineEdit" name="tsharkPathEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2" >
<widget class="QToolButton" name="tsharkPathButton" >
<property name="text" >
<item row="1" column="2">
<widget class="QToolButton" name="tsharkPathButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_5" >
<property name="text" >
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>'gzip' Path</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>diffPathEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QLineEdit" name="gzipPathEdit" >
<property name="enabled" >
<item row="2" column="1">
<widget class="QLineEdit" name="gzipPathEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2" >
<widget class="QToolButton" name="gzipPathButton" >
<property name="text" >
<item row="2" column="2">
<widget class="QToolButton" name="gzipPathButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="3" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>'diff' Path</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>diffPathEdit</cstring>
</property>
</widget>
</item>
<item row="3" column="1" >
<widget class="QLineEdit" name="diffPathEdit" >
<property name="enabled" >
<item row="3" column="1">
<widget class="QLineEdit" name="diffPathEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2" >
<widget class="QToolButton" name="diffPathButton" >
<property name="text" >
<item row="3" column="2">
<widget class="QToolButton" name="diffPathButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="4" column="0" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>'awk' Path</string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>awkPathEdit</cstring>
</property>
</widget>
</item>
<item row="4" column="1" >
<widget class="QLineEdit" name="awkPathEdit" >
<property name="enabled" >
<item row="4" column="1">
<widget class="QLineEdit" name="awkPathEdit">
<property name="enabled">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="2" >
<widget class="QToolButton" name="awkPathButton" >
<property name="text" >
<item row="4" column="2">
<widget class="QToolButton" name="awkPathButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="5" column="1" >
<item row="5" column="1">
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>21</width>
<height>61</height>
@ -162,12 +164,26 @@
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Theme (Experimental)</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="theme"/>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
@ -187,7 +203,7 @@
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="ostinato.qrc" />
<include location="ostinato.qrc"/>
</resources>
<connections>
<connection>
@ -196,11 +212,11 @@
<receiver>Preferences</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
@ -212,11 +228,11 @@
<receiver>Preferences</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>

View File

@ -74,6 +74,8 @@ const QString kAwkPathDefaultValue("/usr/bin/awk");
const QString kAwkPathDefaultValue("/usr/bin/awk");
#endif
const QString kThemeKey("Theme");
const QString kUserKey("User");
extern QString kUserDefaultValue;

130
client/thememanager.cpp Normal file
View File

@ -0,0 +1,130 @@
/*
Copyright (C) 2021 Srivats P.
This file is part of "Ostinato"
This 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 <http://www.gnu.org/licenses/>
*/
#include "thememanager.h"
#include "settings.h"
#include <QApplication>
#include <QDebug>
#include <QDir>
#include <QDirIterator>
#include <QRegularExpression>
#include <QResource>
ThemeManager *ThemeManager::instance_{nullptr};
ThemeManager::ThemeManager()
{
themeDir_ = QCoreApplication::applicationDirPath() + "/themes/";
#if defined(Q_OS_MAC)
/*
* Executable and Theme directory location inside app bundle -
* Ostinato.app/Contents/MacOS/
* Ostinato.app/Contents/SharedSupport/themes/
*/
themeDir_.replace("/MacOS/", "/SharedSupport/");
#elif defined(Q_OS_UNIX)
/*
* Possible (but not comprehensive) locations for Ostinato executable
* and theme directory locations
*
* non-install-dir/
* non-install-dir/themes/
*
* /usr/[local]/bin/
* /usr/[local]/share/ostinato/themes/
*
* /opt/ostinato/bin/
* /opt/ostinato/share/themes/
*/
if (themeDir_.contains(QRegularExpression("^/usr/.*/bin/")))
themeDir_.replace("/bin/", "/share/ostinato/");
else if (themeDir_.contains(QRegularExpression("^/opt/.*/bin/")))
themeDir_.replace("/bin/", "/share/");
#endif
qDebug("Themes directory: %s", qPrintable(themeDir_));
}
QStringList ThemeManager::themeList()
{
QDir themeDir(themeDir_);
themeDir.setFilter(QDir::Files);
themeDir.setNameFilters(QStringList() << "*.qss");
themeDir.setSorting(QDir::Name);
QStringList themes = themeDir.entryList();
for (QString& theme : themes)
theme.remove(".qss");
themes.prepend("default");
return themes;
}
void ThemeManager::setTheme(QString theme)
{
// Remove current theme, if we have one
QString oldTheme = appSettings->value(kThemeKey).toString();
if (!oldTheme.isEmpty()) {
// Remove stylesheet first so that there are
// no references to resources when unregistering 'em
qApp->setStyleSheet("");
QString rccFile = themeDir_ + oldTheme + ".rcc";
if (QResource::unregisterResource(rccFile)) {
qDebug("Unable to unregister theme rccFile %s",
qPrintable(rccFile));
}
appSettings->setValue(kThemeKey, QVariant());
}
if (theme.isEmpty() || (theme == "default"))
return;
// Apply new theme
QFile qssFile(themeDir_ + theme + ".qss");
if (!qssFile.open(QFile::ReadOnly)) {
qDebug("Unable to open theme qssFile %s",
qPrintable(qssFile.fileName()));
return;
}
// Register theme resource before applying theme style sheet
QString rccFile = themeDir_ + theme + ".rcc";
if (!QResource::registerResource(rccFile))
qDebug("Unable to register theme rccFile %s", qPrintable(rccFile));
#if 0 // FIXME: debug only
QDirIterator it(":", QDirIterator::Subdirectories);
while (it.hasNext()) {
qDebug() << it.next();
}
#endif
QString styleSheet { qssFile.readAll() };
qApp->setStyleSheet(styleSheet);
appSettings->setValue(kThemeKey, theme);
}
ThemeManager* ThemeManager::instance()
{
if (!instance_)
instance_ = new ThemeManager();
return instance_;
}

42
client/thememanager.h Normal file
View File

@ -0,0 +1,42 @@
/*
Copyright (C) 2021 Srivats P.
This file is part of "Ostinato"
This 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 <http://www.gnu.org/licenses/>
*/
#ifndef _THEME_MANAGER_H
#define _THEME_MANAGER_H
#include <QStringList>
class ThemeManager
{
public:
ThemeManager();
QStringList themeList();
void setTheme(QString theme);
static ThemeManager* instance();
private:
QString themeDir_;
static ThemeManager *instance_;
};
#endif

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

2213
client/themes/qds-dark.qss Normal file

File diff suppressed because it is too large Load Diff

BIN
client/themes/qds-dark.rcc Normal file

Binary file not shown.

2213
client/themes/qds-light.qss Normal file

File diff suppressed because it is too large Load Diff

BIN
client/themes/qds-light.rcc Normal file

Binary file not shown.

29
shared.pri Normal file
View File

@ -0,0 +1,29 @@
#
# Qt qmake integration for installing files other than executables
# Author: Srivats P
#
# To install files other than executables, specify them in SHARED variable
# and include this file AFTER install.pri
#
# Example:
# SHARED = file1 file2
# include(install.pri)
# include(shared.pri)
#
macx {
shared.path = $${PREFIX}/Ostinato/Ostinato.app/Contents/SharedSupport/
} else: unix {
shared.path = $${PREFIX}/share/ostinato/
} else {
shared.path = $${PREFIX}/bin
}
shared.files = $${SHARED}
INSTALLS += shared
# Themes - need a subdir inside shared
themes.files = $${THEMES}
themes.path = $${shared.path}/themes
INSTALLS += themes