From adfc887770e6d7f3bb6f3eafbc3dd1ac60e3c92d Mon Sep 17 00:00:00 2001 From: Tim Delaney Date: Sun, 19 Feb 2017 11:47:19 +1100 Subject: [PATCH 1/6] Add appearance options tab by @magao: Consolidate appearance options in their own tab. by @evsh: Add preferences-desktop-theme icon, copied from fa-desktop (Unicode f108) symbol of FontAwesome --- src/base/preferences.cpp | 72 ++++++++---- src/base/preferences.h | 16 +-- src/gui/advancedsettings.cpp | 11 -- src/gui/advancedsettings.h | 4 - src/gui/optionsdlg.cpp | 19 ++- src/gui/optionsdlg.h | 3 +- src/gui/optionsdlg.ui | 109 ++++++++++++++++-- src/icons.qrc | 1 + .../build-icons/preferences-desktop-theme.svg | 4 + .../qbt-theme/preferences-desktop-theme.png | Bin 0 -> 3017 bytes 10 files changed, 178 insertions(+), 61 deletions(-) create mode 100644 src/icons/qbt-theme/build-icons/preferences-desktop-theme.svg create mode 100644 src/icons/qbt-theme/preferences-desktop-theme.png diff --git a/src/base/preferences.cpp b/src/base/preferences.cpp index 8f8e4f3096..cb81f5955f 100644 --- a/src/base/preferences.cpp +++ b/src/base/preferences.cpp @@ -31,6 +31,7 @@ */ #include +#include #include #include #include @@ -90,17 +91,40 @@ void Preferences::setValue(const QString &key, const QVariant &value) SettingsStorage::instance()->storeValue(key, value); } -// General options +// Appearance/Language options QString Preferences::getLocale() const { - return value("Preferences/General/Locale", QLocale::system().name()).toString(); + return value("Appearance/Locale", QLocale::system().name()).toString(); } void Preferences::setLocale(const QString &locale) { - setValue("Preferences/General/Locale", locale); + setValue("Appearance/Locale", locale); +} + +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) +bool Preferences::useSystemIconTheme() const +{ + return value("Appearance/useSystemIconTheme", true).toBool(); +} + +void Preferences::setSystemIconTheme(bool enabled) +{ + setValue("Appearance/useSystemIconTheme", enabled); +} +#endif + +bool Preferences::useAlternatingRowColors() const +{ + return value("Appearance/AlternatingRowColors", true).toBool(); } +void Preferences::setAlternatingRowColors(bool b) +{ + setValue("Appearance/AlternatingRowColors", b); +} + +// General options bool Preferences::deleteTorrentFilesAsDefault() const { return value("Preferences/General/DeleteTorrentsFilesAsDefault", false).toBool(); @@ -131,16 +155,6 @@ void Preferences::showSpeedInTitleBar(bool show) setValue("Preferences/General/SpeedInTitleBar", show); } -bool Preferences::useAlternatingRowColors() const -{ - return value("Preferences/General/AlternatingRowColors", true).toBool(); -} - -void Preferences::setAlternatingRowColors(bool b) -{ - setValue("Preferences/General/AlternatingRowColors", b); -} - bool Preferences::getHideZeroValues() const { return value("Preferences/General/HideZeroValues", false).toBool(); @@ -730,18 +744,6 @@ void Preferences::resolvePeerHostNames(bool resolve) setValue("Preferences/Connection/ResolvePeerHostNames", resolve); } -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) -bool Preferences::useSystemIconTheme() const -{ - return value("Preferences/Advanced/useSystemIconTheme", true).toBool(); -} - -void Preferences::useSystemIconTheme(bool enabled) -{ - setValue("Preferences/Advanced/useSystemIconTheme", enabled); -} -#endif - bool Preferences::recursiveDownloadDisabled() const { return value("Preferences/Advanced/DisableRecursiveDownload", false).toBool(); @@ -1456,6 +1458,26 @@ void Preferences::setSpeedWidgetGraphEnable(int id, const bool enable) void Preferences::upgrade() { + // Migrate single-value prefs to new section/name + QList> prefsToMigrate = { + { "Preferences/General/Locale", "Appearance/Locale" }, + { "Preferences/General/AlternatingRowColors", "Appearance/AlternatingRowColors" }, + { "Preferences/Advanced/useSystemIconTheme", "Appearance/useSystemIconTheme" }, + }; + + for (auto iter = prefsToMigrate.begin(); iter != prefsToMigrate.end(); ++iter) { + QString pre(iter->first); + QString post(iter->second); + + QVariant preValue = value(pre); + + if (!preValue.isNull()) { + qDebug() << "Migrating preference" << pre << "->" << post; + setValue(post, preValue); + SettingsStorage::instance()->removeValue(pre); + } + } + QStringList labels = value("TransferListFilters/customLabels").toStringList(); if (!labels.isEmpty()) { QVariantMap categories = value("BitTorrent/Session/Categories").toMap(); diff --git a/src/base/preferences.h b/src/base/preferences.h index e7f2e53e8e..135f6a95de 100644 --- a/src/base/preferences.h +++ b/src/base/preferences.h @@ -100,17 +100,23 @@ class Preferences: public QObject static void freeInstance(); static Preferences *instance(); - // General options + // Appearance options QString getLocale() const; void setLocale(const QString &locale); + bool useAlternatingRowColors() const; + void setAlternatingRowColors(bool b); +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) + bool useSystemIconTheme() const; + void setSystemIconTheme(bool enabled); +#endif + + // General options bool deleteTorrentFilesAsDefault() const; void setDeleteTorrentFilesAsDefault(bool del); bool confirmOnExit() const; void setConfirmOnExit(bool confirm); bool speedInTitleBar() const; void showSpeedInTitleBar(bool show); - bool useAlternatingRowColors() const; - void setAlternatingRowColors(bool b); bool getHideZeroValues() const; void setHideZeroValues(bool b); int getHideZeroComboValues() const; @@ -225,10 +231,6 @@ class Preferences: public QObject void resolvePeerCountries(bool resolve); bool resolvePeerHostNames() const; void resolvePeerHostNames(bool resolve); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - bool useSystemIconTheme() const; - void useSystemIconTheme(bool enabled); -#endif bool recursiveDownloadDisabled() const; void disableRecursiveDownload(bool disable = true); #ifdef Q_OS_WIN diff --git a/src/gui/advancedsettings.cpp b/src/gui/advancedsettings.cpp index 31ad22068d..229e3255fe 100644 --- a/src/gui/advancedsettings.cpp +++ b/src/gui/advancedsettings.cpp @@ -69,9 +69,6 @@ enum AdvSettingsRows TORRENT_ADDED_NOTIFICATIONS, CONFIRM_REMOVE_ALL_TAGS, DOWNLOAD_TRACKER_FAVICON, -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - USE_ICON_THEME, -#endif // libtorrent section LIBTORRENT_HEADER, @@ -207,10 +204,6 @@ void AdvancedSettings::saveAdvancedSettings() #if defined(Q_OS_WIN) || defined(Q_OS_MAC) pref->setUpdateCheckEnabled(cb_update_check.isChecked()); -#endif - // Icon theme -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - pref->useSystemIconTheme(cb_use_icon_theme.isChecked()); #endif pref->setConfirmTorrentRecheck(cb_confirm_torrent_recheck.isChecked()); @@ -439,10 +432,6 @@ void AdvancedSettings::loadAdvancedSettings() #if defined(Q_OS_WIN) || defined(Q_OS_MAC) cb_update_check.setChecked(pref->isUpdateCheckEnabled()); addRow(UPDATE_CHECK, tr("Check for software updates"), &cb_update_check); -#endif -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - cb_use_icon_theme.setChecked(pref->useSystemIconTheme()); - addRow(USE_ICON_THEME, tr("Use system icon theme"), &cb_use_icon_theme); #endif // Torrent recheck confirmation cb_confirm_torrent_recheck.setChecked(pref->confirmTorrentRecheck()); diff --git a/src/gui/advancedsettings.h b/src/gui/advancedsettings.h index d780db5e50..3a63522147 100644 --- a/src/gui/advancedsettings.h +++ b/src/gui/advancedsettings.h @@ -88,10 +88,6 @@ private slots: #if defined(Q_OS_WIN) || defined(Q_OS_MAC) QCheckBox cb_update_check; #endif - -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - QCheckBox cb_use_icon_theme; -#endif }; #endif // ADVANCEDSETTINGS_H diff --git a/src/gui/optionsdlg.cpp b/src/gui/optionsdlg.cpp index c40db1c97b..1f5f1b72c4 100644 --- a/src/gui/optionsdlg.cpp +++ b/src/gui/optionsdlg.cpp @@ -86,7 +86,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) #endif // Icons - m_ui->tabSelection->item(TAB_UI)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop")); + m_ui->tabSelection->item(TAB_APPEARANCE)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop-theme")); + m_ui->tabSelection->item(TAB_BEHAVIOUR)->setIcon(GuiIconProvider::instance()->getIcon("preferences-desktop")); m_ui->tabSelection->item(TAB_BITTORRENT)->setIcon(GuiIconProvider::instance()->getIcon("preferences-system-network")); m_ui->tabSelection->item(TAB_CONNECTION)->setIcon(GuiIconProvider::instance()->getIcon("network-wired")); m_ui->tabSelection->item(TAB_DOWNLOADS)->setIcon(GuiIconProvider::instance()->getIcon("folder-download")); @@ -132,6 +133,13 @@ OptionsDialog::OptionsDialog(QWidget *parent) } } +#if !((defined(Q_OS_UNIX) && !defined(Q_OS_MAC))) + m_ui->checkUseSystemTheme->setHidden(true); +#endif + + // Hide the Appearance/Desktop section if it doesn't contain any visible children. + m_ui->groupBoxAppearanceDesktop->setHidden(m_ui->groupBoxAppearanceDesktop->childrenRect().isEmpty()); + m_ui->scanFoldersView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); m_ui->scanFoldersView->setModel(ScanFoldersModel::instance()); m_ui->scanFoldersView->setItemDelegate(new ScanFoldersDelegate(this, m_ui->scanFoldersView)); @@ -186,6 +194,9 @@ OptionsDialog::OptionsDialog(QWidget *parent) // General tab connect(m_ui->comboI18n, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->confirmDeletion, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) + connect(m_ui->checkUseSystemTheme, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); +#endif connect(m_ui->checkAltRowColors, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkHideZero, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkHideZero, &QAbstractButton::toggled, m_ui->comboHideZero, &QWidget::setEnabled); @@ -495,6 +506,9 @@ void OptionsDialog::saveOptions() pref->setLocale(locale); pref->setConfirmTorrentDeletion(m_ui->confirmDeletion->isChecked()); pref->setAlternatingRowColors(m_ui->checkAltRowColors->isChecked()); +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) + pref->setSystemIconTheme(m_ui->checkUseSystemTheme->isChecked()); +#endif pref->setHideZeroValues(m_ui->checkHideZero->isChecked()); pref->setHideZeroComboValues(m_ui->comboHideZero->currentIndex()); #ifndef Q_OS_MAC @@ -710,6 +724,9 @@ void OptionsDialog::loadOptions() setLocale(pref->getLocale()); m_ui->confirmDeletion->setChecked(pref->confirmTorrentDeletion()); m_ui->checkAltRowColors->setChecked(pref->useAlternatingRowColors()); +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) + m_ui->checkUseSystemTheme->setChecked(pref->useSystemIconTheme()); +#endif m_ui->checkHideZero->setChecked(pref->getHideZeroValues()); m_ui->comboHideZero->setEnabled(m_ui->checkHideZero->isChecked()); m_ui->comboHideZero->setCurrentIndex(pref->getHideZeroComboValues()); diff --git a/src/gui/optionsdlg.h b/src/gui/optionsdlg.h index efaaddf95c..ea438556c1 100644 --- a/src/gui/optionsdlg.h +++ b/src/gui/optionsdlg.h @@ -65,7 +65,8 @@ class OptionsDialog: public QDialog private: enum Tabs { - TAB_UI, + TAB_APPEARANCE, + TAB_BEHAVIOUR, TAB_DOWNLOADS, TAB_CONNECTION, TAB_SPEED, diff --git a/src/gui/optionsdlg.ui b/src/gui/optionsdlg.ui index e617eeb98d..6f2164cfb8 100644 --- a/src/gui/optionsdlg.ui +++ b/src/gui/optionsdlg.ui @@ -47,6 +47,11 @@ -1 + + + Appearance + + Behavior @@ -92,8 +97,8 @@ 0 - - + + 0 @@ -107,7 +112,7 @@ 0 - + 0 @@ -117,7 +122,7 @@ true - + 0 @@ -126,7 +131,7 @@ 893 - + @@ -192,25 +197,104 @@ - + + + Desktop + + + + + + Use system icon theme + + + + + + + + Transfer List - + - + - Confirm when deleting torrents + Use alternating row colors true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + true + + + + + 0 + 0 + 504 + 849 + + + + + + + Transfer List + + - + - Use alternating row colors + Confirm when deleting torrents true @@ -3165,7 +3249,8 @@ Use ';' to split multiple entries. Can use wildcard '*'. tabOption - comboI18n + textSavePath + browseSaveDirButton checkStartPaused spinPort checkUPnP diff --git a/src/icons.qrc b/src/icons.qrc index 257b9813af..3f325e9d18 100644 --- a/src/icons.qrc +++ b/src/icons.qrc @@ -299,6 +299,7 @@ icons/qbt-theme/object-locked.png icons/qbt-theme/office-chart-line.png icons/qbt-theme/preferences-desktop.png + icons/qbt-theme/preferences-desktop-theme.png icons/qbt-theme/preferences-other.png icons/qbt-theme/preferences-system-network.png icons/qbt-theme/preferences-web-browser-cookies.png diff --git a/src/icons/qbt-theme/build-icons/preferences-desktop-theme.svg b/src/icons/qbt-theme/build-icons/preferences-desktop-theme.svg new file mode 100644 index 0000000000..64e1a906a5 --- /dev/null +++ b/src/icons/qbt-theme/build-icons/preferences-desktop-theme.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/icons/qbt-theme/preferences-desktop-theme.png b/src/icons/qbt-theme/preferences-desktop-theme.png new file mode 100644 index 0000000000000000000000000000000000000000..4c05fbb76479229232be04a37cc8373d5e92cb59 GIT binary patch literal 3017 zcmeHJYc$kb8{ad3GZThMuH!PfQ^*V>xizD58FHr)Cr!C@p=Qn?BFt1LClr}Tlw1a@ zP!cCZ{k=KIK_aCb#JG)18al}!<;;1%ykFk;sf2>wVw4{_V#p< zlTnue0Lal?_xS>Vkhnmw2`#bnjt$-tkUHk*;RwLPOxg7#D9K$r)YaDmfCNJTI2Qp} zlTe%)0Ah&%%rOA4%>zJ{b*st8ULv56y1VR?pk%G?eUc&pX_o83XaMBf{yvBt6L}2@ ziHV_kIAO+Q6cx4_YJ|cPU4}>7=jb0l`0@SWsN3OM@TY~L`a^VNgWRt)#KEwr(6Ean z+4Qy|iwl?aW776sJHEepVl+)bk3=#|D8`b$)0$t&V$+X%H1DBt_KmBBrt3%O>Hn^; zbUo@qhg$f@mmhwOPPfM^8q>o@c`P8Dnxxp&Z9$+Clj4T1&@qOgyX4ijFNFIgBq;{`G%j# zV+Qrdu)Cz}W$dNwp^P4_Rd{2`=OB{bUqm zW7O*p%5Qz#*v>NF@wIHV9PC6s0ADe0PZi(XM8?A98c%6-x}3m5Pyu7u%)9*8b2`;h z1WZWqqcOI;R(!;7%;OCi3!=ij_14EwWi+#xkFQ3bh7vq)%`sO55t$R#khO5cg64tO z?f&CZ1Qr(b5}j;+8IZ4f(GrlIU%O=>M5X>{=jxN!CmWE)WA=^7B&x6`bLP9a4l9g1fy1HJN}E53Fp@&RjH?oP}@ z)do~NVKDJSN!`F9EAsxE!p_|S$H8>?EZ=7R&McvKMw3cmozZ~QFv%Ib!zVlaHVX85 zc*2+Q8Wd4fpJw5KQm_Qvht%LBz8$yLeR<_Ca+3Hq_lMY<>>4FedEON`%${x#hw0I9D=};AqNKxWpK#6ZM+n@6QU*m)pPH) z2FknP3-Gt_j;F1~W2B-P__Ld=2Q6rsi4^H}-*$`D1#he;-@yuku+&1opq~@CIsWJ7 zDR=!4dBZgUTIY7taevBIDaXu@V#RpvTb9@G|uoO%C-#!FODZSp!7zFe9M&_SgEpW$hua&_LC>yWt-Krw7MvN#c=ZM_z){E&Ug%K#A_mNz zwx6s6#HNMw#xz6QXr4As>f0`OPE8Rx=$RdL;f{j1T%}AUB59}t7ag=O#r4eZRuBQ=>g{Cc@@E)eO zN-Zv|jk>w@F~@At%~(zSLuZG)I!vh5{S)gq{deLqlsM~(tDZHJN$yRwRMa1}BGTcDkM->*NPgMmSi~VeyK49eWm6m#`vkgqvr^T2%`G12`**IMbD63WQ%M+t# z&3OaXKCw`w;JxDSb3`a>??GRF(le6STgbfvZ=oa`;-D;=^fUu#f4m@`ChYS^Yv1Ww zTt4Ayoq_+?ek?V$-+Tk{1LoGXMElRM1tXH~v;V#I+-4}Ny^%jumJ?N-Q$~j@h(L=x zr7Q{(^bJqkba{)s1JpDJUkNjPO|aByGt_C_<*8>I?>w3e8hQ%+?7BeAh@oJj5ktZq z+B;}Hrw#S$NQMP(@2rs>ExO`(Veu4v##q)1eda1+hM(=u(O~03313Z>ZcGyP>7$FF z^5&9LMlGnoia4D`6zqOp>nN~2X2psYIhukY+Or@}Ee6=08`2@eG51NCNROz?RYK4a z64JJ$S*^iJY^;(MOnbbk@+i7!kEHPR+1lkB+{{Tr53=^^+E{ia=Omt!rfi_D^1scG^$h-K}g(vvH$7Sew zqxWxW5qiC@((}lta++dGsB%h&+TRyL!44zl+n#f8HaiZwJcd%!`wkrFb{N+Ak~o;? znu@eW6wtQHZ%I-j)<$6RSatQ(#Qkk(hAXP Date: Wed, 8 Mar 2017 08:59:01 +0100 Subject: [PATCH 2/6] Add color and font themes --- src/app/application.cpp | 8 + src/base/logger.h | 2 +- src/gui/CMakeLists.txt | 30 +- src/gui/executionlog.cpp | 54 ++-- src/gui/gui.pri | 32 +- src/gui/loglistwidget.cpp | 31 +- src/gui/loglistwidget.h | 3 + src/gui/mainwindow.cpp | 1 + src/gui/optionsdlg.cpp | 214 ++++++++++++++ src/gui/optionsdlg.h | 6 +- src/gui/optionsdlg.ui | 112 ++++++- src/gui/properties/downloadedpiecesbar.cpp | 16 +- src/gui/properties/pieceavailabilitybar.cpp | 12 +- src/gui/properties/propertieswidget.cpp | 34 +++ src/gui/properties/propertieswidget.h | 4 + src/gui/theme/builtinthemes.qrc | 7 + src/gui/theme/colorprovider_p.cpp | 69 +++++ src/gui/theme/colorprovider_p.h | 78 +++++ src/gui/theme/colorproviders.cpp | 186 ++++++++++++ src/gui/theme/colorproviders.h | 130 ++++++++ src/gui/theme/colortheme.cpp | 38 +++ src/gui/theme/colortheme.h | 81 +++++ src/gui/theme/fontprovider_p.cpp | 48 +++ src/gui/theme/fontprovider_p.h | 63 ++++ src/gui/theme/fontproviders.cpp | 107 +++++++ src/gui/theme/fontproviders.h | 67 +++++ src/gui/theme/fonttheme.cpp | 38 +++ src/gui/theme/fonttheme.h | 59 ++++ src/gui/theme/provider_p.cpp | 30 ++ src/gui/theme/provider_p.h | 168 +++++++++++ src/gui/theme/qBittorrent.fonttheme | 8 + src/gui/theme/qBittorrentDark.colortheme | 27 ++ src/gui/theme/qBittorrentLight.colortheme | 37 +++ src/gui/theme/serializablecolortheme.cpp | 310 ++++++++++++++++++++ src/gui/theme/serializablecolortheme.h | 99 +++++++ src/gui/theme/serializablefonttheme.cpp | 57 ++++ src/gui/theme/serializablefonttheme.h | 58 ++++ src/gui/theme/serializabletheme.cpp | 138 +++++++++ src/gui/theme/serializabletheme.h | 156 ++++++++++ src/gui/theme/themecommon.cpp | 38 +++ src/gui/theme/themecommon.h | 47 +++ src/gui/theme/themeexceptions.cpp | 87 ++++++ src/gui/theme/themeexceptions.h | 101 +++++++ src/gui/theme/themeinfo.cpp | 156 ++++++++++ src/gui/theme/themeinfo.h | 112 +++++++ src/gui/theme/themeprovider.cpp | 266 +++++++++++++++++ src/gui/theme/themeprovider.h | 123 ++++++++ src/gui/torrentmodel.cpp | 76 +---- src/gui/transferlistwidget.cpp | 16 + src/gui/transferlistwidget.h | 3 + 50 files changed, 3531 insertions(+), 112 deletions(-) create mode 100644 src/gui/theme/builtinthemes.qrc create mode 100644 src/gui/theme/colorprovider_p.cpp create mode 100644 src/gui/theme/colorprovider_p.h create mode 100644 src/gui/theme/colorproviders.cpp create mode 100644 src/gui/theme/colorproviders.h create mode 100644 src/gui/theme/colortheme.cpp create mode 100644 src/gui/theme/colortheme.h create mode 100644 src/gui/theme/fontprovider_p.cpp create mode 100644 src/gui/theme/fontprovider_p.h create mode 100644 src/gui/theme/fontproviders.cpp create mode 100644 src/gui/theme/fontproviders.h create mode 100644 src/gui/theme/fonttheme.cpp create mode 100644 src/gui/theme/fonttheme.h create mode 100644 src/gui/theme/provider_p.cpp create mode 100644 src/gui/theme/provider_p.h create mode 100644 src/gui/theme/qBittorrent.fonttheme create mode 100644 src/gui/theme/qBittorrentDark.colortheme create mode 100644 src/gui/theme/qBittorrentLight.colortheme create mode 100644 src/gui/theme/serializablecolortheme.cpp create mode 100644 src/gui/theme/serializablecolortheme.h create mode 100644 src/gui/theme/serializablefonttheme.cpp create mode 100644 src/gui/theme/serializablefonttheme.h create mode 100644 src/gui/theme/serializabletheme.cpp create mode 100644 src/gui/theme/serializabletheme.h create mode 100644 src/gui/theme/themecommon.cpp create mode 100644 src/gui/theme/themecommon.h create mode 100644 src/gui/theme/themeexceptions.cpp create mode 100644 src/gui/theme/themeexceptions.h create mode 100644 src/gui/theme/themeinfo.cpp create mode 100644 src/gui/theme/themeinfo.h create mode 100644 src/gui/theme/themeprovider.cpp create mode 100644 src/gui/theme/themeprovider.h diff --git a/src/app/application.cpp b/src/app/application.cpp index 2eae2b0878..8ede4d68c7 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -37,6 +37,9 @@ #ifndef DISABLE_GUI #include "gui/guiiconprovider.h" +#include "gui/theme/colorproviders.h" +#include "gui/theme/fontproviders.h" +#include "gui/theme/themeprovider.h" #ifdef Q_OS_WIN #include #include @@ -466,9 +469,14 @@ int Application::exec(const QStringList ¶ms) { Net::ProxyConfigurationManager::initInstance(); Net::DownloadManager::initInstance(); + #ifdef DISABLE_GUI IconProvider::initInstance(); #else + Theme::Serialization::registerColorProviders(); + Theme::Serialization::registerFontProviders(); + Theme::ThemeProvider::initInstance(); + GuiIconProvider::initInstance(); #endif diff --git a/src/base/logger.h b/src/base/logger.h index 441a7408b0..7802231ea0 100644 --- a/src/base/logger.h +++ b/src/base/logger.h @@ -10,7 +10,7 @@ const int MAX_LOG_MESSAGES = 20000; namespace Log { - enum MsgType + enum MsgType: int { ALL = -1, NORMAL = 0x1, diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index e4bfce773d..6b08e0c04a 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -74,6 +74,20 @@ transferlistfilterswidget.h transferlistsortmodel.h transferlistwidget.h updownratiodlg.h +theme/colorprovider_p.h +theme/colorproviders.h +theme/colortheme.h +theme/fontprovider_p.h +theme/fontproviders.h +theme/fonttheme.h +theme/provider_p.h +theme/serializabletheme.h +theme/serializablecolortheme.h +theme/serializablefonttheme.h +theme/themecommon.h +theme/themeexceptions.h +theme/themeinfo.h +theme/themeprovider.h ) set(QBT_GUI_SOURCES @@ -118,6 +132,20 @@ transferlistfilterswidget.cpp transferlistsortmodel.cpp transferlistwidget.cpp updownratiodlg.cpp +theme/colorprovider_p.cpp +theme/colorproviders.cpp +theme/colortheme.cpp +theme/fonttheme.cpp +theme/fontprovider_p.cpp +theme/fontproviders.cpp +theme/provider_p.cpp +theme/serializabletheme.cpp +theme/serializablecolortheme.cpp +theme/serializablefonttheme.cpp +theme/themecommon.cpp +theme/themeexceptions.cpp +theme/themeinfo.cpp +theme/themeprovider.cpp ) if (APPLE) @@ -151,7 +179,7 @@ torrentcreatordlg.ui shutdownconfirmdlg.ui ) -qbt_target_sources(about.qrc) +qbt_target_sources(about.qrc theme/builtinthemes.qrc) add_library(qbt_gui STATIC ${QBT_GUI_HEADERS} ${QBT_GUI_SOURCES} ${QBT_GUI_FORMS}) target_link_libraries(qbt_gui qbt_lineedit qbt_powermanagement qbt_rss qbt_properties qbt_searchengine diff --git a/src/gui/executionlog.cpp b/src/gui/executionlog.cpp index b286f0ed47..cf46751862 100644 --- a/src/gui/executionlog.cpp +++ b/src/gui/executionlog.cpp @@ -28,15 +28,19 @@ * Contact : chris@qbittorrent.org */ +#include "executionlog.h" + #include #include #include #include #include -#include "executionlog.h" -#include "ui_executionlog.h" + #include "guiiconprovider.h" #include "loglistwidget.h" +#include "theme/colortheme.h" + +#include "ui_executionlog.h" ExecutionLog::ExecutionLog(QWidget *parent, const Log::MsgTypes &types) : QWidget(parent) @@ -75,39 +79,39 @@ void ExecutionLog::showMsgTypes(const Log::MsgTypes &types) m_msgList->showMsgTypes(types); } -void ExecutionLog::addLogMessage(const Log::Msg &msg) +namespace { - QString text; - QDateTime time = QDateTime::fromMSecsSinceEpoch(msg.timestamp); - QColor color; - - switch (msg.type) { - case Log::INFO: - color.setNamedColor("blue"); - break; - case Log::WARNING: - color.setNamedColor("orange"); - break; - case Log::CRITICAL: - color.setNamedColor("red"); - break; - default: - color = QApplication::palette().color(QPalette::WindowText); + QString coloredString(const QString &str, const QColor &color) + { + return QString(QLatin1String("%2")) + .arg(color.name(), str); } +} + +void ExecutionLog::addLogMessage(const Log::Msg &msg) +{ + const QDateTime time = QDateTime::fromMSecsSinceEpoch(msg.timestamp); + const QColor messageColor = Theme::ColorTheme::current().logMessageColor(msg.type); + const QColor neutralColor = QPalette().color(QPalette::Inactive, QPalette::WindowText); - text = "" + time.toString(Qt::SystemLocaleShortDate) + " - " + msg.message + ""; + QString text = coloredString(time.toString(Qt::SystemLocaleShortDate), neutralColor) + + QLatin1String(" - ") + + coloredString(msg.message, messageColor); m_msgList->appendLine(text, msg.type); } -void ExecutionLog::addPeerMessage(const Log::Peer& peer) +void ExecutionLog::addPeerMessage(const Log::Peer &peer) { - QString text; - QDateTime time = QDateTime::fromMSecsSinceEpoch(peer.timestamp); + const QDateTime time = QDateTime::fromMSecsSinceEpoch(peer.timestamp); + const QColor IPColor = Theme::ColorTheme::current().logMessageColor(Log::MsgType::CRITICAL); + const QColor neutralColor = QPalette().color(QPalette::Inactive, QPalette::WindowText); + QString text = coloredString(time.toString(Qt::SystemLocaleShortDate), neutralColor) + + QLatin1String(" - ") + coloredString(peer.ip, IPColor) + QLatin1Char(' '); if (peer.blocked) - text = "" + time.toString(Qt::SystemLocaleShortDate) + " - " + tr("%1 was blocked %2", "x.y.z.w was blocked").arg(peer.ip).arg(peer.reason); + text += tr("was blocked %1", "x.y.z.w was blocked").arg(peer.reason); else - text = "" + time.toString(Qt::SystemLocaleShortDate) + " - " + tr("%1 was banned", "x.y.z.w was banned").arg(peer.ip); + text += tr("was banned", "x.y.z.w was banned"); m_peerList->appendLine(text, Log::NORMAL); } diff --git a/src/gui/gui.pri b/src/gui/gui.pri index 6a80504038..59675b0729 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -63,6 +63,20 @@ HEADERS += \ $$PWD/fspathedit.h \ $$PWD/fspathedit_p.h \ $$PWD/previewselectdialog.h \ + $$PWD/theme/colorprovider_p.h \ + $$PWD/theme/colorproviders.h \ + $$PWD/theme/colortheme.h \ + $$PWD/theme/fontprovider_p.h \ + $$PWD/theme/fontproviders.h \ + $$PWD/theme/fonttheme.h \ + $$PWD/theme/provider_p.h \ + $$PWD/theme/serializabletheme.h \ + $$PWD/theme/serializablecolortheme.h \ + $$PWD/theme/serializablefonttheme.h \ + $$PWD/theme/themecommon.h \ + $$PWD/theme/themeexceptions.h \ + $$PWD/theme/themeinfo.h \ + $$PWD/theme/themeprovider.h \ SOURCES += \ $$PWD/mainwindow.cpp \ @@ -117,6 +131,20 @@ SOURCES += \ $$PWD/fspathedit.cpp \ $$PWD/fspathedit_p.cpp \ $$PWD/previewselectdialog.cpp \ + $$PWD/theme/colorprovider_p.cpp \ + $$PWD/theme/colortheme.cpp \ + $$PWD/theme/fonttheme.cpp \ + $$PWD/theme/fontprovider_p.cpp \ + $$PWD/theme/colorproviders.cpp \ + $$PWD/theme/fontproviders.cpp \ + $$PWD/theme/provider_p.cpp \ + $$PWD/theme/serializabletheme.cpp \ + $$PWD/theme/serializablecolortheme.cpp \ + $$PWD/theme/serializablefonttheme.cpp \ + $$PWD/theme/themecommon.cpp \ + $$PWD/theme/themeexceptions.cpp \ + $$PWD/theme/themeinfo.cpp \ + $$PWD/theme/themeprovider.cpp \ win32|macx { HEADERS += $$PWD/programupdater.h @@ -154,4 +182,6 @@ FORMS += \ $$PWD/rss/automatedrssdownloader.ui \ $$PWD/torrentcategorydialog.ui -RESOURCES += $$PWD/about.qrc +RESOURCES += \ + $$PWD/about.qrc \ + $$PWD/theme/builtinthemes.qrc diff --git a/src/gui/loglistwidget.cpp b/src/gui/loglistwidget.cpp index c6a71f65c6..82ea86e141 100644 --- a/src/gui/loglistwidget.cpp +++ b/src/gui/loglistwidget.cpp @@ -26,16 +26,22 @@ * exception statement from your version. * * Contact : chris@qbittorrent.org - */ -#include +*/ + +#include "loglistwidget.h" + +#include #include #include -#include +#include +#include #include +#include #include -#include -#include "loglistwidget.h" + #include "guiiconprovider.h" +#include "theme/fonttheme.h" +#include "theme/themeprovider.h" LogListWidget::LogListWidget(int maxLines, const Log::MsgTypes &types, QWidget *parent) : QListWidget(parent) @@ -52,6 +58,9 @@ LogListWidget::LogListWidget(int maxLines, const Log::MsgTypes &types, QWidget * addAction(copyAct); addAction(clearAct); setContextMenuPolicy(Qt::ActionsContextMenu); + + connect(&Theme::ThemeProvider::instance(), &Theme::ThemeProvider::fontThemeChanged, + this, &LogListWidget::applyFontTheme); } void LogListWidget::showMsgTypes(const Log::MsgTypes &types) @@ -74,11 +83,23 @@ void LogListWidget::keyPressEvent(QKeyEvent *event) selectAll(); } +void LogListWidget::applyFontTheme() +{ + QFont font = Theme::FontTheme::current().font(Theme::FontThemeElement::ExecutionLog); + for (int row = 0; row < count(); ++row) { + QListWidgetItem *item = this->item(row); + QLabel *label = static_cast(this->itemWidget(item)); + label->setFont(font); + item->setSizeHint(label->sizeHint()); + } +} + void LogListWidget::appendLine(const QString &line, const Log::MsgType &type) { QListWidgetItem *item = new QListWidgetItem; // We need to use QLabel here to support rich text QLabel *lbl = new QLabel(line); + lbl->setFont(Theme::FontTheme::current().font(Theme::FontThemeElement::ExecutionLog)); lbl->setContentsMargins(4, 2, 4, 2); item->setSizeHint(lbl->sizeHint()); item->setData(Qt::UserRole, type); diff --git a/src/gui/loglistwidget.h b/src/gui/loglistwidget.h index 46147f2047..052779767d 100644 --- a/src/gui/loglistwidget.h +++ b/src/gui/loglistwidget.h @@ -55,6 +55,9 @@ protected slots: protected: void keyPressEvent(QKeyEvent *event); +private slots: + void applyFontTheme(); + private: int m_maxLines; Log::MsgTypes m_types; diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index f923729ac5..9f850cc499 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -103,6 +103,7 @@ #include "lineedit.h" #include "executionlog.h" #include "hidabletabwidget.h" + #include "ui_mainwindow.h" #ifdef Q_OS_MAC diff --git a/src/gui/optionsdlg.cpp b/src/gui/optionsdlg.cpp index 1f5f1b72c4..153d678888 100644 --- a/src/gui/optionsdlg.cpp +++ b/src/gui/optionsdlg.cpp @@ -30,7 +30,9 @@ #include "optionsdlg.h" +#include #include +#include #include #include @@ -64,12 +66,115 @@ #include "addnewtorrentdialog.h" #include "advancedsettings.h" #include "rss/automatedrssdownloader.h" +#include "theme/themeexceptions.h" +#include "theme/themeinfo.h" +#include "theme/themeprovider.h" #include "banlistoptions.h" #include "guiiconprovider.h" #include "scanfoldersdelegate.h" #include "ui_optionsdlg.h" +namespace +{ + /** + * @brief Implements list model for themes of the given kind + * + * The class gets map of the themes from ThemeProvider, converts it into array sorting + * by theme localized name. + */ + class ThemeInfoListModel: public QAbstractListModel + { + public: + ThemeInfoListModel(Theme::Kind kind, QObject *parent); + + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + + struct Entry + { + Theme::ThemeInfo info; + QString filePath; + }; + + const Entry &entry(int index) const; + int indexForTheme(const Theme::ThemeInfo &info); + + private: + std::vector m_entries; + }; + + ThemeInfoListModel::ThemeInfoListModel(Theme::Kind kind, QObject *parent) + : QAbstractListModel(parent) + { + std::map themes = Theme::ThemeProvider::instance().availableThemes(kind); + + for (const auto &pair: themes) + m_entries.push_back({pair.first, pair.second}); + + std::sort(m_entries.begin(), m_entries.end(), [](const Entry &left, const Entry &right) + { + return left.info.localizedName() < right.info.localizedName(); + }); + } + + int ThemeInfoListModel::rowCount(const QModelIndex &/*parent*/) const + { + return static_cast(m_entries.size()); + } + + QVariant ThemeInfoListModel::data(const QModelIndex &index, int role) const + { + if ((index.row() >= static_cast(m_entries.size())) || (index.column() > 0)) return {}; + + switch (role) { + case Qt::DisplayRole: + return entry(index.row()).info.localizedName(); + case Qt::ToolTipRole: + return entry(index.row()).info.localizedDescription(); + } + + return {}; + } + + const ThemeInfoListModel::Entry &ThemeInfoListModel::entry(int index) const + { + return m_entries.at(static_cast(index)); + } + + int ThemeInfoListModel::indexForTheme(const Theme::ThemeInfo& info) + { + auto i = std::find_if(m_entries.begin(), m_entries.end(), [&info](const Entry &entry) + { + return (entry.info == info); + }); + if (i == m_entries.end()) { + qDebug() << "Could not find theme info in the model"; + return 0; // don't want to crash, will lead to theme re-appliance most likely + } + return std::distance(m_entries.begin(), i); + } + + //just a shortcut + const ThemeInfoListModel::Entry &themeEntry(QComboBox *comboBox, int index = -1) + { + if (index < 0) { + index = comboBox->currentIndex(); + } + return static_cast(comboBox->model())->entry(index); + } + + QString descriptionString(const ThemeInfoListModel::Entry &entry) + { + QString res = entry.info.localizedDescription() + QLatin1Char('\n'); + if (entry.filePath.startsWith(QLatin1String(":/"))) // this theme is located in resources + res += QObject::tr("Built-in theme"); + else + res += QObject::tr("Located in: ") + entry.filePath; + return res; + } +} + // Constructor OptionsDialog::OptionsDialog(QWidget *parent) : QDialog(parent) @@ -140,6 +245,17 @@ OptionsDialog::OptionsDialog(QWidget *parent) // Hide the Appearance/Desktop section if it doesn't contain any visible children. m_ui->groupBoxAppearanceDesktop->setHidden(m_ui->groupBoxAppearanceDesktop->childrenRect().isEmpty()); + ThemeInfoListModel *colorThemeModel = new ThemeInfoListModel(Theme::Kind::Color, this); + m_ui->comboBoxColorTheme->setModel(colorThemeModel); + const Theme::ThemeInfo currentColorTheme = Theme::ThemeProvider::instance().currentTheme(Theme::Kind::Color); + m_ui->comboBoxColorTheme->setCurrentIndex(colorThemeModel->indexForTheme(currentColorTheme)); + m_ui->labelColorThemeDescription->setText(descriptionString(themeEntry(m_ui->comboBoxColorTheme, -1))); + ThemeInfoListModel *fontThemeModel = new ThemeInfoListModel(Theme::Kind::Font, this); + m_ui->comboBoxFontTheme->setModel(fontThemeModel); + const Theme::ThemeInfo currentFontTheme = Theme::ThemeProvider::instance().currentTheme(Theme::Kind::Font); + m_ui->comboBoxFontTheme->setCurrentIndex(fontThemeModel->indexForTheme(currentFontTheme)); + m_ui->labelFontThemeDescription->setText(descriptionString(themeEntry(m_ui->comboBoxFontTheme, -1))); + m_ui->scanFoldersView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); m_ui->scanFoldersView->setModel(ScanFoldersModel::instance()); m_ui->scanFoldersView->setItemDelegate(new ScanFoldersDelegate(this, m_ui->scanFoldersView)); @@ -185,12 +301,14 @@ OptionsDialog::OptionsDialog(QWidget *parent) // Shortcuts for frequently used signals that have more than one overload. They would require // type casts and that is why we declare required member pointer here instead. void (QComboBox::*qComboBoxCurrentIndexChanged)(int) = &QComboBox::currentIndexChanged; + void (QComboBox::*qComboBoxActivated)(int) = &QComboBox::activated; void (QSpinBox::*qSpinBoxValueChanged)(int) = &QSpinBox::valueChanged; connect(m_ui->comboProxyType, qComboBoxCurrentIndexChanged, this, &ThisType::enableProxy); connect(m_ui->checkRandomPort, &QAbstractButton::toggled, m_ui->spinPort, &ThisType::setDisabled); // Apply button is activated when a value is changed + // General tab connect(m_ui->comboI18n, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->confirmDeletion, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); @@ -230,6 +348,13 @@ OptionsDialog::OptionsDialog(QWidget *parent) connect(m_ui->spinFileLogSize, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); connect(m_ui->spinFileLogAge, qSpinBoxValueChanged, this, &ThisType::enableApplyButton); connect(m_ui->comboFileLogAgeType, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); + + // Appearance tab + connect(m_ui->comboBoxColorTheme, qComboBoxActivated, this, &ThisType::colorThemeActivated); + connect(m_ui->comboBoxFontTheme, qComboBoxActivated, this, &ThisType::fontThemeActivated); + connect(m_ui->toolButtonExportColorTheme, &QToolButton::clicked, this, &ThisType::exportColorTheme); + connect(m_ui->toolButtonExportFontTheme, &QToolButton::clicked, this, &ThisType::exportFontTheme); + // Downloads tab connect(m_ui->textSavePath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); connect(m_ui->checkUseSubcategories, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); @@ -502,6 +627,52 @@ void OptionsDialog::saveOptions() qApp->installTranslator(translator); } + // Appearance preferences + + const auto applyTheme = [this](Theme::Kind kind, const QString &themeName) + { + + const auto themeKindToString = [](Theme::Kind kind) + { + switch (kind) { + case Theme::Kind::Color: + return tr("color", "e.g. 'color theme'"); + case Theme::Kind::Font: + return tr("font", "e.g. 'font theme'"); + default: + return tr("unknown", "e.g. 'unknown theme'"); + } + }; + + using namespace Theme::Serialization; + QString errorMessage; + try { + Theme::ThemeProvider::instance().setCurrentTheme(kind, themeName); + return; + } + catch (ThemeElementMissing &ex) { + errorMessage = tr("theme element '%1' is missing").arg(ex.elementName()); + } + catch (ValueParsingError &ex) { + errorMessage = tr("could not parse element value '%1'").arg(ex.valueString()); + } + catch (ParsingError &ex) { + errorMessage = tr("Could not parse element '%1'").arg(ex.serializedValue()); + } + catch (UnknownProvider &ex) { + errorMessage = tr("theme element contains unknown scheme '%1'").arg(ex.profiderName()); + } + catch (DeserializationError &ex) { + errorMessage = tr("theme loading error '%1'").arg(QString::fromUtf8(ex.what())); + } + QMessageBox::warning(this, tr("Theme applying failed"), + tr("Could not apply %1 theme due to following error:\n%2") + .arg(themeKindToString(kind), errorMessage)); + }; + + applyTheme(Theme::Kind::Color, themeEntry(m_ui->comboBoxColorTheme).info.name()); + applyTheme(Theme::Kind::Font, themeEntry(m_ui->comboBoxFontTheme).info.name()); + // General preferences pref->setLocale(locale); pref->setConfirmTorrentDeletion(m_ui->confirmDeletion->isChecked()); @@ -1418,6 +1589,49 @@ void OptionsDialog::setLocale(const QString &localeStr) m_ui->comboI18n->setCurrentIndex(index); } +void OptionsDialog::colorThemeActivated(int index) +{ + m_ui->labelColorThemeDescription->setText( + descriptionString(themeEntry(m_ui->comboBoxColorTheme, index))); + enableApplyButton(); +} + +void OptionsDialog::fontThemeActivated(int index) +{ + m_ui->labelFontThemeDescription->setText( + descriptionString(themeEntry(m_ui->comboBoxFontTheme, index))); + enableApplyButton(); +} + +void OptionsDialog::exportColorTheme() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save theme as..."), + QDir::homePath(), + tr("qBittorrent color theme") + + QLatin1String(" (*") + Theme::ThemeProvider::colorThemeFileExtension + QLatin1Char(')')); + if (!fileName.isEmpty()) { + Theme::ThemeProvider::instance().exportTheme(Theme::Kind::Color, + themeEntry(m_ui->comboBoxColorTheme, -1).info.name(), fileName); + } +} + +void OptionsDialog::exportFontTheme() +{ + QString fileName = QFileDialog::getSaveFileName(this, tr("Save theme as..."), + QDir::homePath(), + tr("qBittorrent font theme") + + QLatin1String(" (*") + Theme::ThemeProvider::fontThemeFileExtension + QLatin1Char(')')); + if (!fileName.isEmpty()) { + const bool explicitFontStrings = QMessageBox::question(this, tr("Exporting theme"), + tr("Font theme might contain references to default fonts. Do you want to expand them" + " to their actual values?")) == QMessageBox::Yes; + Theme::ThemeProvider::instance().exportTheme(Theme::Kind::Font, + themeEntry(m_ui->comboBoxFontTheme, -1).info.name(), fileName, + explicitFontStrings ? Theme::ThemeProvider::ExportOption::WriteExplicitValues + : Theme::ThemeProvider::ExportOption::NoOptions); + } +} + QString OptionsDialog::getTorrentExportDir() const { if (m_ui->checkExportDir->isChecked()) diff --git a/src/gui/optionsdlg.h b/src/gui/optionsdlg.h index ea438556c1..67aadbaf85 100644 --- a/src/gui/optionsdlg.h +++ b/src/gui/optionsdlg.h @@ -106,7 +106,11 @@ private slots: void on_btnWebUiCrt_clicked(); void on_btnWebUiKey_clicked(); void on_registerDNSBtn_clicked(); - void setLocale(const QString &localeStr); + void setLocale(const QString &locale); + void colorThemeActivated(int index); + void fontThemeActivated(int index); + void exportColorTheme(); + void exportFontTheme(); private: // Methods diff --git a/src/gui/optionsdlg.ui b/src/gui/optionsdlg.ui index 6f2164cfb8..d980f10143 100644 --- a/src/gui/optionsdlg.ui +++ b/src/gui/optionsdlg.ui @@ -231,6 +231,113 @@ + + + + Themes + + + + + + Color theme: + + + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + Export color theme into a file + + + ... + + + + .. + + + + + + + + + Font theme: + + + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + TextLabel + + + + + + + Export font theme into a file + + + ... + + + + .. + + + + + + + + @@ -280,8 +387,8 @@ 0 0 - 504 - 849 + 448 + 887 @@ -3250,7 +3357,6 @@ Use ';' to split multiple entries. Can use wildcard '*'. tabOption textSavePath - browseSaveDirButton checkStartPaused spinPort checkUPnP diff --git a/src/gui/properties/downloadedpiecesbar.cpp b/src/gui/properties/downloadedpiecesbar.cpp index 4ecdb82f90..87465f5df2 100644 --- a/src/gui/properties/downloadedpiecesbar.cpp +++ b/src/gui/properties/downloadedpiecesbar.cpp @@ -34,6 +34,8 @@ #include +#include "theme/colortheme.h" + DownloadedPiecesBar::DownloadedPiecesBar(QWidget *parent) : base {parent} , m_dlPieceColor {0, 0xd0, 0} @@ -174,7 +176,15 @@ void DownloadedPiecesBar::clear() QString DownloadedPiecesBar::simpleToolTipText() const { - return tr("White: Missing pieces") + '\n' - + tr("Green: Partial pieces") + '\n' - + tr("Blue: Completed pieces") + '\n'; + return QString(QLatin1String(R"()" + R"()" + R"()" + R"()" + R"(
     : %2
     : %4
     : %6
)")) + .arg(Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Background).name()) + .arg(tr("Missing pieces")) + .arg(Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Incomplete).name()) + .arg(tr("Partial pieces")) + .arg(Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Complete).name()) + .arg(tr("Completed pieces")); } diff --git a/src/gui/properties/pieceavailabilitybar.cpp b/src/gui/properties/pieceavailabilitybar.cpp index 0ce3f2618c..1b91f55c0c 100644 --- a/src/gui/properties/pieceavailabilitybar.cpp +++ b/src/gui/properties/pieceavailabilitybar.cpp @@ -34,6 +34,8 @@ #include +#include "theme/colortheme.h" + PieceAvailabilityBar::PieceAvailabilityBar(QWidget *parent) : base {parent} { @@ -160,8 +162,14 @@ void PieceAvailabilityBar::clear() QString PieceAvailabilityBar::simpleToolTipText() const { - return tr("White: Unavailable pieces") + '\n' - + tr("Blue: Available pieces") + '\n'; + return QString(QLatin1String(R"()" + R"()" + R"()" + R"(
     : %2
     : %4
)")) + .arg(Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Background).name()) + .arg(tr("Unavailable pieces")) + .arg(Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Complete).name()) + .arg(tr("Available pieces")); } bool PieceAvailabilityBar::isFileNameCorrectionNeeded() const diff --git a/src/gui/properties/propertieswidget.cpp b/src/gui/properties/propertieswidget.cpp index 16ed3be331..af8b056242 100644 --- a/src/gui/properties/propertieswidget.cpp +++ b/src/gui/properties/propertieswidget.cpp @@ -53,6 +53,9 @@ #include "downloadedpiecesbar.h" #include "guiiconprovider.h" #include "lineedit.h" +#include "theme/colortheme.h" +#include "theme/fonttheme.h" +#include "theme/themeprovider.h" #include "mainwindow.h" #include "messageboxraised.h" #include "peerlistwidget.h" @@ -168,6 +171,14 @@ PropertiesWidget::PropertiesWidget(QWidget *parent, MainWindow *main_window, Tra connect(deleteHotkeyWeb, SIGNAL(activated()), SLOT(deleteSelectedUrlSeeds())); openHotkeyFile = new QShortcut(Qt::Key_Return, m_ui->filesList, 0, 0, Qt::WidgetShortcut); connect(openHotkeyFile, SIGNAL(activated()), SLOT(openSelectedFile())); + + applyColorTheme(); + applyFontTheme(); + + connect(&Theme::ThemeProvider::instance(), &Theme::ThemeProvider::colorThemeChanged, + this, &PropertiesWidget::applyColorTheme); + connect(&Theme::ThemeProvider::instance(), &Theme::ThemeProvider::fontThemeChanged, + this, &PropertiesWidget::applyFontTheme); } PropertiesWidget::~PropertiesWidget() @@ -895,3 +906,26 @@ void PropertiesWidget::filterText(const QString &filter) m_ui->filesList->expandAll(); } } + +void PropertiesWidget::applyColorTheme() +{ + downloaded_pieces->setColors( + Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Background), + Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Border), + Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Complete), + Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Incomplete)); + pieces_availability->setColors( + Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Background), + Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Border), + Theme::ColorTheme::current().downloadProgressBarColor(Theme::DownloadProgressBarElement::Complete)); +} + +void PropertiesWidget::applyFontTheme() +{ + QFont font = Theme::FontTheme::current().font(Theme::FontThemeElement::TorrentProperties); + foreach (QWidget *widget, findChildren()) + widget->setFont(font); + + foreach (QWidget *widget, findChildren()) + widget->setFont(font); +} diff --git a/src/gui/properties/propertieswidget.h b/src/gui/properties/propertieswidget.h index 9bfefe10c2..05eec1685d 100644 --- a/src/gui/properties/propertieswidget.h +++ b/src/gui/properties/propertieswidget.h @@ -111,6 +111,10 @@ protected slots: void renameSelectedFile(); void openSelectedFile(); +private slots: + void applyColorTheme(); + void applyFontTheme(); + private: void openFile(const QModelIndex &index); void openFolder(const QModelIndex &index, bool containing_folder); diff --git a/src/gui/theme/builtinthemes.qrc b/src/gui/theme/builtinthemes.qrc new file mode 100644 index 0000000000..7e2e3f57f5 --- /dev/null +++ b/src/gui/theme/builtinthemes.qrc @@ -0,0 +1,7 @@ + + + qBittorrentLight.colortheme + qBittorrentDark.colortheme + qBittorrent.fonttheme + + diff --git a/src/gui/theme/colorprovider_p.cpp b/src/gui/theme/colorprovider_p.cpp new file mode 100644 index 0000000000..e312b0de06 --- /dev/null +++ b/src/gui/theme/colorprovider_p.cpp @@ -0,0 +1,69 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "colorprovider_p.h" + +#include + +// -------------------------- Color ----------------------------------------------- + +QString Theme::Serialization::Color::explicitSerializedValue() const +{ + return value().name(QColor::HexRgb); +} + +// ------------------------- ColorsProviderRegistry ------------------------------ + +namespace +{ + class ColorsProviderRegistrySignletonImpl: public Theme::Serialization::ColorsProviderRegistry + { + public: + ~ColorsProviderRegistrySignletonImpl() = default; + }; + + Q_GLOBAL_STATIC(ColorsProviderRegistrySignletonImpl, colorsProviderRegistrySignletonImpl) +} + +Theme::Serialization::ColorsProviderRegistry &Theme::Serialization::ColorsProviderRegistry::instance() +{ + return *colorsProviderRegistrySignletonImpl(); +} + +void Theme::Serialization::ColorsProviderRegistry::applicationPaletteChanged() const +{ + for (const auto& providerPair: providers()) { + providerPair.second->applicationPaletteChanged(); + } +} + +// ------------------------- ColorProvider ------------------------------ + +void Theme::Serialization::ColorProvider::applicationPaletteChanged() const +{ +} diff --git a/src/gui/theme/colorprovider_p.h b/src/gui/theme/colorprovider_p.h new file mode 100644 index 0000000000..3f900c9c31 --- /dev/null +++ b/src/gui/theme/colorprovider_p.h @@ -0,0 +1,78 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_COLORPROVIDER_P_H +#define QBT_THEME_COLORPROVIDER_P_H + +#include "provider_p.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Theme +{ + namespace Serialization + { + class ColorDeserializationError: public DeserializationError + { + public: + using DeserializationError::DeserializationError; + }; + + class Color : public Entity + { + public: + QString explicitSerializedValue() const override; + }; + + class ColorProvider: public Provider + { + public: + using Provider::Provider; + virtual void applicationPaletteChanged() const; + }; + + class ColorsProviderRegistry: public ProviderRegistry + { + public: + static const Kind kind = Kind::Color; + + static ColorsProviderRegistry &instance(); + void applicationPaletteChanged() const; + }; + } +} + +#endif // QBT_COLORPROVIDER_P_H diff --git a/src/gui/theme/colorproviders.cpp b/src/gui/theme/colorproviders.cpp new file mode 100644 index 0000000000..60bdf0c5fd --- /dev/null +++ b/src/gui/theme/colorproviders.cpp @@ -0,0 +1,186 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "colorproviders.h" + +#include + +namespace +{ + struct ColorProvidersRegistrator + { + ColorProvidersRegistrator() + { + using Registry = Theme::Serialization::ColorsProviderRegistry; + using ProviderUPtr = Registry::ProviderUPtr; + + Registry::instance().registerProvider(ProviderUPtr(new Theme::Serialization::ExplicitColorProvider())); + Registry::instance().registerProvider(ProviderUPtr(new Theme::Serialization::PaletteColorProvider())); + } + }; + + const QMetaEnum &QPaletteGroupMeta() + { + static QMetaEnum res = QMetaEnum::fromType(); + return res; + } + + const QMetaEnum &QPaletteRoleMeta() + { + static QMetaEnum res = QMetaEnum::fromType(); + return res; + } +} + +void Theme::Serialization::registerColorProviders() +{ + static ColorProvidersRegistrator colorProvidersRegistrator; +} + +Theme::Serialization::ExplicitColor::ExplicitColor(const QColor &color) + : m_value {color} +{ +} + +/* ExplicitColor is just what it means: a single QColor value. + * It is serialized into a string formatted as follows: ,,, e.g.: 127,234,12 + */ +Theme::Serialization::ExplicitColor::ExplicitColor(const QString &serialized) + : m_value {QColor(serialized)} +{ + if (!m_value.isValid()) { + throw ValueParsingError("QColor could not recognize color string", serialized); + } +} + +QColor Theme::Serialization::ExplicitColor::value() const +{ + return m_value; +} + +QString Theme::Serialization::ExplicitColor::serializedValue() const +{ + return explicitSerializedValue(); +} + +QString Theme::Serialization::ExplicitColor::serializationKey() const +{ + return QLatin1String("RGB"); +} + +QPalette Theme::Serialization::PaletteColor::m_palette; + +Theme::Serialization::PaletteColor::PaletteColor(QPalette::ColorGroup group, QPalette::ColorRole role) + : m_group(group) + , m_role(role) +{ +} + +Theme::Serialization::PaletteColor::PaletteColor(const QString &serialized) +{ + const auto list = serialized.split(QLatin1Char(':')); + if (list.size() != 2) + throw ValueParsingError("QPalette color notation should have 2 components", serialized); + + bool parsedOk = false; + const int groupRawVal = QPaletteGroupMeta().keyToValue(list[0].toLatin1().constData(), &parsedOk); + if (!parsedOk) { + throw ValueParsingError("Could not parse QPalette group name", serialized); + } + m_group = static_cast(groupRawVal); + + const int roleRawVal = QPaletteRoleMeta().keyToValue(list[1].toLatin1().constData(), &parsedOk); + if (!parsedOk) { + throw ValueParsingError("Could not parse QPalette role name", serialized); + } + m_role = static_cast(roleRawVal); +} + +void Theme::Serialization::PaletteColor::reloadDefaultPalette() +{ + m_palette = QPalette(); // which asks QApplication instance for the current default palette +} + +QColor Theme::Serialization::PaletteColor::value() const +{ + return m_palette.color(m_group, m_role); +} + +QString Theme::Serialization::PaletteColor::serializedValue() const +{ + return QString(QLatin1String("%1:%2")) + .arg(QPaletteGroupMeta().key(m_group)).arg(QPaletteRoleMeta().key(m_role)); +} + +QString Theme::Serialization::PaletteColor::serializationKey() const +{ + return QLatin1String("QPalette"); +} + +void Theme::Serialization::PaletteColorProvider::applicationPaletteChanged() const +{ + PaletteColor::reloadDefaultPalette(); +} + +Theme::Serialization::ExplicitColorProvider::ExplicitColorProvider() + : ColorProvider(ExplicitColor(QColor(Qt::black)).serializationKey()) +{ +} + +Theme::Serialization::ExplicitColorProvider::EntityUPtr +Theme::Serialization::ExplicitColorProvider::load(const QString& serialized) const +{ + return EntityUPtr(new ExplicitColor(serialized)); +} + +Theme::Serialization::PaletteColorProvider::PaletteColorProvider() + : ColorProvider(PaletteColor(QPalette::Active, QPalette::Window).serializationKey()) +{ +} + +Theme::Serialization::PaletteColorProvider::EntityUPtr +Theme::Serialization::PaletteColorProvider::load(const QString& serialized) const +{ + return EntityUPtr(new PaletteColor(serialized)); +} + +Theme::Serialization::ColorProviderWidgetUI::~ColorProviderWidgetUI() = default; + +Theme::Serialization::ColorPickingWidget * +Theme::Serialization::ExplicitColorProvider::createEditorWidget(QWidget* parentWidget) const +{ + Q_UNUSED(parentWidget); + throw std::logic_error("Not implemented"); +} + +Theme::Serialization::ColorPickingWidget * +Theme::Serialization::PaletteColorProvider::createEditorWidget(QWidget* parentWidget) const +{ + Q_UNUSED(parentWidget); + throw std::logic_error("Not implemented"); +} diff --git a/src/gui/theme/colorproviders.h b/src/gui/theme/colorproviders.h new file mode 100644 index 0000000000..27b55dc653 --- /dev/null +++ b/src/gui/theme/colorproviders.h @@ -0,0 +1,130 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_COLORPROVIDERS_H +#define QBT_THEME_COLORPROVIDERS_H + +#include + +#include "colorprovider_p.h" + +namespace Theme +{ + namespace Serialization + { + void registerColorProviders(); + + class ExplicitColor: public Color + { + public: + explicit ExplicitColor(const QColor &color); + explicit ExplicitColor(const QString &serialized); + + QColor value() const override; + QString serializedValue() const override; + QString serializationKey() const override; + + private: + QColor m_value; + }; + + // links to a color from app default palette; + class PaletteColor: public Color + { + public: + explicit PaletteColor(QPalette::ColorGroup group, QPalette::ColorRole role); + explicit PaletteColor(const QString &serialized); + + QColor value() const override; + QString serializedValue() const override; + QString serializationKey() const override; + + static void reloadDefaultPalette(); + + private: + static QPalette m_palette; + QPalette::ColorGroup m_group; + QPalette::ColorRole m_role; + }; + + class ColorPickingWidget: public QWidget + { + public: + ColorPickingWidget(QWidget *parent); + + /** + * @brief ... + * + * @return may return nullptr + */ + virtual ColorProvider::EntityUPtr selectedColor() const = 0; + virtual void selectColor(const Color &color) = 0; + }; + + /*! \brief Interface provides Widget-based UI for color providers + * + * This interface may be used when a color theme is edited and user wants to + * select one of the supported colors using QWidget-based UI + */ + class ColorProviderWidgetUI + { + public: + virtual ~ColorProviderWidgetUI(); + virtual ColorPickingWidget *createEditorWidget(QWidget *parentWidget) const = 0; + }; + + namespace impl + { + class ExplicitColorWidget; + class PaletteColorWidget; + } + + class ExplicitColorProvider: public ColorProvider, public ColorProviderWidgetUI + { + public: + ExplicitColorProvider(); + + private: + ColorPickingWidget *createEditorWidget(QWidget *parentWidget) const override; + ColorProvider::EntityUPtr load(const QString &serialized) const override; + }; + + class PaletteColorProvider: public ColorProvider, public ColorProviderWidgetUI + { + public: + PaletteColorProvider(); + + private: + ColorPickingWidget *createEditorWidget(QWidget *parentWidget) const override; + ColorProvider::EntityUPtr load(const QString &serialized) const override; + void applicationPaletteChanged() const override; + }; + } +} + +#endif // QBT_THEME_COLORPROVIDERS_H diff --git a/src/gui/theme/colortheme.cpp b/src/gui/theme/colortheme.cpp new file mode 100644 index 0000000000..0759ded817 --- /dev/null +++ b/src/gui/theme/colortheme.cpp @@ -0,0 +1,38 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "colortheme.h" + +#include "themeprovider.h" + +Theme::ColorTheme::~ColorTheme() = default; + +const Theme::ColorTheme &Theme::ColorTheme::current() +{ + return ThemeProvider::instance().colorTheme(); +} diff --git a/src/gui/theme/colortheme.h b/src/gui/theme/colortheme.h new file mode 100644 index 0000000000..0efebaf5d2 --- /dev/null +++ b/src/gui/theme/colortheme.h @@ -0,0 +1,81 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_COLORTHEME_H +#define QBT_THEME_COLORTHEME_H + +#include + +#include +#include + +class QColor; +class QSettings; + +namespace BitTorrent +{ + enum class TorrentState; +} + +namespace Log +{ + enum MsgType: int; +} + +namespace Theme +{ + enum class DownloadProgressBarElement + { + Background, + Border, + Complete, + Incomplete + }; + + class ThemeInfo; + + /*! \brief qBittorrent color theme + * + * Contains all colors that are needed to render a qBt UI, either using widgets or Web + */ + class ColorTheme + { + public: + virtual ~ColorTheme(); + + virtual ThemeInfo info() const = 0; + + virtual QColor torrentStateColor(const BitTorrent::TorrentState state) const = 0; + virtual QColor logMessageColor(const Log::MsgType messageType) const = 0; + virtual QColor downloadProgressBarColor(const DownloadProgressBarElement element) const = 0; + + static const ColorTheme ¤t(); + }; +} + +#endif // QBT_THEME_COLORTHEME_H diff --git a/src/gui/theme/fontprovider_p.cpp b/src/gui/theme/fontprovider_p.cpp new file mode 100644 index 0000000000..4523655fa5 --- /dev/null +++ b/src/gui/theme/fontprovider_p.cpp @@ -0,0 +1,48 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "fontprovider_p.h" + +#include + +// ------------------------- FontProviderRegistry ------------------------------ +namespace +{ + class FontProviderRegistrySignletonImpl: public Theme::Serialization::FontProviderRegistry + { + public: + ~FontProviderRegistrySignletonImpl() = default; + }; + + Q_GLOBAL_STATIC(FontProviderRegistrySignletonImpl, fontProviderRegistrySignletonImpl) +} + +Theme::Serialization::FontProviderRegistry &Theme::Serialization::FontProviderRegistry::instance() +{ + return *fontProviderRegistrySignletonImpl(); +} diff --git a/src/gui/theme/fontprovider_p.h b/src/gui/theme/fontprovider_p.h new file mode 100644 index 0000000000..ebe5d80b14 --- /dev/null +++ b/src/gui/theme/fontprovider_p.h @@ -0,0 +1,63 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_FONTPROVIDER_P_H +#define QBT_THEME_FONTPROVIDER_P_H + +#include "provider_p.h" + +#include + +namespace Theme +{ + namespace Serialization + { + class FontDeserializationError: public DeserializationError + { + public: + using DeserializationError::DeserializationError; + }; + + using Font = Entity; + + class FontProvider: public Provider + { + public: + using Provider::Provider; + }; + + class FontProviderRegistry: public ProviderRegistry + { + public: + static const Kind kind = Kind::Font; + static FontProviderRegistry &instance(); + }; + } +} + +#endif // QBT_THEME_FONTPROVIDER_P_H diff --git a/src/gui/theme/fontproviders.cpp b/src/gui/theme/fontproviders.cpp new file mode 100644 index 0000000000..b82554d606 --- /dev/null +++ b/src/gui/theme/fontproviders.cpp @@ -0,0 +1,107 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "fontproviders.h" + +#include "themeexceptions.h" + +namespace +{ + struct FontProvidersRegistrator + { + FontProvidersRegistrator() + { + using Registry = Theme::Serialization::FontProviderRegistry; + using ProviderUPtr = Registry::ProviderUPtr; + + Registry::instance().registerProvider(ProviderUPtr(new Theme::Serialization::ExplicitFontProvider())); + } + }; +} + +void Theme::Serialization::registerFontProviders() +{ + static FontProvidersRegistrator fontProvidersRegistrator; +} + +Theme::Serialization::ExplicitFont::ExplicitFont(const QFont &color) + : m_value {color} +{ +} + +/* ExplicitFont is just what it means: a single QFont value. + * It is serialized into a string formatted as QFont::toString() + */ +Theme::Serialization::ExplicitFont::ExplicitFont(const QString &serialized) + : m_value {fromString(serialized)} +{ +} + +QFont Theme::Serialization::ExplicitFont::fromString(const QString &str) +{ + if (str.isEmpty()) { + // they want default app font + return QFont(); + } + QFont res; + if (!res.fromString(str)) { + throw ValueParsingError("QFont could not recognize font string", str); + } + return res; +} + +QFont Theme::Serialization::ExplicitFont::value() const +{ + return m_value; +} + +QString Theme::Serialization::ExplicitFont::explicitSerializedValue() const +{ + return m_value.toString(); +} + +QString Theme::Serialization::ExplicitFont::serializedValue() const +{ + return explicitSerializedValue(); +} + +QString Theme::Serialization::ExplicitFont::serializationKey() const +{ + return QLatin1String("QFont"); +} + +Theme::Serialization::ExplicitFontProvider::ExplicitFontProvider() + : FontProvider(ExplicitFont(QFont()).serializationKey()) +{ +} + +Theme::Serialization::ExplicitFontProvider::EntityUPtr +Theme::Serialization::ExplicitFontProvider::load(const QString& serialized) const +{ + return EntityUPtr(new ExplicitFont(serialized)); +} diff --git a/src/gui/theme/fontproviders.h b/src/gui/theme/fontproviders.h new file mode 100644 index 0000000000..5570777e8f --- /dev/null +++ b/src/gui/theme/fontproviders.h @@ -0,0 +1,67 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_GUIFONTPROVIDERS_H +#define QBT_THEME_GUIFONTPROVIDERS_H + +#include "fontprovider_p.h" + +namespace Theme +{ + namespace Serialization + { + void registerFontProviders(); + + class ExplicitFont: public Font + { + public: + explicit ExplicitFont(const QFont &color); + explicit ExplicitFont(const QString &serialized); + + QFont value() const override; + QString serializedValue() const override; + QString explicitSerializedValue() const override; + QString serializationKey() const override; + + private: + static QFont fromString(const QString &str); + QFont m_value; + }; + + class ExplicitFontProvider: public FontProvider + { + public: + ExplicitFontProvider(); + + private: + FontProvider::EntityUPtr load(const QString &serialized) const override; + }; + } +} + +#endif // QBT_THEME_GUIFONTPROVIDERS_H diff --git a/src/gui/theme/fonttheme.cpp b/src/gui/theme/fonttheme.cpp new file mode 100644 index 0000000000..a4893371bb --- /dev/null +++ b/src/gui/theme/fonttheme.cpp @@ -0,0 +1,38 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "fonttheme.h" + +#include "themeprovider.h" + +Theme::FontTheme::~FontTheme() = default; + +const Theme::FontTheme &Theme::FontTheme::current() +{ + return ThemeProvider::instance().fontTheme(); +} diff --git a/src/gui/theme/fonttheme.h b/src/gui/theme/fonttheme.h new file mode 100644 index 0000000000..1e64df777a --- /dev/null +++ b/src/gui/theme/fonttheme.h @@ -0,0 +1,59 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_FONTTHEME_H +#define QBT_THEME_FONTTHEME_H + +#include + +class QFont; + +namespace Theme +{ + class ThemeInfo; + + enum class FontThemeElement + { + TransferList, + TorrentProperties, + ExecutionLog + }; + + class FontTheme + { + public: + virtual ~FontTheme(); + + virtual const ThemeInfo &info() const = 0; + virtual const QFont &font(FontThemeElement element) const = 0; + + static const FontTheme ¤t(); + }; +} + +#endif // QBT_THEME_FONTTHEME_H diff --git a/src/gui/theme/provider_p.cpp b/src/gui/theme/provider_p.cpp new file mode 100644 index 0000000000..966d302f1b --- /dev/null +++ b/src/gui/theme/provider_p.cpp @@ -0,0 +1,30 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "provider_p.h" + diff --git a/src/gui/theme/provider_p.h b/src/gui/theme/provider_p.h new file mode 100644 index 0000000000..8ffd5499e3 --- /dev/null +++ b/src/gui/theme/provider_p.h @@ -0,0 +1,168 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_PROVIDER_P_H +#define QBT_THEME_PROVIDER_P_H + +#include +#include +#include +#include + +#include + +#include "themecommon.h" +#include "themeexceptions.h" + +namespace Theme +{ + namespace Serialization + { + /* + * Serialization: each serializable object shall be able to serialize itself into a QString value. + * To freely mix objects from different sources within a theme, they are serialized as ID:value pairs. + * For example: + * + * Background=RGB:128,128,125 + * Stalled=QPalette:Inactive,Midlight + * + * The value format is determined by the object, while : part is written and read + * by the managing code. + */ + + template + class Entity + { + public: + using ValueType = Value; + + virtual ~Entity() = default; + virtual Value value() const = 0; + virtual QString serializedValue() const = 0; + virtual QString explicitSerializedValue() const = 0; + virtual QString serializationKey() const = 0; + }; + + template + class Provider + { + public: + using EntityType = Entity; + using EntityUPtr = std::unique_ptr; + virtual ~Provider() = default; + QString name() const; + virtual EntityUPtr load(const QString &serialized) const = 0; + + protected: + Provider(const QString &name); + + private: + QString m_name; + }; + + template + class ProviderRegistry + { + public: + using ProviderType = Provider; + using ProviderUPtr = std::unique_ptr; + using EntityUPtr = typename ProviderType::EntityUPtr; + + void registerProvider(ProviderUPtr creator); + const ProviderType *provider(const QString &name) const; + EntityUPtr load(const QString &serializedWithKey) const; + + void applicationPaletteChanged() const; + + protected: + ~ProviderRegistry() = default; + + using ProvidersMap = std::map; + const ProvidersMap &providers() const; + + private: + ProvidersMap m_providers; + }; + + // ------------------------- implementation ------------------------------ + template + inline Provider::Provider(const QString &name) + : m_name(name) + { + } + + template + inline QString Provider::name() const + { + return m_name; + } + + template + inline void ProviderRegistry::registerProvider(ProviderUPtr creator) + { + const QString id = creator->name(); + Q_ASSERT_X(m_providers.count(id) == 0, Q_FUNC_INFO, + "Attempted to register the same theme color type twice"); + m_providers[id] = std::move(creator); + } + + template + inline const typename ProviderRegistry::ProviderType * + ProviderRegistry::provider(const QString &name) const + { + const auto i = m_providers.find(name); + if (i != m_providers.end()) + return i->second.get(); + return nullptr; + } + + template + inline typename ProviderRegistry::EntityUPtr + ProviderRegistry::load(const QString &serializedWithKey) const + { + const int keyValueSeparatorPos = serializedWithKey.indexOf(QLatin1Char(':'), 0); + if (keyValueSeparatorPos != -1) { + const QString id = serializedWithKey.left(keyValueSeparatorPos); + const auto *provider = this->provider(id); + if (provider) + return provider->load(serializedWithKey.right(serializedWithKey.size() - keyValueSeparatorPos - 1)); + throw UnknownProvider(serializedWithKey); + } + qCInfo(theme, "Failed to parse serialized value '%s'", qPrintable(serializedWithKey)); + throw ParsingError(serializedWithKey); + } + + template + const typename ProviderRegistry::ProvidersMap &ProviderRegistry::providers() const + { + return m_providers; + } + } +} + +#endif // QBT_THEME_PROVIDER_P_H diff --git a/src/gui/theme/qBittorrent.fonttheme b/src/gui/theme/qBittorrent.fonttheme new file mode 100644 index 0000000000..4a920d119a --- /dev/null +++ b/src/gui/theme/qBittorrent.fonttheme @@ -0,0 +1,8 @@ +[Info] +Name=Default +Description=Default qBittorrent font theme. + +[Fonts] +TransferList=QFont: +TorrentProperties=QFont: +ExecutionLog=QFont: diff --git a/src/gui/theme/qBittorrentDark.colortheme b/src/gui/theme/qBittorrentDark.colortheme new file mode 100644 index 0000000000..95c866f520 --- /dev/null +++ b/src/gui/theme/qBittorrentDark.colortheme @@ -0,0 +1,27 @@ +[Info] +Name=Default (Dark) +Description=Default qBittorrent color theme. Dark flavour. +Inherits=Default (Light) + +[TorrentState] +Uploading=RGB:#63b8ff +PausedUploading=RGB:#4f94cd +QueuedUploading=RGB:#00cdcd +StalledUploading=RGB:#cccccc +CheckingUploading=RGB:#00cdcd +ForcedUploading=RGB:#63b8ff +Allocating=RGB:#cccccc +Downloading=RGB:#32cd32 +DownloadingMetadata=RGB:#32cd32 +PausedDownloading=RGB:#fa8072 +QueuedDownloading=RGB:#00cdcd +StalledDownloading=RGB:#cccccc +CheckingDownloading=RGB:#00cdcd +ForcedDownloading=RGB:#32cd32 +QueuedForChecking=RGB:#00cdcd +CheckingResumeData=RGB:#00cdcd + +[LogMessageType] +INFO=RGB:lightblue +WARNING=RGB:lightsalmon +CRITICAL=RGB:red diff --git a/src/gui/theme/qBittorrentLight.colortheme b/src/gui/theme/qBittorrentLight.colortheme new file mode 100644 index 0000000000..c2590e1a1b --- /dev/null +++ b/src/gui/theme/qBittorrentLight.colortheme @@ -0,0 +1,37 @@ +[Info] +Name=Default (Light) +Description=Default qBittorrent color theme. Light flavour. + +[TorrentState] +Unknown=RGB:#ff0000 +Error=RGB:#ff0000 +MissingFiles=RGB:#ff0000 +Uploading=RGB:#4169e1 +PausedUploading=RGB:#000081 +QueuedUploading=RGB:#008080 +StalledUploading=RGB:#000000 +CheckingUploading=RGB:#008080 +ForcedUploading=RGB:#4169e1 +Allocating=RGB:#000000 +Downloading=RGB:#228b22 +DownloadingMetadata=RGB:#228b22 +PausedDownloading=RGB:#fa8072 +QueuedDownloading=RGB:#008080 +StalledDownloading=RGB:#000000 +CheckingDownloading=RGB:#008080 +ForcedDownloading=RGB:#228b22 +QueuedForChecking=RGB:#008080 +CheckingResumeData=RGB:#008080 + +[LogMessageType] +ALL=QPalette:Active:WindowText +NORMAL=QPalette:Active:WindowText +INFO=RGB:blue +WARNING=RGB:orange +CRITICAL=RGB:red + +[DownloadProgressBar] +Background=RGB:white +Border=QPalette:Active:Dark +Complete=RGB:blue +Incomplete=RGB:#00d000 diff --git a/src/gui/theme/serializablecolortheme.cpp b/src/gui/theme/serializablecolortheme.cpp new file mode 100644 index 0000000000..6bac29b650 --- /dev/null +++ b/src/gui/theme/serializablecolortheme.cpp @@ -0,0 +1,310 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "serializablecolortheme.h" + +#include +#include +#include + +#include + +#include "base/bittorrent/torrenthandle.h" +#include "base/logger.h" + +#include "colorprovider_p.h" +#include "serializabletheme.h" +#include "themeprovider.h" + +namespace +{ + const QByteArray torrentStateColorsGroup("TorrentState/"); + const QByteArray msgTypeColorsGroup("LogMessageType/"); + const QByteArray downloadProggressBarColorsGroup("DownloadProgressBar/"); + + const QLatin1String defaultLightColorThemeName ("Default (Light)"); + const QLatin1String defaultDarkColorThemeName ("Default (Dark)"); + + Theme::ColorThemeElement toThemeElement(Theme::DownloadProgressBarElement element) + { + switch (element) { + case Theme::DownloadProgressBarElement::Background: + return Theme::ColorThemeElement::DownloadProgressBarElementBackground; + case Theme::DownloadProgressBarElement::Border: + return Theme::ColorThemeElement::DownloadProgressBarElementBorder; + case Theme::DownloadProgressBarElement::Complete: + return Theme::ColorThemeElement::DownloadProgressBarElementComplete; + case Theme::DownloadProgressBarElement::Incomplete: + return Theme::ColorThemeElement::DownloadProgressBarElementIncomplete; + default: + throw std::logic_error("Unexpected DownloadProgressBarElement value"); + } + } + + Theme::ColorThemeElement toThemeElement(Log::MsgType messageType) + { + switch (messageType) { + case Log::MsgType::ALL: + return Theme::ColorThemeElement::MsgTypeALL; + case Log::MsgType::NORMAL: + return Theme::ColorThemeElement::MsgTypeNORMAL; + case Log::MsgType::INFO: + return Theme::ColorThemeElement::MsgTypeINFO; + case Log::MsgType::WARNING: + return Theme::ColorThemeElement::MsgTypeWARNING; + case Log::MsgType::CRITICAL: + return Theme::ColorThemeElement::MsgTypeCRITICAL; + default: + throw std::logic_error("Unexpected Log::MsgType value"); + } + } + + Theme::ColorThemeElement toThemeElement(BitTorrent::TorrentState state) + { + switch (state) { + case BitTorrent::TorrentState::Unknown: + return Theme::ColorThemeElement::TorrentStateUnknown; + case BitTorrent::TorrentState::Error: + return Theme::ColorThemeElement::TorrentStateError; + case BitTorrent::TorrentState::MissingFiles: + return Theme::ColorThemeElement::TorrentStateMissingFiles; + case BitTorrent::TorrentState::Uploading: + return Theme::ColorThemeElement::TorrentStateUploading; + case BitTorrent::TorrentState::PausedUploading: + return Theme::ColorThemeElement::TorrentStatePausedUploading; + case BitTorrent::TorrentState::QueuedUploading: + return Theme::ColorThemeElement::TorrentStateQueuedUploading; + case BitTorrent::TorrentState::StalledUploading: + return Theme::ColorThemeElement::TorrentStateStalledUploading; + case BitTorrent::TorrentState::CheckingUploading: + return Theme::ColorThemeElement::TorrentStateCheckingUploading; + case BitTorrent::TorrentState::ForcedUploading: + return Theme::ColorThemeElement::TorrentStateForcedUploading; + case BitTorrent::TorrentState::Allocating: + return Theme::ColorThemeElement::TorrentStateAllocating; + case BitTorrent::TorrentState::Downloading: + return Theme::ColorThemeElement::TorrentStateDownloading; + case BitTorrent::TorrentState::DownloadingMetadata: + return Theme::ColorThemeElement::TorrentStateDownloadingMetadata; + case BitTorrent::TorrentState::PausedDownloading: + return Theme::ColorThemeElement::TorrentStatePausedDownloading; + case BitTorrent::TorrentState::QueuedDownloading: + return Theme::ColorThemeElement::TorrentStateQueuedDownloading; + case BitTorrent::TorrentState::StalledDownloading: + return Theme::ColorThemeElement::TorrentStateStalledDownloading; + case BitTorrent::TorrentState::CheckingDownloading: + return Theme::ColorThemeElement::TorrentStateCheckingDownloading; + case BitTorrent::TorrentState::ForcedDownloading: + return Theme::ColorThemeElement::TorrentStateForcedDownloading; + #if LIBTORRENT_VERSION_NUM < 10100 + case BitTorrent::TorrentState::QueuedForChecking: + return Theme::ColorThemeElement::TorrentStateQueuedForChecking; + #endif + case BitTorrent::TorrentState::CheckingResumeData: + return Theme::ColorThemeElement::TorrentStateCheckingResumeData; + default: + throw std::logic_error("Unexpected TorrentState value"); + } + } +} + +Theme::SerializableColorTheme::SerializableColorTheme(const QString &name) + : BaseSerializableTheme(name, elementNames()) +{ +} + +void Theme::SerializableColorTheme::applicationPaletteChanged() +{ + updateCache(); +} + +Theme::SerializableColorTheme::BaseSerializableTheme::NamesMap +Theme::SerializableColorTheme::elementNames() +{ + const auto makeTorrentStateNamePair = [](BitTorrent::TorrentState st) + { + return std::make_pair(QByteArray(torrentStateColorsGroup + colorSaveName(st)), static_cast(toThemeElement(st))); + }; + + const auto makeMsgTypeNamePair = [](Log::MsgType mt) + { + return std::make_pair(QByteArray(msgTypeColorsGroup + colorSaveName(mt)), static_cast(toThemeElement(mt))); + }; + + const auto makeDownloadProgressBarNamePair = [](DownloadProgressBarElement e) + { + return std::make_pair(QByteArray(downloadProggressBarColorsGroup + colorSaveName(e)), static_cast(toThemeElement(e))); + }; + + return { + makeTorrentStateNamePair(BitTorrent::TorrentState::Unknown), + makeTorrentStateNamePair(BitTorrent::TorrentState::Error), + makeTorrentStateNamePair(BitTorrent::TorrentState::MissingFiles), + makeTorrentStateNamePair(BitTorrent::TorrentState::Uploading), + makeTorrentStateNamePair(BitTorrent::TorrentState::PausedUploading), + makeTorrentStateNamePair(BitTorrent::TorrentState::QueuedUploading), + makeTorrentStateNamePair(BitTorrent::TorrentState::StalledUploading), + makeTorrentStateNamePair(BitTorrent::TorrentState::CheckingUploading), + makeTorrentStateNamePair(BitTorrent::TorrentState::ForcedUploading), + makeTorrentStateNamePair(BitTorrent::TorrentState::Allocating), + makeTorrentStateNamePair(BitTorrent::TorrentState::Downloading), + makeTorrentStateNamePair(BitTorrent::TorrentState::DownloadingMetadata), + makeTorrentStateNamePair(BitTorrent::TorrentState::PausedDownloading), + makeTorrentStateNamePair(BitTorrent::TorrentState::QueuedDownloading), + makeTorrentStateNamePair(BitTorrent::TorrentState::StalledDownloading), + makeTorrentStateNamePair(BitTorrent::TorrentState::CheckingDownloading), + makeTorrentStateNamePair(BitTorrent::TorrentState::ForcedDownloading), +#if LIBTORRENT_VERSION_NUM < 10100 + makeTorrentStateNamePair(BitTorrent::TorrentState::QueuedForChecking), +#endif + makeTorrentStateNamePair(BitTorrent::TorrentState::CheckingResumeData), + + makeMsgTypeNamePair(Log::MsgType::ALL), + makeMsgTypeNamePair(Log::MsgType::NORMAL), + makeMsgTypeNamePair(Log::MsgType::INFO), + makeMsgTypeNamePair(Log::MsgType::WARNING), + makeMsgTypeNamePair(Log::MsgType::CRITICAL), + + makeDownloadProgressBarNamePair(DownloadProgressBarElement::Background), + makeDownloadProgressBarNamePair(DownloadProgressBarElement::Border), + makeDownloadProgressBarNamePair(DownloadProgressBarElement::Complete), + makeDownloadProgressBarNamePair(DownloadProgressBarElement::Incomplete) + }; +} + +Theme::ThemeInfo Theme::SerializableColorTheme::info() const +{ + return BaseSerializableTheme::info(); +} + +QByteArray Theme::SerializableColorTheme::colorSaveName(BitTorrent::TorrentState state) +{ + // TODO Qt 5.8+: use Q_NAMESPACE + Q_ENUM_NS + // static QMetaEnum meta = QMetaEnum::fromType(); + // return QString::fromLatin1(meta.key(static_cast(state))); + switch (state) { + case BitTorrent::TorrentState::Unknown: + return "Unknown"; + case BitTorrent::TorrentState::Error: + return "Error"; + case BitTorrent::TorrentState::MissingFiles: + return "MissingFiles"; + case BitTorrent::TorrentState::Uploading: + return "Uploading"; + case BitTorrent::TorrentState::PausedUploading: + return "PausedUploading"; + case BitTorrent::TorrentState::QueuedUploading: + return "QueuedUploading"; + case BitTorrent::TorrentState::StalledUploading: + return "StalledUploading"; + case BitTorrent::TorrentState::CheckingUploading: + return "CheckingUploading"; + case BitTorrent::TorrentState::ForcedUploading: + return "ForcedUploading"; + case BitTorrent::TorrentState::Allocating: + return "Allocating"; + case BitTorrent::TorrentState::Downloading: + return "Downloading"; + case BitTorrent::TorrentState::DownloadingMetadata: + return "DownloadingMetadata"; + case BitTorrent::TorrentState::PausedDownloading: + return "PausedDownloading"; + case BitTorrent::TorrentState::QueuedDownloading: + return "QueuedDownloading"; + case BitTorrent::TorrentState::StalledDownloading: + return "StalledDownloading"; + case BitTorrent::TorrentState::CheckingDownloading: + return "CheckingDownloading"; + case BitTorrent::TorrentState::ForcedDownloading: + return "ForcedDownloading"; +#if LIBTORRENT_VERSION_NUM < 10100 + case BitTorrent::TorrentState::QueuedForChecking: + return "QueuedForChecking"; +#endif + case BitTorrent::TorrentState::CheckingResumeData: + return "CheckingResumeData"; + default: + throw std::logic_error("Unexpected TorrentState value"); + } +} + +QByteArray Theme::SerializableColorTheme::colorSaveName(Log::MsgType msgType) +{ + // TODO Qt 5.8+: use Q_NAMESPACE + Q_ENUM_NS + // static QMetaEnum meta = QMetaEnum::fromType(); + // return QString::fromLatin1(meta.key(static_cast(msgType))); + switch (msgType) { + case Log::MsgType::ALL: + return "ALL"; + case Log::MsgType::NORMAL: + return "NORMAL"; + case Log::MsgType::INFO: + return "INFO"; + case Log::MsgType::WARNING: + return "WARNING"; + case Log::MsgType::CRITICAL: + return "CRITICAL"; + default: + throw std::logic_error("Unexpected Log::MsgType value"); + } +} + +QByteArray Theme::SerializableColorTheme::colorSaveName(DownloadProgressBarElement element) +{ + // TODO Qt 5.8+: use Q_NAMESPACE + Q_ENUM_NS + // static QMetaEnum meta = QMetaEnum::fromType(); + // return QString::fromLatin1(meta.key(static_cast(element))); + switch (element) { + case DownloadProgressBarElement::Background: + return "Background"; + case DownloadProgressBarElement::Border: + return "Border"; + case DownloadProgressBarElement::Complete: + return "Complete"; + case DownloadProgressBarElement::Incomplete: + return "Incomplete"; + default: + throw std::logic_error("Unexpected DownloadProgressBarElement value"); + } +} + +QColor Theme::SerializableColorTheme::downloadProgressBarColor(const DownloadProgressBarElement elem) const +{ + return element(toThemeElement(elem)); +} + +QColor Theme::SerializableColorTheme::logMessageColor(const Log::MsgType messageType) const +{ + return element(toThemeElement(messageType)); +} + +QColor Theme::SerializableColorTheme::torrentStateColor(const BitTorrent::TorrentState state) const +{ + return element(toThemeElement(state)); +} + diff --git a/src/gui/theme/serializablecolortheme.h b/src/gui/theme/serializablecolortheme.h new file mode 100644 index 0000000000..6bc307fe1e --- /dev/null +++ b/src/gui/theme/serializablecolortheme.h @@ -0,0 +1,99 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_SERIALIZABLECOLORTHEME_H +#define QBT_THEME_SERIALIZABLECOLORTHEME_H + +#include "colorprovider_p.h" +#include "colortheme.h" +#include "serializabletheme.h" + +namespace Theme +{ + enum class ColorThemeElement + { + TorrentStateUnknown, + TorrentStateForcedDownloading, + TorrentStateDownloading, + TorrentStateDownloadingMetadata, + TorrentStateAllocating, + TorrentStateStalledDownloading, + TorrentStateForcedUploading, + TorrentStateUploading, + TorrentStateStalledUploading, +#if LIBTORRENT_VERSION_NUM < 10100 + TorrentStateQueuedForChecking, +#endif + TorrentStateCheckingResumeData, + TorrentStateQueuedDownloading, + TorrentStateQueuedUploading, + TorrentStateCheckingUploading, + TorrentStateCheckingDownloading, + TorrentStatePausedDownloading, + TorrentStatePausedUploading, + TorrentStateMissingFiles, + TorrentStateError, + + MsgTypeALL, + MsgTypeNORMAL, + MsgTypeINFO, + MsgTypeWARNING, + MsgTypeCRITICAL, + + DownloadProgressBarElementBackground, + DownloadProgressBarElementBorder, + DownloadProgressBarElementComplete, + DownloadProgressBarElementIncomplete + }; + + class SerializableColorTheme: public ColorTheme, + protected SerializableTheme + { + public: + using BaseSerializableTheme = SerializableTheme; + SerializableColorTheme(const QString &name); + + using BaseSerializableTheme::save; + + ThemeInfo info() const override; + QColor torrentStateColor(const BitTorrent::TorrentState state) const override; + QColor logMessageColor(const Log::MsgType messageType) const override; + QColor downloadProgressBarColor(const DownloadProgressBarElement element) const override; + + void applicationPaletteChanged(); + + private: + static QByteArray colorSaveName(BitTorrent::TorrentState state); + static QByteArray colorSaveName(Log::MsgType msgType); + static QByteArray colorSaveName(DownloadProgressBarElement element); + + static BaseSerializableTheme::NamesMap elementNames(); + }; +} + +#endif // QBT_THEME_SERIALIZABLECOLORTHEME_H diff --git a/src/gui/theme/serializablefonttheme.cpp b/src/gui/theme/serializablefonttheme.cpp new file mode 100644 index 0000000000..986c05ec79 --- /dev/null +++ b/src/gui/theme/serializablefonttheme.cpp @@ -0,0 +1,57 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "serializablefonttheme.h" + +#include + +#include "themeexceptions.h" + +namespace +{ + const QByteArray fontsGroupName("Fonts/"); +} + +Theme::SerializableFontTheme::SerializableFontTheme(const QString& themeName) + : BaseSerializableTheme(themeName, elementNames()) +{ +} + +const Theme::ThemeInfo &Theme::SerializableFontTheme::info() const +{ + return BaseSerializableTheme::info(); +} + +Theme::SerializableFontTheme::BaseSerializableTheme::NamesMap Theme::SerializableFontTheme::elementNames() +{ + return { + {fontsGroupName + QByteArray("TransferList"), static_cast(FontThemeElement::TransferList)}, + {fontsGroupName + QByteArray("TorrentProperties"), static_cast(FontThemeElement::TorrentProperties)}, + {fontsGroupName + QByteArray("ExecutionLog"), static_cast(FontThemeElement::ExecutionLog)}, + }; +} diff --git a/src/gui/theme/serializablefonttheme.h b/src/gui/theme/serializablefonttheme.h new file mode 100644 index 0000000000..dbb17e9318 --- /dev/null +++ b/src/gui/theme/serializablefonttheme.h @@ -0,0 +1,58 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_SERIALIZABLEFONTTHEME_H +#define QBT_THEME_SERIALIZABLEFONTTHEME_H + +#include "fontprovider_p.h" +#include "fonttheme.h" +#include "serializabletheme.h" +#include "themeinfo.h" + +namespace Theme +{ + class SerializableFontTheme : public FontTheme, + protected SerializableTheme + { + public: + using BaseSerializableTheme = SerializableTheme; + SerializableFontTheme(const QString &themeName); + + using BaseSerializableTheme::save; + + const QFont &font(FontThemeElement e) const override { + return element(e); + } + + const Theme::ThemeInfo & info() const override; + private: + static BaseSerializableTheme::NamesMap elementNames(); + }; +} + +#endif // QBT_THEME_SERIALIZABLEFONTTHEME_H diff --git a/src/gui/theme/serializabletheme.cpp b/src/gui/theme/serializabletheme.cpp new file mode 100644 index 0000000000..7299a8094f --- /dev/null +++ b/src/gui/theme/serializabletheme.cpp @@ -0,0 +1,138 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "serializabletheme.h" + +#include + +#include + +#include "themeinfo.h" +#include "themeprovider.h" + +namespace +{ + void appendAbsentElements(Theme::ElementsMap &res, QSettings &settings) + { + // we ignore all keys in [Info] group + const QString infoPrefix = Theme::ThemeInfo::sectionName + QLatin1Char('/'); + const auto keys = settings.allKeys(); + for (const auto& key: keys) { + if (!key.startsWith(infoPrefix) && // ignore all keys in [Info] group + res.find(key) == res.end()) { + QVariant v = settings.value(key); + // if there were commas in the value, QVariant contains string list + // and we have to join it back + res[key] = v.type() == QVariant::StringList + ? v.toStringList().join(QLatin1Char(',')) + : v.toString(); + } + } + } + + struct LoadedTheme + { + Theme::ThemeInfo info; + Theme::ElementsMap elements; + }; + + /** + * @brief Loads serialized themes + * + * This function handles themes inheritance and takes care of appending default theme if needed + */ + LoadedTheme collectThemeElements(Theme::Kind kind, const QString& name, const QString& defaultInherited) + { + // we are going to load themes from inheritance hierarchy from descendant + // to ancestor, appending ancestor element to the dictionary if corresponding keys + // are not already present in it. + bool firstThemeWasLoaded = false; // we need info object from the first theme only + LoadedTheme res; + + QString themeName = name; + std::set loadedThemeNames; // this will be used to protect us against infinite + // inheritance loops + + Q_ASSERT(!themeName.isEmpty()); + do { + const QString themeFileName = Theme::ThemeProvider::instance().locateTheme(kind, themeName); + QSettings settings(themeFileName, QSettings::IniFormat); + Theme::ThemeInfo info = Theme::ThemeInfo(settings); + if (!firstThemeWasLoaded) { + res.info = info; + firstThemeWasLoaded = true; + } + appendAbsentElements(res.elements, settings); + + loadedThemeNames.insert(info.name()); + + themeName = info.inheritedTheme(); + if (themeName.isEmpty()) { + themeName = defaultInherited; + } + } while (loadedThemeNames.count(themeName) == 0); + + return res; + } +} + +Theme::ThemeSerializer::ThemeSerializer(Kind kind, const QString &themeName, + const NamesMap& names, ElementDeserializer deserializer) + : m_names {names} + , m_info {} + , m_kind {kind} +{ + const QString defaultThemeName = ThemeProvider::instance().defaultThemeName(m_kind); + QString nameToUse = themeName.isEmpty() ? defaultThemeName : themeName; + const LoadedTheme loaded = collectThemeElements(m_kind, nameToUse, defaultThemeName); + m_info = std::move(loaded.info); + for (const auto &p : loaded.elements) { + const auto it = m_names.find(p.first.toLatin1()); + if (it == m_names.end()) { + qCWarning(theme) << "Unexpected theme element '" << p.first << '\''; + continue; + } + deserializer(it->second, p.second); + } +} + +void Theme::ThemeSerializer::save(const QString& themeFileName, + bool explicitValues, ElementSerializer serializer) const +{ + QSettings settings(themeFileName, QSettings::IniFormat); + + m_info.save(settings); + for (const auto &p : m_names) { + settings.setValue(p.first, serializer(p.second, explicitValues)); + } +} + +const Theme::ThemeInfo &Theme::ThemeSerializer::info() const +{ + return m_info; +} diff --git a/src/gui/theme/serializabletheme.h b/src/gui/theme/serializabletheme.h new file mode 100644 index 0000000000..a357e0ac60 --- /dev/null +++ b/src/gui/theme/serializabletheme.h @@ -0,0 +1,156 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_SERIALIZABLE_THEME_H +#define QBT_THEME_SERIALIZABLE_THEME_H + +#include "themecommon.h" +#include "themeinfo.h" + +#include +#include + +#include +#include +#include + +namespace Theme +{ + using ElementsMap = std::map; + + class ThemeSerializer + { + public: + using NamesMap = std::map; + using ElementDeserializer = std::function; + using ElementSerializer = std::function; + + ThemeSerializer(Kind kind, const QString &themeName, + const NamesMap& names, ElementDeserializer deserializer); + + void save(const QString &themeFileName, bool explicitValues, ElementSerializer serializer) const; + + const ThemeInfo &info() const; + private: + + NamesMap m_names; + ThemeInfo m_info; + Kind m_kind; + }; + + template + class SerializableTheme + { + static_assert(std::is_same::type>::value, + "Element underlying type has to be int"); + + public: + using EntityProviderType = typename ProviderRegistry::ProviderType; + using EntityType = typename EntityProviderType::EntityType; + using ThemeObjectType = typename EntityType::ValueType; + using ElementType = Element; + using NamesMap = typename ThemeSerializer::NamesMap; + + using ThisType = SerializableTheme; + + const ThemeObjectType &element(Element e) const; + const ThemeInfo &info() const; + + protected: + SerializableTheme(const QString &themeName, const NamesMap& names); + void updateCache() const; + + void save(const QString &themeFileName, bool explicitValues) const; + + private: + QString serialize(int elementId, bool explicitValue) const; + void deserialize(int elementId, const QString &value); + + using ElementsMap = std::map; + using ObjectsMap = std::map; + + ElementsMap m_elements; + ThemeSerializer m_serializer; + mutable ObjectsMap m_cache; + }; +} + +template +const typename Theme::SerializableTheme::ThemeObjectType +&Theme::SerializableTheme::element(Element e) const +{ + return m_cache[e]; +} + +template +const Theme::ThemeInfo & Theme::SerializableTheme::info() const +{ + return m_serializer.info(); +} + +template +Theme::SerializableTheme::SerializableTheme( + const QString& themeName, const NamesMap& names) + : m_elements{} + , m_serializer(ProviderRegistry::kind, themeName, names, + std::bind(&SerializableTheme::deserialize, this, std::placeholders::_1, std::placeholders::_2)) +{ + updateCache(); +} + +template +void Theme::SerializableTheme::save(const QString& themeFileName, bool explicitValues) const +{ + m_serializer.save(themeFileName, explicitValues, + std::bind(&SerializableTheme::serialize, this, std::placeholders::_1, std::placeholders::_2)); +} + +template +QString Theme::SerializableTheme::serialize(int elementId, bool explicitValue) const +{ + const auto &element = m_elements.at(static_cast(elementId)); + return element->serializationKey() + QLatin1Char(':') + + (explicitValue ? element->explicitSerializedValue() : element->serializedValue()); +} + +template +void Theme::SerializableTheme::deserialize(int elementId, const QString &value) +{ + m_elements[static_cast(elementId)] = ProviderRegistry::instance().load(value); +} + +template +void Theme::SerializableTheme::updateCache() const +{ + for (const auto &p : m_elements) { + m_cache[p.first] = p.second->value(); + } +} + + +#endif // QBT_THEME_SERIALIZABLE_THEME_H diff --git a/src/gui/theme/themecommon.cpp b/src/gui/theme/themecommon.cpp new file mode 100644 index 0000000000..fff2197b1b --- /dev/null +++ b/src/gui/theme/themecommon.cpp @@ -0,0 +1,38 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "themecommon.h" + +#include + +bool Theme::isDarkTheme() +{ + return (QPalette().color(QPalette::Active, QPalette::Base).lightness() < 127); +} + +Q_LOGGING_CATEGORY(theme, "qbt.theme") diff --git a/src/gui/theme/themecommon.h b/src/gui/theme/themecommon.h new file mode 100644 index 0000000000..45b6a99187 --- /dev/null +++ b/src/gui/theme/themecommon.h @@ -0,0 +1,47 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_THEMECOMMON_H +#define QBT_THEME_THEMECOMMON_H + +#include + +Q_DECLARE_LOGGING_CATEGORY(theme) + +namespace Theme +{ + enum class Kind + { + Color, + Font + }; + + bool isDarkTheme(); +} + +#endif // QBT_THEME_THEMECOMMON_H diff --git a/src/gui/theme/themeexceptions.cpp b/src/gui/theme/themeexceptions.cpp new file mode 100644 index 0000000000..d6710a17b7 --- /dev/null +++ b/src/gui/theme/themeexceptions.cpp @@ -0,0 +1,87 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "themeexceptions.h" + +Theme::ThemeNotFound::ThemeNotFound(const QString& themeName) + : ThemeError("Could not find theme named '" + themeName.toStdString() + "'") +{ +} + +Theme::Serialization::ThemeElementMissing::ThemeElementMissing(const QString& elementName) + : DeserializationError("Theme misses element '" + elementName.toStdString() + '\'') + , m_elementName(elementName) +{ +} + +const QString &Theme::Serialization::ThemeElementMissing::elementName() const +{ + return m_elementName; +} + +Theme::Serialization::ElementDeserializationError::ElementDeserializationError( + const std::string& message, const QString& serializedValue) + : DeserializationError("Could not deserialize theme object '" + serializedValue.toStdString() + "': " + message) + , m_serializedValue(serializedValue) +{ +} + +const QString &Theme::Serialization::ElementDeserializationError::serializedValue() const +{ + return m_serializedValue; +} + +Theme::Serialization::ParsingError::ParsingError(const QString& serializedValue) + : ElementDeserializationError("Could not find scheme part", serializedValue) +{ +} + +// we know that serializedValue follows scheme:value pattern, otherwise this exception is not applicable +Theme::Serialization::UnknownProvider::UnknownProvider(const QString& serializedValue) + : ElementDeserializationError("Could not find provider for scheme '" + + serializedValue.section(QLatin1Char(':'), 0, 1).toStdString() + '\'', serializedValue) +{ +} + +QString Theme::Serialization::UnknownProvider::profiderName() const +{ + // we know that serializedValue follows scheme:value pattern, otherwise this exception is not applicable + return this->serializedValue().section(QLatin1Char(':'), 0, 1); +} + +Theme::Serialization::ValueParsingError::ValueParsingError(const std::string& message, const QString& serializedValue) + : ElementDeserializationError("Could not parse element value: " + message, serializedValue) +{ +} + +QString Theme::Serialization::ValueParsingError::valueString() const +{ + // we know that serializedValue follows scheme:value pattern, otherwise this exception is not applicable + return this->serializedValue().section(QLatin1Char(':'), 1); +} + diff --git a/src/gui/theme/themeexceptions.h b/src/gui/theme/themeexceptions.h new file mode 100644 index 0000000000..b37051c6e2 --- /dev/null +++ b/src/gui/theme/themeexceptions.h @@ -0,0 +1,101 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_THEMEEXCEPTIONS_H +#define QBT_THEME_THEMEEXCEPTIONS_H + +#include + +#include + +namespace Theme +{ + + class ThemeError: public std::runtime_error + { + public: + using std::runtime_error::runtime_error; + }; + + class ThemeNotFound: public ThemeError + { + public: + ThemeNotFound(const QString &themeName); + }; + + namespace Serialization + { + class DeserializationError: public ThemeError + { + public: + using ThemeError::ThemeError; + }; + + class ThemeElementMissing: public DeserializationError + { + public: + ThemeElementMissing(const QString &elementName); + + const QString &elementName() const; + private: + QString m_elementName; + }; + + class ElementDeserializationError: public DeserializationError + { + public: + ElementDeserializationError(const std::string &message, const QString &serializedValue); + const QString &serializedValue() const; + + private: + QString m_serializedValue; + }; + + class ParsingError: public ElementDeserializationError + { + public: + ParsingError(const QString &serializedValue); + }; + + class UnknownProvider: public ElementDeserializationError + { + public: + UnknownProvider(const QString &serializedValue); + QString profiderName() const; + }; + + class ValueParsingError: public ElementDeserializationError + { + public: + ValueParsingError(const std::string &message, const QString &serializedValue); + QString valueString() const; + }; + } +} + +#endif // QBT_THEME_THEMEEXCEPTIONS_H diff --git a/src/gui/theme/themeinfo.cpp b/src/gui/theme/themeinfo.cpp new file mode 100644 index 0000000000..3fd2438787 --- /dev/null +++ b/src/gui/theme/themeinfo.cpp @@ -0,0 +1,156 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "themeinfo.h" + +#include +#include +#include + +namespace +{ +#define GROUP_NAME "Info" +#define FULL_SETTING_KEY(name) GROUP_NAME "/" name + const QLatin1String nameFullKey(FULL_SETTING_KEY("Name")); + const QLatin1String descriptionFullKey(FULL_SETTING_KEY("Description")); + const QLatin1String inheritsFullKey(FULL_SETTING_KEY("Inherits")); + + const QLatin1String nameKey = QLatin1String("Name"); + const QLatin1String descriptionKey = QLatin1String("Description"); +} + +const QString Theme::ThemeInfo::sectionName = QLatin1String(GROUP_NAME); + +Theme::ThemeInfo::ThemeInfo() = default; + +Theme::ThemeInfo::ThemeInfo(QSettings& settings) + : m_name {settings.value(nameFullKey, QLatin1Literal("Unnamed")).toString()} + , m_description {settings.value(descriptionFullKey, QString()).toString()} + , m_inheritedTheme {settings.value(inheritsFullKey, QString()).toString()} +{ + settings.beginGroup(QLatin1String(GROUP_NAME)); + m_localizedNames = readAffixedKeys(settings, QString(nameKey) + QLatin1Char('_')); + m_localizedDescriptions = readAffixedKeys(settings, QString(descriptionKey) + QLatin1Char('_')); + settings.endGroup(); +} + +void Theme::ThemeInfo::save(QSettings& settings) const +{ + settings.setValue(nameFullKey, m_name); + settings.setValue(descriptionFullKey, m_description); + settings.setValue(inheritsFullKey, m_inheritedTheme); + + settings.beginGroup(QLatin1String(GROUP_NAME)); + writeAffixedKeys(m_localizedNames, settings, QString(nameKey) + QLatin1Char('_')); + writeAffixedKeys(m_localizedDescriptions, settings, QString(descriptionKey) + QLatin1Char('_')); + settings.endGroup(); +} + +Theme::ThemeInfo::LocalizedStrings +Theme::ThemeInfo::readAffixedKeys(QSettings &settings, const QString &name) +{ + LocalizedStrings res; + const QStringList keys = settings.allKeys(); + for (const QString &key: keys) { + if (key.startsWith(name)) { + res[key.mid(name.size())] = settings.value(key).toString(); + } + } + return res; +} + +void Theme::ThemeInfo::writeAffixedKeys(const LocalizedStrings& values, QSettings& settings, const QString& name) +{ + for (const auto &pair: values) { + settings.setValue(name + pair.first, pair.second); + } +} + +QString Theme::ThemeInfo::name() const +{ + return m_name; +} + +QString Theme::ThemeInfo::description() const +{ + return m_description; +} + +QString Theme::ThemeInfo::inheritedTheme() const +{ + return m_inheritedTheme; +} + +void Theme::ThemeInfo::setName(const QString& name) +{ + m_name = name; +} + +void Theme::ThemeInfo::setDescription(const QString& description) +{ + m_description = description; +} + +void Theme::ThemeInfo::setInheritedTheme(const QString& name) +{ + m_inheritedTheme = name; +} + +QString Theme::ThemeInfo::findLocalizedString(const LocalizedStrings& strings) +{ + static QLocale loc; + auto i = strings.find(loc.name()); + if (i != strings.end()) { + return i->second; + } + + i = strings.find(QLocale::languageToString(loc.language())); + if (i != strings.end()) { + return i->second; + } + + return {}; +} + +QString Theme::ThemeInfo::localizedName() const +{ + const QString localized = findLocalizedString(m_localizedNames); + return localized.isEmpty() ? m_name : localized; +} + +QString Theme::ThemeInfo::localizedDescription() const +{ + const QString localized = findLocalizedString(m_localizedDescriptions); + return localized.isEmpty() ? m_description : localized; +} + +QDebug Theme::operator<<(QDebug debug, const Theme::ThemeInfo &info) +{ + debug << info.name() << " [" << info.description() << ']'; + return debug; +} diff --git a/src/gui/theme/themeinfo.h b/src/gui/theme/themeinfo.h new file mode 100644 index 0000000000..747606a642 --- /dev/null +++ b/src/gui/theme/themeinfo.h @@ -0,0 +1,112 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEMES_THEMEINFO_H +#define QBT_THEMES_THEMEINFO_H + +#include + +#include + +class QDebug; +class QSettings; + +namespace Theme +{ + /** + * @brief Utility class to encapsulate general theme attributes + * + * Contains name and description of the theme + * + * These data reside in section [Info] of the theme file: + * + * [Info] + * Name=Theme name + * Description=Description of the theme + * Inherits=Other theme name + * Name_de=Name in German + * Name_gr=Name in Greek + * Description_fr=Description in French + * Description_uk=Description in Ukrainian + * + */ + class ThemeInfo + { + public: + ThemeInfo(); + ThemeInfo(QSettings &settings); + + void save(QSettings &settings) const; + + QString name() const; + QString localizedName() const; + QString description() const; + QString localizedDescription() const; + QString inheritedTheme() const; + + void setName(const QString &name); + void setDescription(const QString &description); + void setInheritedTheme(const QString &name); + + static const QString sectionName; + + private: + QString m_name; + QString m_description; + QString m_inheritedTheme; + + using LocalizedStrings = std::map; + /** + * @brief Function reads key values whose names start with "${name}" + * @returns dictionary of affix -> value + */ + static LocalizedStrings readAffixedKeys(QSettings &settings, const QString &name); + static void writeAffixedKeys(const LocalizedStrings& values, QSettings &settings, const QString &name); + + static QString findLocalizedString(const LocalizedStrings &strings); + + LocalizedStrings m_localizedNames; + LocalizedStrings m_localizedDescriptions; + }; + + QDebug operator<<(QDebug debug, const ThemeInfo &info); + + // comparison operators: there may not be two themes with equal names of the same kind in the app + + inline bool operator < (const ThemeInfo &left, const ThemeInfo &right) + { + return left.name() < right.name(); + } + + inline bool operator == (const ThemeInfo &left, const ThemeInfo &right) + { + return left.name() == right.name(); + } +} + +#endif diff --git a/src/gui/theme/themeprovider.cpp b/src/gui/theme/themeprovider.cpp new file mode 100644 index 0000000000..59a85cca64 --- /dev/null +++ b/src/gui/theme/themeprovider.cpp @@ -0,0 +1,266 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "themeprovider.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "base/logger.h" +#include "base/profile.h" +#include "base/settingsstorage.h" +#include "colorprovider_p.h" +#include "serializablecolortheme.h" +#include "serializablefonttheme.h" +#include "themecommon.h" +#include "themeexceptions.h" +#include "themeinfo.h" + +const QLatin1String Theme::ThemeProvider::colorThemeFileExtension(".colortheme"); +const QLatin1String Theme::ThemeProvider::fontThemeFileExtension(".fonttheme"); + +namespace +{ + class ThemeProviderInstantiable: public Theme::ThemeProvider + { + public: + using ThemeProvider::ThemeProvider; + }; + +#define SETTINGS_KEY(name) "Appearance/" name + const QLatin1String selectedColorThemeKey (SETTINGS_KEY("ColorTheme")); + const QLatin1String selectedFontThemeKey (SETTINGS_KEY("FontTheme")); + + const QLatin1String defaultLightColorThemeName ("Default (Light)"); + const QLatin1String defaultDarkColorThemeName ("Default (Dark)"); + const QLatin1String defaultFontThemeName("Default"); +} + +Q_GLOBAL_STATIC(ThemeProviderInstantiable, themeProvider) + +Theme::ThemeProvider & Theme::ThemeProvider::instance() +{ + return *themeProvider(); +} + +Theme::ThemeProvider::ThemeProvider() +{ + connect(qGuiApp, &QGuiApplication::paletteChanged, this, &ThemeProvider::applicationPaletteChanged); +} + +Theme::ThemeProvider::~ThemeProvider() = default; + +void Theme::ThemeProvider::loadConfiguration() +{ + const QString colorThemeName = SettingsStorage::instance()->loadValue(selectedColorThemeKey, QString()).toString(); + try { + setCurrentTheme(Kind::Color, colorThemeName); + } catch (Serialization::DeserializationError &ex) { + qCWarning(theme, "Color theme '%s' loading failed (%s), loading default theme instead", + qPrintable(colorThemeName), ex.what()); + Logger::instance()->addMessage(tr("Could not load color theme '%1'. Loading default theme.") + .arg(colorThemeName)); + setCurrentTheme(Kind::Color, QString()); + } + + const QString fontThemeName = SettingsStorage::instance()->loadValue(selectedFontThemeKey, QString()).toString(); + try { + setCurrentTheme(Kind::Font, fontThemeName); + } catch (Serialization::DeserializationError &ex) { + qCWarning(theme, "Font theme '%s' loading failed (%s), loading default theme instead", + qPrintable(fontThemeName), ex.what()); + Logger::instance()->addMessage(tr("Could not load font theme '%1'. Loading default theme.") + .arg(fontThemeName)); + setCurrentTheme(Kind::Font, QString()); + } +} + +std::map Theme::ThemeProvider::availableThemes(Kind kind) const +{ + QDir themeDir; + switch (kind) { + case Kind::Color: + themeDir.setNameFilters({QStringLiteral("*") + colorThemeFileExtension}); + break; + case Kind::Font: + themeDir.setNameFilters({QStringLiteral("*") + fontThemeFileExtension}); + break; + } + QStringList themeSearchPaths = this->themeSearchPaths(); + std::map res; + std::set loadedThemeNames; + for (const QString &path: themeSearchPaths) { + themeDir.cd(path); + QStringList themeFiles = themeDir.entryList(); + for (const QString &themeFile: themeFiles) { + const QString absThemePath = themeDir.absoluteFilePath(themeFile); + QSettings theme(absThemePath, QSettings::IniFormat); + ThemeInfo info(theme); + if (!loadedThemeNames.count(info.name())) { + res[info] = absThemePath; + loadedThemeNames.insert(info.name()); + } + } + } + + return res; +} + +QString Theme::ThemeProvider::defaultThemeName(Theme::Kind kind) const +{ + switch (kind) { + case Kind::Color: + return isDarkTheme() ? defaultDarkColorThemeName : defaultLightColorThemeName; + case Kind::Font: + return defaultFontThemeName; + default: + throw std::logic_error("Unexpected theme kind"); + } +} + + +QString Theme::ThemeProvider::locateTheme(Kind kind, const QString& themeName) const +{ + const auto themes = availableThemes(kind); + ThemeInfo fake; + fake.setName(themeName); + auto i = themes.find(fake); + if (i != themes.end()) + return i->second; + + throw ThemeNotFound(themeName); +} + +void Theme::ThemeProvider::exportTheme(Theme::Kind kind, const QString &themeName, + const QString &fileName, ExportOptios options) +{ + switch (kind) { + case Kind::Color: + SerializableColorTheme(themeName).save(fileName, options.testFlag(ExportOption::WriteExplicitValues)); + break; + case Kind::Font: + SerializableFontTheme(themeName).save(fileName, options.testFlag(ExportOption::WriteExplicitValues)); + break; + } +} + +QStringList Theme::ThemeProvider::themeSearchPaths() const +{ + const QString themeDirName = QStringLiteral("theme"); + QStringList res; + // always support resources, they are first in the list for two reasons: + // 1) themes from this dir serve as fallback + // 2) user may not override them because of 1) + res << QLatin1String(":/") + themeDirName; + res << QDir(Profile::instance().location(SpecialFolder::Data)).absoluteFilePath(themeDirName); + // WARNING QStandardPaths::locateAll() returns a list with entries from home directory at the + // beginning, but this is not documented and might change. In that case this method will be incorrect. + res << QStandardPaths::locateAll(QStandardPaths::AppLocalDataLocation, themeDirName, QStandardPaths::LocateDirectory); +#if defined Q_OS_UNIX && !defined Q_OS_MACOS + QDir appDir = QCoreApplication::applicationDirPath(); + appDir.cdUp(); + const QString installPrefix = appDir.canonicalPath(); + const QString resourceDirInInstallPrefix = installPrefix + QLatin1String("/share/") + + QCoreApplication::applicationName() + QDir::separator() + themeDirName; + if (!res.contains(resourceDirInInstallPrefix)) + res << resourceDirInInstallPrefix; +#endif + return res; +} + +const Theme::ColorTheme &Theme::ThemeProvider::colorTheme() const +{ + return *m_currentColorTheme; +} + +const Theme::FontTheme & Theme::ThemeProvider::fontTheme() const +{ + return *m_currentFontTheme; +} + +void Theme::ThemeProvider::setCurrentTheme(Kind kind, const QString& themeName) +{ + switch (kind) { + case Kind::Color: + qCInfo(theme, "Loading color theme %s", qPrintable(themeName)); + try { + decltype(m_currentColorTheme) newTheme(new SerializableColorTheme(themeName)); + std::swap(m_currentColorTheme, newTheme); + emit colorThemeChanged(); + SettingsStorage::instance()->storeValue(selectedColorThemeKey, themeName); + } + catch (Serialization::DeserializationError &er) { + qCInfo(theme) << "Could not load color theme '" << themeName << "': " << er.what(); + throw; + } + break; + case Kind::Font: + qCInfo(theme, "Loading font theme %s", qPrintable(themeName)); + try { + decltype(m_currentFontTheme) newTheme(new SerializableFontTheme(themeName)); + std::swap(m_currentFontTheme, newTheme); + emit fontThemeChanged(); + SettingsStorage::instance()->storeValue(selectedFontThemeKey, themeName); + } + catch (Serialization::DeserializationError &er) { + qCInfo(theme) << "Could not load font theme '" << themeName << "': " << er.what(); + throw; + } + break; + } +} + +Theme::ThemeInfo Theme::ThemeProvider::currentTheme(Theme::Kind kind) const +{ + switch (kind) { + case Kind::Color: + return colorTheme().info(); + case Kind::Font: + return fontTheme().info(); + } + throw std::logic_error("Unexpected theme kind"); +} + +void Theme::ThemeProvider::applicationPaletteChanged(const QPalette&) +{ + Serialization::ColorsProviderRegistry::instance().applicationPaletteChanged(); + m_currentColorTheme->applicationPaletteChanged(); + emit colorThemeChanged(); +} + +void Theme::ThemeProvider::initInstance() +{ + instance().loadConfiguration(); +} diff --git a/src/gui/theme/themeprovider.h b/src/gui/theme/themeprovider.h new file mode 100644 index 0000000000..fed3b731ab --- /dev/null +++ b/src/gui/theme/themeprovider.h @@ -0,0 +1,123 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEMEPROVIDER_H +#define QBT_THEMEPROVIDER_H + +#include +#include + +#include + +#include "themecommon.h" + +class QPalette; +class QStringList; +class Application; + +namespace Theme +{ + class ColorTheme; + class FontTheme; + class SerializableColorTheme; + class SerializableFontTheme; + class ThemeInfo; + + class ThemeProvider: public QObject + { + Q_OBJECT + Q_DISABLE_COPY(ThemeProvider) + + public: + static ThemeProvider &instance(); + + /** + * @brief Collection of available colour themes + * + * @returns map them info object -> file path + */ + std::map availableThemes(Kind kind) const; + + QString defaultThemeName(Kind kind) const; + + const ColorTheme &colorTheme() const; + const FontTheme &fontTheme() const; + + void setCurrentTheme(Kind kind, const QString &themeName); + ThemeInfo currentTheme(Kind kind) const; + + /** + * @brief Locate file with given named theme + * + * @param themeName Name of the theme to search for + * @return File path + */ + QString locateTheme(Kind kind, const QString &themeName) const; + + static const QLatin1String colorThemeFileExtension; + static const QLatin1String fontThemeFileExtension; + + enum class ExportOption + { + NoOptions = 0x0, + WriteExplicitValues = 0x1 //!< write explicit values, i.e. RGB instead of palette members + }; + + Q_DECLARE_FLAGS(ExportOptios, ExportOption) + + void exportTheme(Kind kind, const QString &themeName, const QString &fileName, ExportOptios options = ExportOption::NoOptions); + + signals: + void colorThemeChanged(); + void fontThemeChanged(); + + protected: + ThemeProvider(); + ~ThemeProvider(); + + private slots: + void applicationPaletteChanged(const QPalette&); + + private: + friend class ::Application; + static void initInstance(); + void loadConfiguration(); + /** + * @brief Theme search paths arranged by priority + * + * @return QStringList with paths. The firs one is of highest priority. + */ + QStringList themeSearchPaths() const; + + + std::unique_ptr m_currentColorTheme; + std::unique_ptr m_currentFontTheme; + }; +} + +#endif // QBT_THEMEPROVIDER_H diff --git a/src/gui/torrentmodel.cpp b/src/gui/torrentmodel.cpp index 4feef0897b..df8f9572ea 100644 --- a/src/gui/torrentmodel.cpp +++ b/src/gui/torrentmodel.cpp @@ -29,19 +29,20 @@ * Contact : chris@qbittorrent.org */ -#include +#include "torrentmodel.h" + #include -#include +#include #include +#include #include "base/bittorrent/session.h" #include "base/bittorrent/torrenthandle.h" #include "base/torrentfilter.h" #include "base/utils/fs.h" -#include "torrentmodel.h" +#include "theme/colortheme.h" static QIcon getIconByState(BitTorrent::TorrentState state); -static QColor getColorByState(BitTorrent::TorrentState state); static QIcon getPausedIcon(); static QIcon getQueuedIcon(); @@ -53,8 +54,6 @@ static QIcon getCompletedIcon(); static QIcon getCheckingIcon(); static QIcon getErrorIcon(); -static bool isDarkTheme(); - // TorrentModel TorrentModel::TorrentModel(QObject *parent) @@ -169,7 +168,7 @@ QVariant TorrentModel::data(const QModelIndex &index, int role) const return getIconByState(torrent->state()); if (role == Qt::ForegroundRole) - return getColorByState(torrent->state()); + return Theme::ColorTheme::current().torrentStateColor(torrent->state()); if ((role != Qt::DisplayRole) && (role != Qt::UserRole)) return QVariant(); @@ -359,62 +358,6 @@ QIcon getIconByState(BitTorrent::TorrentState state) } } -QColor getColorByState(BitTorrent::TorrentState state) -{ - // Color names taken from http://cloford.com/resources/colours/500col.htm - bool dark = isDarkTheme(); - - switch (state) { - case BitTorrent::TorrentState::Downloading: - case BitTorrent::TorrentState::ForcedDownloading: - case BitTorrent::TorrentState::DownloadingMetadata: - if (!dark) - return QColor(34, 139, 34); // Forest Green - else - return QColor(50, 205, 50); // Lime Green - case BitTorrent::TorrentState::Allocating: - case BitTorrent::TorrentState::StalledDownloading: - case BitTorrent::TorrentState::StalledUploading: - if (!dark) - return QColor(0, 0, 0); // Black - else - return QColor(204, 204, 204); // Gray 80 - case BitTorrent::TorrentState::Uploading: - case BitTorrent::TorrentState::ForcedUploading: - if (!dark) - return QColor(65, 105, 225); // Royal Blue - else - return QColor(99, 184, 255); // Steel Blue 1 - case BitTorrent::TorrentState::PausedDownloading: - return QColor(250, 128, 114); // Salmon - case BitTorrent::TorrentState::PausedUploading: - if (!dark) - return QColor(0, 0, 139); // Dark Blue - else - return QColor(79, 148, 205); // Steel Blue 3 - case BitTorrent::TorrentState::Error: - case BitTorrent::TorrentState::MissingFiles: - return QColor(255, 0, 0); // red - case BitTorrent::TorrentState::QueuedDownloading: - case BitTorrent::TorrentState::QueuedUploading: - case BitTorrent::TorrentState::CheckingDownloading: - case BitTorrent::TorrentState::CheckingUploading: -#if LIBTORRENT_VERSION_NUM < 10100 - case BitTorrent::TorrentState::QueuedForChecking: -#endif - case BitTorrent::TorrentState::CheckingResumeData: - if (!dark) - return QColor(0, 128, 128); // Teal - else - return QColor(0, 205, 205); // Cyan 3 - case BitTorrent::TorrentState::Unknown: - return QColor(255, 0, 0); // red - default: - Q_ASSERT(false); - return QColor(255, 0, 0); // red - } -} - QIcon getPausedIcon() { static QIcon cached = QIcon(":/icons/skin/paused.png"); @@ -469,10 +412,3 @@ QIcon getErrorIcon() return cached; } -bool isDarkTheme() -{ - QPalette pal = QApplication::palette(); - // QPalette::Base is used for the background of the Treeview - QColor color = pal.color(QPalette::Active, QPalette::Base); - return (color.lightness() < 127); -} diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index 34d9e75a03..da9abad060 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -61,6 +61,8 @@ #include "transferlistdelegate.h" #include "transferlistsortmodel.h" #include "updownratiodlg.h" +#include "theme/fonttheme.h" +#include "theme/themeprovider.h" namespace { @@ -296,6 +298,10 @@ TransferListWidget::TransferListWidget(QWidget *parent, MainWindow *mainWindow) unused.setVerticalHeader(header()); header()->setParent(this); unused.setVerticalHeader(new QHeaderView(Qt::Horizontal)); + + applyFontTheme(); + connect(&Theme::ThemeProvider::instance(), &Theme::ThemeProvider::fontThemeChanged, + this, &TransferListWidget::applyFontTheme); } TransferListWidget::~TransferListWidget() @@ -1194,3 +1200,13 @@ void TransferListWidget::wheelEvent(QWheelEvent *event) QTreeView::wheelEvent(event); // event delegated to base class } + +void TransferListWidget::applyFontTheme() +{ + QFont font = Theme::FontTheme::current().font(Theme::FontThemeElement::TransferList); + setFont(font); + header()->setFont(font); + foreach (QWidget *widget, header()->findChildren()) { + widget->setFont(font); + } +} diff --git a/src/gui/transferlistwidget.h b/src/gui/transferlistwidget.h index 2ad24ab690..6d06598e99 100644 --- a/src/gui/transferlistwidget.h +++ b/src/gui/transferlistwidget.h @@ -120,6 +120,9 @@ protected slots: signals: void currentTorrentChanged(BitTorrent::TorrentHandle *const torrent); +private slots: + void applyFontTheme(); + private: void wheelEvent(QWheelEvent *event) override; void askAddTagsForSelection(); From 9ca461ef9d76b5e128dc5a2d22d6047ae493e466 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Sun, 7 May 2017 17:57:53 +0200 Subject: [PATCH 3/6] Add Plasma color scheme parsing --- CMakeLists.txt | 1 + configure | 28 +- configure.ac | 17 +- dist/unix/CMakeLists.txt | 6 + dist/unix/qBittorrentPlasma.colortheme | 37 ++ src/CMakeLists.txt | 5 + src/config.h.cmakein | 1 + src/gui/CMakeLists.txt | 13 + src/gui/gui.pri | 9 + src/gui/theme/colorproviders.cpp | 7 + src/gui/theme/plasmacolorprovider.cpp | 192 +++++++++++ src/gui/theme/plasmacolorprovider.h | 93 +++++ src/gui/theme/themeprovider.h | 6 +- src/gui/utils/colorutils.cpp | 328 ++++++++++++++++++ src/gui/utils/colorutils.h | 165 +++++++++ src/gui/utils/plasmacolorscheme.cpp | 456 +++++++++++++++++++++++++ src/gui/utils/plasmacolorscheme.h | 173 ++++++++++ unixconf.pri | 7 + 18 files changed, 1539 insertions(+), 5 deletions(-) create mode 100644 dist/unix/qBittorrentPlasma.colortheme create mode 100644 src/gui/theme/plasmacolorprovider.cpp create mode 100644 src/gui/theme/plasmacolorprovider.h create mode 100644 src/gui/utils/colorutils.cpp create mode 100644 src/gui/utils/colorutils.h create mode 100644 src/gui/utils/plasmacolorscheme.cpp create mode 100644 src/gui/utils/plasmacolorscheme.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 924478431d..4a35d93903 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ option(WEBUI "Allows to disable the WebUI." ON) if (WIN32) option(STACKTRACE_WIN "") else (WIN32) + option(PLASMA_INTEGRATION "Enable KDE/Plasma integration" OFF) cmake_dependent_option(SYSTEMD "Install the systemd service file (headless only)" OFF "NOT GUI" OFF) cmake_dependent_option(DBUS "Enable use of QtDBus (GUI only)" ON "GUI" OFF) diff --git a/configure b/configure index 67eb94016a..36c5a51d04 100755 --- a/configure +++ b/configure @@ -721,6 +721,7 @@ enable_gui enable_systemd enable_webui enable_qt_dbus +enable_plasma_integration with_boost with_boost_libdir with_boost_system @@ -1387,6 +1388,8 @@ Optional Features: --enable-systemd Install the systemd service file (headless only). --disable-webui Disable the WebUI. --disable-qt-dbus Disable use of QtDBus (GUI only) + --enable-plasma-integration + Enable KDE/Plasma integration Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -4221,6 +4224,14 @@ else fi +# Check whether --enable-plasma-integration was given. +if test "${enable_plasma_integration+set}" = set; then : + enableval=$enable_plasma_integration; +else + enable_plasma_integration=no +fi + + # Detect OS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OS is FreeBSD" >&5 $as_echo_n "checking whether OS is FreeBSD... " >&6; } @@ -4632,7 +4643,22 @@ $as_echo "no" >&6; } $as_echo "$enable_qt_dbus" >&6; } as_fn_error $? "Unknown option \"$enable_qt_dbus\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;; esac - +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether KDE/Plasma integration should be enabled" >&5 +$as_echo_n "checking whether KDE/Plasma integration should be enabled... " >&6; } +case "x$enable_plasma_integration" in #( + "xyes") : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + QBT_ADD_CONFIG="$QBT_ADD_CONFIG plasma_integration" ;; #( + "xno") : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG plasma_integration" ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_plasma_integration" >&5 +$as_echo "$enable_plasma_integration" >&6; } + as_fn_error $? "Unknown option \"$plasma_integration\". Use either \"yes\" or \"no\"." "$LINENO" 5 ;; +esac diff --git a/configure.ac b/configure.ac index d55156dc65..7c1c9f387c 100644 --- a/configure.ac +++ b/configure.ac @@ -48,6 +48,12 @@ AC_ARG_ENABLE(qt-dbus, [], [enable_qt_dbus=yes]) +AC_ARG_ENABLE(plasma-integration, + [AS_HELP_STRING([--enable-plasma-integration], + [Enable KDE/Plasma integration])], + [], + [enable_plasma_integration=no]) + # Detect OS AC_MSG_CHECKING([whether OS is FreeBSD]) AS_IF([expr "$host_os" : ".*freebsd.*" > /dev/null], @@ -136,7 +142,16 @@ AS_CASE(["x$enable_qt_dbus"], QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG dbus"], [AC_MSG_RESULT([$enable_qt_dbus]) AC_MSG_ERROR([Unknown option "$enable_qt_dbus". Use either "yes" or "no".])]) - +AC_MSG_CHECKING([whether KDE/Plasma integration should be enabled]) +AS_CASE(["x$enable_plasma_integration"], + ["xyes"], + [AC_MSG_RESULT([yes]) + QBT_ADD_CONFIG="$QBT_ADD_CONFIG plasma_integration"], + ["xno"], + [AC_MSG_RESULT([no]) + QBT_REMOVE_CONFIG="$QBT_REMOVE_CONFIG plasma_integration"], + [AC_MSG_RESULT([$enable_plasma_integration]) + AC_MSG_ERROR([Unknown option "$plasma_integration". Use either "yes" or "no".])]) AX_BOOST_BASE([1.35]) # HAVE_BOOST is set to an empty value when Boost is found. I don't know diff --git a/dist/unix/CMakeLists.txt b/dist/unix/CMakeLists.txt index 2dfb3f4fa5..63ecbdaf27 100644 --- a/dist/unix/CMakeLists.txt +++ b/dist/unix/CMakeLists.txt @@ -43,3 +43,9 @@ if (GUI) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status COMPONENT data) endif() + +if (PLASMA_INTEGRATION) + install(FILES qBittorrentPlasma.colortheme + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/qBittorrent/theme/ + COMPONENT data) +endif (PLASMA_INTEGRATION) diff --git a/dist/unix/qBittorrentPlasma.colortheme b/dist/unix/qBittorrentPlasma.colortheme new file mode 100644 index 0000000000..8026812a4d --- /dev/null +++ b/dist/unix/qBittorrentPlasma.colortheme @@ -0,0 +1,37 @@ +[Info] +Name=Plasma colors +Description=qBittorrent color theme which uses Plasma colors. + +[TorrentState] +Unknown=Plasma:ForegroundNegative:Disabled +Error=Plasma:ForegroundNegative +MissingFiles=Plasma:ForegroundNegative +Uploading=Plasma:ForegroundNeutral +PausedUploading=Plasma:ForegroundNeutral:Disabled +QueuedUploading=Plasma:ForegroundNeutral:Inactive +StalledUploading=Plasma:ForegroundInactive +CheckingUploading=Plasma:ForegroundActive:Inactive +ForcedUploading=Plasma:ForegroundNeutral:Active:View:Intensify +Allocating=Plasma:ForegroundInactive +Downloading=Plasma:ForegroundPositive +DownloadingMetadata=Plasma:ForegroundActive:Active:View:Reduce +PausedDownloading=Plasma:ForegroundPositive:Disabled +QueuedDownloading=Plasma:ForegroundPositive:Inactive +StalledDownloading=Plasma:ForegroundInactive +CheckingDownloading=Plasma:ForegroundActive:Inactive +ForcedDownloading=Plasma:ForegroundPositive:Active:View:Intensify +QueuedForChecking=Plasma:ForegroundActive:Inactive +CheckingResumeData=Plasma:ForegroundActive:Inactive + +[LogMessageType] +ALL=QPalette:Active:WindowText +NORMAL=QPalette:Active:WindowText +INFO=Plasma:ForegroundActive +WARNING=Plasma:ForegroundNeutral +CRITICAL=Plasma:ForegroundNegative + +[DownloadProgressBar] +Background=Plasma:BackgroundNormal +Border=Plasma:DecorationFocus +Complete=Plasma:ForegroundActive +Incomplete=Plasma:ForegroundPositive diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fc08356cea..41840a3377 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -54,6 +54,11 @@ endif (NOT WEBUI) if (STACKTRACE_WIN) add_definitions(-DSTACKTRACE_WIN) endif(STACKTRACE_WIN) + +if (PLASMA_INTEGRATION) + add_definitions(-DPLASMA_INTEGRATION) +endif (PLASMA_INTEGRATION) + # nogui { # TARGET = qbittorrent-nox # } else { diff --git a/src/config.h.cmakein b/src/config.h.cmakein index 5d6a30c32a..5486aa644c 100644 --- a/src/config.h.cmakein +++ b/src/config.h.cmakein @@ -12,3 +12,4 @@ #endif #cmakedefine STACKTRACE_WIN +#cmakedefine PLASMA_INTEGRATION diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 6b08e0c04a..9aee86abc7 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -158,6 +158,19 @@ if (WIN32 OR APPLE) list(APPEND QBT_GUI_SOURCES programupdater.cpp) endif (WIN32 OR APPLE) +if (PLASMA_INTEGRATION) + list(APPEND QBT_GUI_HEADERS + theme/plasmacolorprovider.h + utils/colorutils.h + utils/plasmacolorscheme.h + ) + list(APPEND QBT_GUI_SOURCES + theme/plasmacolorprovider.cpp + utils/colorutils.cpp + utils/plasmacolorscheme.cpp + ) +endif (PLASMA_INTEGRATION) + set(QBT_GUI_FORMS mainwindow.ui about.ui diff --git a/src/gui/gui.pri b/src/gui/gui.pri index 59675b0729..48e5556555 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -156,6 +156,15 @@ macx { OBJECTIVE_SOURCES += $$PWD/macutilities.mm } +plasma_integration { + HEADERS += $$PWD/theme/plasmacolorprovider.h \ + $$PWD/utils/colorutils.h \ + $$PWD/utils/plasmacolorscheme.h + SOURCES += $$PWD/theme/plasmacolorprovider.cpp \ + $$PWD/utils/colorutils.cpp \ + $$PWD/utils/plasmacolorscheme.cpp +} + FORMS += \ $$PWD/mainwindow.ui \ $$PWD/about.ui \ diff --git a/src/gui/theme/colorproviders.cpp b/src/gui/theme/colorproviders.cpp index 60bdf0c5fd..e8b462ba31 100644 --- a/src/gui/theme/colorproviders.cpp +++ b/src/gui/theme/colorproviders.cpp @@ -30,6 +30,10 @@ #include +#ifdef PLASMA_INTEGRATION +#include "plasmacolorprovider.h" +#endif + namespace { struct ColorProvidersRegistrator @@ -60,6 +64,9 @@ namespace void Theme::Serialization::registerColorProviders() { static ColorProvidersRegistrator colorProvidersRegistrator; +#ifdef PLASMA_INTEGRATION + registerPlasmaColorProviders(); +#endif } Theme::Serialization::ExplicitColor::ExplicitColor(const QColor &color) diff --git a/src/gui/theme/plasmacolorprovider.cpp b/src/gui/theme/plasmacolorprovider.cpp new file mode 100644 index 0000000000..dec3fa1258 --- /dev/null +++ b/src/gui/theme/plasmacolorprovider.cpp @@ -0,0 +1,192 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "plasmacolorprovider.h" + +#include + +#include "utils/colorutils.h" +#include "utils/plasmacolorscheme.h" + +namespace +{ + struct ColorProvidersRegistrator + { + ColorProvidersRegistrator() + { + using Registry = Theme::Serialization::ColorsProviderRegistry; + using ProviderUPtr = Registry::ProviderUPtr; + + Registry::instance().registerProvider(ProviderUPtr(new Theme::Serialization::PlasmaColorProvider())); + } + }; + + const QMetaEnum &QPaletteGroupMeta() + { + static QMetaEnum res = QMetaEnum::fromType(); + return res; + } + + const QMetaEnum &plasmaColorSetMeta() + { + static QMetaEnum res = QMetaEnum::fromType(); + return res; + } + + const QMetaEnum &plasmaColorRoleMeta() + { + static QMetaEnum res = QMetaEnum::fromType(); + return res; + } + + const QMetaEnum &enhancementMeta() + { + static QMetaEnum res = QMetaEnum::fromType(); + return res; + } + + QColor lighten(const QColor &c) + { + return Utils::Color::lighten(c, 0.25); + } + + QColor darken(const QColor &c) + { + return Utils::Color::darken(c, 0.25); + } +} + +std::unique_ptr Theme::Serialization::PlasmaColor::m_colorSheme; +Theme::Serialization::PlasmaColor::ColorCorrectionFunc Theme::Serialization::PlasmaColor::m_intencifyColor; +Theme::Serialization::PlasmaColor::ColorCorrectionFunc Theme::Serialization::PlasmaColor::m_reduceColor; + +void Theme::Serialization::registerPlasmaColorProviders() +{ + static ColorProvidersRegistrator registrator; +} + +Theme::Serialization::PlasmaColor::PlasmaColor(QPalette::ColorGroup group, + PlasmaColorScheme::ColorSet set, + PlasmaColorScheme::ColorRole role) + : m_group {group} + , m_set {set} + , m_role {role} +{ +} + +namespace { + template + Enum stringToEnum(const QString &str, const QMetaEnum &meta) + { + bool ok = false; + const int rawVal = meta.keyToValue(str.toLatin1().constData(), &ok); + if (!ok) { + throw std::runtime_error("Can not parse " + str.toStdString() + " into " + meta.name()); + } + return static_cast(rawVal); + } +} + +Theme::Serialization::PlasmaColor::PlasmaColor(const QString& serialized) +{ + const auto list = serialized.split(QLatin1Char(':')); + if (list.size() < 1 || list.size() > 4) + throw ValueParsingError("Plasma color notation should have 1 or 4 components", serialized); + + try { + m_role = stringToEnum(list[0], plasmaColorRoleMeta()); + m_group = list.size() > 1 ? stringToEnum(list[1], QPaletteGroupMeta()) + : QPalette::Active; + m_set = list.size() > 2 ? stringToEnum(list[2], plasmaColorSetMeta()) + : PlasmaColorScheme::View; + m_enhancement = list.size() > 3 ? stringToEnum(list[3], enhancementMeta()) + : Enhancement::None; + } + catch (std::runtime_error&) { + throw ValueParsingError("Could not parse Plasma color", serialized); + } +} + +void Theme::Serialization::PlasmaColor::reloadDefaultPalette() +{ + if (!m_colorSheme) { + m_colorSheme.reset(new PlasmaColorScheme()); + } + else { + m_colorSheme->reload(); + } + const bool isDarkTheme = Theme::isDarkTheme(); + m_intencifyColor = isDarkTheme ? &lighten : &darken; + m_reduceColor = isDarkTheme ? &darken : &lighten; +} + +QString Theme::Serialization::PlasmaColor::serializationKey() const +{ + return QLatin1String("Plasma"); +} + +QString Theme::Serialization::PlasmaColor::serializedValue() const +{ + return QString(QLatin1String("%1:%2:%3:4%")) + .arg(plasmaColorRoleMeta().key(m_role)) + .arg(QPaletteGroupMeta().key(m_group)) + .arg(plasmaColorSetMeta().key(m_set)) + .arg(enhancementMeta().key(static_cast(m_enhancement))); +} + +QColor Theme::Serialization::PlasmaColor::value() const +{ + QColor c = m_colorSheme->color(m_role, m_group, m_set); + switch (m_enhancement) { + case Enhancement::None: + return c; + case Enhancement::Intensify: + return m_intencifyColor(c); + case Enhancement::Reduce: + return m_reduceColor(c); + default: + throw std::runtime_error("Unexpected value of m_enhancement"); + } +} + +Theme::Serialization::PlasmaColorProvider::PlasmaColorProvider() + : ColorProvider(PlasmaColor(QPalette::Active, PlasmaColorScheme::View, PlasmaColorScheme::ForegroundActive).serializationKey()) +{ + PlasmaColor::reloadDefaultPalette(); +} + +void Theme::Serialization::PlasmaColorProvider::applicationPaletteChanged() const +{ + PlasmaColor::reloadDefaultPalette(); +} + +Theme::Serialization::ColorProvider::EntityUPtr +Theme::Serialization::PlasmaColorProvider::load(const QString& serialized) const +{ + return EntityUPtr(new PlasmaColor(serialized)); +} diff --git a/src/gui/theme/plasmacolorprovider.h b/src/gui/theme/plasmacolorprovider.h new file mode 100644 index 0000000000..9cbe51d950 --- /dev/null +++ b/src/gui/theme/plasmacolorprovider.h @@ -0,0 +1,93 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2017 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_THEME_PLASMACOLORPROVIDERS_H +#define QBT_THEME_PLASMACOLORPROVIDERS_H + +#include "colorprovider_p.h" +#include "utils/plasmacolorscheme.h" + +class QWidget; + +namespace Theme +{ + namespace Serialization + { + void registerPlasmaColorProviders(); + + /** + * @brief Provides colors from Plasma color scheme + * + */ + class PlasmaColor: public Color + { + Q_GADGET + public: + enum class Enhancement + { + None, + Intensify, + Reduce + }; + + Q_ENUM(Enhancement) + + explicit PlasmaColor(QPalette::ColorGroup group, PlasmaColorScheme::ColorSet set, PlasmaColorScheme::ColorRole role); + explicit PlasmaColor(const QString &serialized); + + QColor value() const override; + QString serializedValue() const override; + QString serializationKey() const override; + + static void reloadDefaultPalette(); + + private: + using ColorCorrectionFunc = QColor (*)(const QColor&); + static ColorCorrectionFunc m_intencifyColor; + static ColorCorrectionFunc m_reduceColor; + + static std::unique_ptr m_colorSheme; + QPalette::ColorGroup m_group; + PlasmaColorScheme::ColorSet m_set; + PlasmaColorScheme::ColorRole m_role; + Enhancement m_enhancement; + }; + + class PlasmaColorProvider: public ColorProvider + { + public: + PlasmaColorProvider(); + + private: + ColorProvider::EntityUPtr load(const QString &serialized) const override; + void applicationPaletteChanged() const override; + }; + } +} + +#endif // QBT_THEME_PLASMACOLORPROVIDERS_H diff --git a/src/gui/theme/themeprovider.h b/src/gui/theme/themeprovider.h index fed3b731ab..d2c87c9fbf 100644 --- a/src/gui/theme/themeprovider.h +++ b/src/gui/theme/themeprovider.h @@ -57,9 +57,9 @@ namespace Theme static ThemeProvider &instance(); /** - * @brief Collection of available colour themes + * @brief Collection of available color themes * - * @returns map them info object -> file path + * @returns map theme info object -> file path */ std::map availableThemes(Kind kind) const; @@ -110,7 +110,7 @@ namespace Theme /** * @brief Theme search paths arranged by priority * - * @return QStringList with paths. The firs one is of highest priority. + * @return QStringList with paths. The first one is of highest priority. */ QStringList themeSearchPaths() const; diff --git a/src/gui/utils/colorutils.cpp b/src/gui/utils/colorutils.cpp new file mode 100644 index 0000000000..9cf3740ed4 --- /dev/null +++ b/src/gui/utils/colorutils.cpp @@ -0,0 +1,328 @@ +/* This file is composed from stripped versions of + * kcolorutils.cpp, kguiaddons_colorhelpers_p.h, + * kcolorspaces_p.h, and kcolorspaces.cpp + * + * This file is part of the KDE project + * Copyright (C) 2007 Matthew Woehlke + * Copyright (C) 2007 Thomas Zander + * Copyright (C) 2007 Zack Rusin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#include "colorutils.h" + +#include +#include + +#include // qIsNaN + +#include + +// BEGIN internal helper functions +namespace { + // normalize: like qBound(a, 0.0, 1.0) but without needing the args and with + // "safer" behavior on NaN (isnan(a) -> return 0.0) + inline qreal normalize(qreal a) + { + return (a < 1.0 ? (a > 0.0 ? a : 0.0) : 1.0); + } + + inline qreal mixQreal(qreal a, qreal b, qreal bias) + { + return a + (b - a) * bias; + } + + inline qreal wrap(qreal a, qreal d = 1.0) + { + qreal r = fmod(a, d); + return (r < 0.0 ? d + r : (r > 0.0 ? r : 0.0)); + } + + // END internal helper functions + + class HCY + { + public: + explicit HCY(const QColor &); + explicit HCY(qreal h_, qreal c_, qreal y_, qreal a_ = 1.0); + QColor qColor() const; + qreal h, c, y, a; + static qreal luma(const QColor &); + private: + static qreal gamma(qreal); + static qreal igamma(qreal); + static qreal lumag(qreal, qreal, qreal); + }; + + /////////////////////////////////////////////////////////////////////////////// + // HCY color space + +#define HCY_REC 709 // use 709 for now +#if HCY_REC == 601 + static const qreal yc[3] = { 0.299, 0.587, 0.114 }; +#elif HCY_REC == 709 + static const qreal yc[3] = {0.2126, 0.7152, 0.0722}; +#else // use Qt values + static const qreal yc[3] = { 0.34375, 0.5, 0.15625 }; +#endif + + qreal HCY::gamma(qreal n) + { + return pow(normalize(n), 2.2); + } + + qreal HCY::igamma(qreal n) + { + return pow(normalize(n), 1.0 / 2.2); + } + + qreal HCY::lumag(qreal r, qreal g, qreal b) + { + return r * yc[0] + g * yc[1] + b * yc[2]; + } + +#if 0 + HCY::HCY(qreal h_, qreal c_, qreal y_, qreal a_) + { + h = h_; + c = c_; + y = y_; + a = a_; + } +#endif + + HCY::HCY(const QColor &color) + { + qreal r = gamma(color.redF()); + qreal g = gamma(color.greenF()); + qreal b = gamma(color.blueF()); + a = color.alphaF(); + + // luma component + y = lumag(r, g, b); + + // hue component + qreal p = qMax(qMax(r, g), b); + qreal n = qMin(qMin(r, g), b); + qreal d = 6.0 * (p - n); + if (n == p) + h = 0.0; + else if (r == p) + h = ((g - b) / d); + else if (g == p) + h = ((b - r) / d) + (1.0 / 3.0); + else + h = ((r - g) / d) + (2.0 / 3.0); + + // chroma component + if (( r == g) && ( g == b) ) + c = 0.0; + else + c = qMax((y - n) / y, (p - y) / (1 - y)); + } + + QColor HCY::qColor() const + { + // start with sane component values + qreal _h = wrap(h); + qreal _c = normalize(c); + qreal _y = normalize(y); + + // calculate some needed variables + qreal _hs = _h * 6.0, th, tm; + if (_hs < 1.0) { + th = _hs; + tm = yc[0] + yc[1] * th; + } + else if (_hs < 2.0) { + th = 2.0 - _hs; + tm = yc[1] + yc[0] * th; + } + else if (_hs < 3.0) { + th = _hs - 2.0; + tm = yc[1] + yc[2] * th; + } + else if (_hs < 4.0) { + th = 4.0 - _hs; + tm = yc[2] + yc[1] * th; + } + else if (_hs < 5.0) { + th = _hs - 4.0; + tm = yc[2] + yc[0] * th; + } + else { + th = 6.0 - _hs; + tm = yc[0] + yc[2] * th; + } + + // calculate RGB channels in sorted order + qreal tn, to, tp; + if (tm >= _y) { + tp = _y + _y * _c * (1.0 - tm) / tm; + to = _y + _y * _c * (th - tm) / tm; + tn = _y - (_y * _c); + } + else { + tp = _y + (1.0 - _y) * _c; + to = _y + (1.0 - _y) * _c * (th - tm) / (1.0 - tm); + tn = _y - (1.0 - _y) * _c * tm / (1.0 - tm); + } + + // return RGB channels in appropriate order + if (_hs < 1.0) + return QColor::fromRgbF(igamma(tp), igamma(to), igamma(tn), a); + else if (_hs < 2.0) + return QColor::fromRgbF(igamma(to), igamma(tp), igamma(tn), a); + else if (_hs < 3.0) + return QColor::fromRgbF(igamma(tn), igamma(tp), igamma(to), a); + else if (_hs < 4.0) + return QColor::fromRgbF(igamma(tn), igamma(to), igamma(tp), a); + else if (_hs < 5.0) + return QColor::fromRgbF(igamma(to), igamma(tn), igamma(tp), a); + else + return QColor::fromRgbF(igamma(tp), igamma(tn), igamma(to), a); + } + + qreal HCY::luma(const QColor &color) + { + return lumag(gamma(color.redF()), + gamma(color.greenF()), + gamma(color.blueF())); + } + +} + +qreal Utils::Color::luma(const QColor &color) +{ + return HCY::luma(color); +} + +void Utils::Color::getHcy(const QColor &color, qreal *h, qreal *c, qreal *y, qreal *a) +{ + if (!c || !h || !y) + return; + HCY khcy(color); + *c = khcy.c; + *h = khcy.h; + *y = khcy.y; + if (a) + *a = khcy.a; +} + +static qreal contrastRatioForLuma(qreal y1, qreal y2) +{ + if (y1 > y2) + return (y1 + 0.05) / (y2 + 0.05); + else + return (y2 + 0.05) / (y1 + 0.05); +} + +qreal Utils::Color::contrastRatio(const QColor &c1, const QColor &c2) +{ + return contrastRatioForLuma(luma(c1), luma(c2)); +} + +QColor Utils::Color::lighten(const QColor &color, qreal ky, qreal kc) +{ + HCY c(color); + c.y = 1.0 - normalize((1.0 - c.y) * (1.0 - ky)); + c.c = 1.0 - normalize((1.0 - c.c) * kc); + return c.qColor(); +} + +QColor Utils::Color::darken(const QColor &color, qreal ky, qreal kc) +{ + HCY c(color); + c.y = normalize(c.y * (1.0 - ky)); + c.c = normalize(c.c * kc); + return c.qColor(); +} + +QColor Utils::Color::shade(const QColor &color, qreal ky, qreal kc) +{ + HCY c(color); + c.y = normalize(c.y + ky); + c.c = normalize(c.c + kc); + return c.qColor(); +} + +static QColor tintHelper(const QColor &base, qreal baseLuma, const QColor &color, qreal amount) +{ + HCY result(Utils::Color::mix(base, color, pow(amount, 0.3))); + result.y = mixQreal(baseLuma, result.y, amount); + + return result.qColor(); +} + +QColor Utils::Color::tint(const QColor &base, const QColor &color, qreal amount) +{ + if (amount <= 0.0) + return base; + if (amount >= 1.0) + return color; + if (qIsNaN(amount)) + return base; + + qreal baseLuma = luma(base); //cache value because luma call is expensive + double ri = contrastRatioForLuma(baseLuma, luma(color)); + double rg = 1.0 + ((ri + 1.0) * amount * amount * amount); + double u = 1.0, l = 0.0; + QColor result; + for (int i = 12; i; --i) { + double a = 0.5 * (l + u); + result = tintHelper(base, baseLuma, color, a); + double ra = contrastRatioForLuma(baseLuma, luma(result)); + if (ra > rg) + u = a; + else + l = a; + } + return result; +} + +QColor Utils::Color::mix(const QColor &c1, const QColor &c2, qreal bias) +{ + if (bias <= 0.0) + return c1; + if (bias >= 1.0) + return c2; + if (qIsNaN(bias)) + return c1; + + qreal r = mixQreal(c1.redF(), c2.redF(), bias); + qreal g = mixQreal(c1.greenF(), c2.greenF(), bias); + qreal b = mixQreal(c1.blueF(), c2.blueF(), bias); + qreal a = mixQreal(c1.alphaF(), c2.alphaF(), bias); + + return QColor::fromRgbF(r, g, b, a); +} + +QColor Utils::Color::overlayColors(const QColor &base, const QColor &paint, + QPainter::CompositionMode comp) +{ + // This isn't the fastest way, but should be "fast enough". + // It's also the only safe way to use QPainter::CompositionMode + QImage img(1, 1, QImage::Format_ARGB32_Premultiplied); + QPainter p(&img); + QColor start = base; + start.setAlpha(255); // opaque + p.fillRect(0, 0, 1, 1, start); + p.setCompositionMode(comp); + p.fillRect(0, 0, 1, 1, paint); + p.end(); + return img.pixel(0, 0); +} + diff --git a/src/gui/utils/colorutils.h b/src/gui/utils/colorutils.h new file mode 100644 index 0000000000..0f9223a732 --- /dev/null +++ b/src/gui/utils/colorutils.h @@ -0,0 +1,165 @@ +/* This is the stripped version of the file kcolorutils.h + * from KDE framework KGuiAddons. + * + * This file is part of the KDE project + * Copyright (C) 2007 Matthew Woehlke + * Copyright (C) 2007 Thomas Zander + * Copyright (C) 2007 Zack Rusin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef COLORUTILS_H +#define COLORUTILS_H + +#include + +class QColor; + +/** + * A set of methods used to work with colors. + */ +namespace Utils +{ + namespace Color + { + /** + * Calculate the luma of a color. Luma is weighted sum of gamma-adjusted + * R'G'B' components of a color. The result is similar to qGray. The range + * is from 0.0 (black) to 1.0 (white). + * + * Utils::Color::darken(), Utils::Color::lighten() and Utils::Color::shade() + * operate on the luma of a color. + * + * @see http://en.wikipedia.org/wiki/Luma_(video) + */ + qreal luma(const QColor &); + + /** + * Calculate hue, chroma and luma of a color in one call. + */ + void getHcy(const QColor &, qreal *hue, qreal *chroma, qreal *luma, qreal *alpha = 0); + + /** + * Calculate the contrast ratio between two colors, according to the + * W3C/WCAG2.0 algorithm, (Lmax + 0.05)/(Lmin + 0.05), where Lmax and Lmin + * are the luma values of the lighter color and the darker color, + * respectively. + * + * A contrast ration of 5:1 (result == 5.0) is the minimum for "normal" + * text to be considered readable (large text can go as low as 3:1). The + * ratio ranges from 1:1 (result == 1.0) to 21:1 (result == 21.0). + * + * @see Utils::Color::luma + */ + qreal contrastRatio(const QColor &, const QColor &); + + /** + * Adjust the luma of a color by changing its distance from white. + * + * @li amount == 1.0 gives white + * @li amount == 0.5 results in a color whose luma is halfway between 1.0 + * and that of the original color + * @li amount == 0.0 gives the original color + * @li amount == -1.0 gives a color that is 'twice as far from white' as + * the original color, that is luma(result) == 1.0 - 2*(1.0 - luma(color)) + * + * @param amount factor by which to adjust the luma component of the color + * @param chromaInverseGain (optional) factor by which to adjust the chroma + * component of the color; 1.0 means no change, 0.0 maximizes chroma + * @see Utils::Color::shade + */ + QColor lighten(const QColor &, qreal amount = 0.5, qreal chromaInverseGain = 1.0); + + /** + * Adjust the luma of a color by changing its distance from black. + * + * @li amount == 1.0 gives black + * @li amount == 0.5 results in a color whose luma is halfway between 0.0 + * and that of the original color + * @li amount == 0.0 gives the original color + * @li amount == -1.0 gives a color that is 'twice as far from black' as + * the original color, that is luma(result) == 2*luma(color) + * + * @param amount factor by which to adjust the luma component of the color + * @param chromaGain (optional) factor by which to adjust the chroma + * component of the color; 1.0 means no change, 0.0 minimizes chroma + * @see Utils::Color::shade + */ + QColor darken(const QColor &, qreal amount = 0.5, qreal chromaGain = 1.0); + + /** + * Adjust the luma and chroma components of a color. The amount is added + * to the corresponding component. + * + * @param lumaAmount amount by which to adjust the luma component of the + * color; 0.0 results in no change, -1.0 turns anything black, 1.0 turns + * anything white + * @param chromaAmount (optional) amount by which to adjust the chroma + * component of the color; 0.0 results in no change, -1.0 minimizes chroma, + * 1.0 maximizes chroma + * @see Utils::Color::luma + */ + QColor shade(const QColor &, qreal lumaAmount, qreal chromaAmount = 0.0); + + /** + * Create a new color by tinting one color with another. This function is + * meant for creating additional colors withings the same class (background, + * foreground) from colors in a different class. Therefore when @p amount + * is low, the luma of @p base is mostly preserved, while the hue and + * chroma of @p color is mostly inherited. + * + * @param base color to be tinted + * @param color color with which to tint + * @param amount how strongly to tint the base; 0.0 gives @p base, + * 1.0 gives @p color + */ + QColor tint(const QColor &base, const QColor &color, qreal amount = 0.3); + + /** + * Blend two colors into a new color by linear combination. + * @code + QColor lighter = Utils::Color::mix(myColor, Qt::white) + * @endcode + * @param c1 first color. + * @param c2 second color. + * @param bias weight to be used for the mix. @p bias <= 0 gives @p c1, + * @p bias >= 1 gives @p c2. @p bias == 0.5 gives a 50% blend of @p c1 + * and @p c2. + */ + QColor mix(const QColor &c1, const QColor &c2, + qreal bias = 0.5); + + /** + * Blend two colors into a new color by painting the second color over the + * first using the specified composition mode. + * @code + QColor white(Qt::white); + white.setAlphaF(0.5); + QColor lighter = Utils::Color::overlayColors(myColor, white); + @endcode + * @param base the base color (alpha channel is ignored). + * @param paint the color to be overlayed onto the base color. + * @param comp the CompositionMode used to do the blending. + */ + QColor overlayColors(const QColor &base, const QColor &paint, + QPainter::CompositionMode comp = QPainter::CompositionMode_SourceOver); + + } +} + +#endif // COLORUTILS_H + diff --git a/src/gui/utils/plasmacolorscheme.cpp b/src/gui/utils/plasmacolorscheme.cpp new file mode 100644 index 0000000000..a3c41d17d8 --- /dev/null +++ b/src/gui/utils/plasmacolorscheme.cpp @@ -0,0 +1,456 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "plasmacolorscheme.h" + +#include + +#include +#include +#include +#include +#include + +#include "colorutils.h" + +namespace +{ + class KDEColorThemeDecodingError: public std::runtime_error + { + public: + KDEColorThemeDecodingError(const QString& entryName); + const QString &entryName() const; + + private: + QString m_entryName; + }; + + KDEColorThemeDecodingError::KDEColorThemeDecodingError(const QString& entryName) + : std::runtime_error("Could not parse color '" + entryName.toStdString() + '\'') + , m_entryName {entryName} + { + } + + const QString &KDEColorThemeDecodingError::entryName() const + { + return m_entryName; + } + + static QString settingsGroupName(PlasmaColorScheme::ColorSet set) + { + switch (set) { + case PlasmaColorScheme::View: + return QLatin1String("Colors:View"); + case PlasmaColorScheme::Window: + return QLatin1String("Colors:Window"); + case PlasmaColorScheme::Button: + return QLatin1String("Colors:Button"); + case PlasmaColorScheme::Selection: + return QLatin1String("Colors:Selection"); + case PlasmaColorScheme::Tooltip: + return QLatin1String("Colors:Tooltip"); + default: + throw std::logic_error("Unexpected value of PlasmaColorScheme::ColorSet"); + } + } + + QRgb decodeKDEColor(QSettings &settings, const QString &colorName) + { + QVariantList components(settings.value(colorName).toList()); + if (components.size() == 3) { + bool rOk, gOk, bOk; + const int r = components[0].toString().toInt(&rOk); + const int g = components[1].toString().toInt(&gOk); + const int b = components[2].toString().toInt(&bOk); + if (rOk && gOk && bOk) { + return qRgb(r, g, b); + } + } + throw KDEColorThemeDecodingError(colorName); + } + + class SettingsGroupGuard + { + public: + SettingsGroupGuard(QSettings &settings, const QString &groupName); + ~SettingsGroupGuard(); + + private: + QSettings &m_settings; + }; + + SettingsGroupGuard::SettingsGroupGuard(QSettings& settings, const QString& groupName) + : m_settings(settings) + { + m_settings.beginGroup(groupName); + } + + SettingsGroupGuard::~SettingsGroupGuard() + { + m_settings.endGroup(); + } + + template + T readValue(QSettings &settings, const QString &key, const T &defaultValue = T()) + { + QVariant v = settings.value(key, defaultValue); + if (v.canConvert()) { + return v.value(); + } + throw KDEColorThemeDecodingError(key); + } + + PlasmaColorScheme::Effect readColorEffect(QSettings &settings, const QString &name) + { + using Effect = PlasmaColorScheme::Effect; + Effect res; + + SettingsGroupGuard group(settings, QLatin1String("ColorEffects:") + name); + + res.changeSelectionColor = settings.value(QLatin1String("ChangeSelectionColor"), false).toBool(); + res.color = decodeKDEColor(settings, QLatin1String("Color")); + res.colorAmount = readValue(settings, QLatin1String("ColorAmount")); + res.colorEffect = static_cast(readValue(settings, QLatin1String("ColorEffect"))); + res.contrastAmount = readValue(settings, QLatin1String("ContrastAmount")); + res.contrastEffect = static_cast(readValue(settings, QLatin1String("ContrastEffect"))); + res.enable = readValue(settings, QLatin1String("Enable"), false); + res.intensityAmount = readValue(settings, QLatin1String("IntensityAmount")); + res.intensityEffect = static_cast(readValue(settings, QLatin1String("IntensityEffect"))); + return res; + } + + QColor applyColorEffect(const QColor &color, const PlasmaColorScheme::Effect &effect) + { + using Effect = PlasmaColorScheme::Effect; + QColor res(color); + + switch (effect.intensityEffect) { + case Effect::IntensityEffectNone: + break; + case Effect::IntensityEffectShade: + res = Utils::Color::shade(res, effect.intensityAmount); + break; + case Effect::IntensityEffectDarken: + res = Utils::Color::darken(res, effect.intensityAmount); + break; + case Effect::IntensityEffectLighten: + res = Utils::Color::lighten(res, effect.intensityAmount); + break; + } + + switch (effect.colorEffect) { + case Effect::ColorEffectNone: + break; + case Effect::ColorEffectDesaturate: + res = Utils::Color::darken(res, 0., 1.0 - effect.colorAmount); + break; + case Effect::ColorEffectFade: + res = Utils::Color::mix(res, effect.color, effect.colorAmount); + break; + case Effect::ColorEffectTint: + res = Utils::Color::tint(res, effect.color, effect.colorAmount); + break; + } + +#if 0 + // shall we worry about contrast with background at all? + switch (effect.contrastEffect) { + case KDEColorEffect::ContrastEffectNone: + break; + case KDEColorEffect::ContrastEffectFade: + res = Utils::Color::mix(res, bgColor, effect.contrastAmount); + break; + case KDEColorEffect::ContrastEffectTint: + res = Utils::Color::tint(res, bgColor, effect.contrastAmount); + break; + } +#endif + return res; + } + + class ColorLoadingError: public std::runtime_error + { + public: + ColorLoadingError() : std::runtime_error(""){} + }; +} + +Q_GLOBAL_STATIC(PlasmaColorScheme, kdeColorScheme) + +const PlasmaColorScheme *PlasmaColorScheme::instance() +{ + return kdeColorScheme; +} + +PlasmaColorScheme::PlasmaColorScheme(const QProcessEnvironment& env) +{ + reload(env); +} + +void PlasmaColorScheme::reload(const QProcessEnvironment& env) +{ + try { + load(env); + m_loadedSuccesfully = true; + } + catch (ColorLoadingError&) { + qDebug() << "Could not load Plasma color theme. Falling back to QPalette"; + m_loadedSuccesfully = false; + setFallbackColors(); + } +} + +QColor PlasmaColorScheme::color(PlasmaColorScheme::ColorRole role, QPalette::ColorGroup group, PlasmaColorScheme::ColorSet set) const +{ + if (group > QPalette::Inactive) + return Qt::black; + + return m_colors[group][set][role]; +} + +QColor PlasmaColorScheme::inactiveColor(const QColor& color) const +{ + return applyColorEffect(color, m_inactiveEffect); +} + +QColor PlasmaColorScheme::disabledColor(const QColor& color) const +{ + return applyColorEffect(color, m_disabledEffect); +} + +bool PlasmaColorScheme::wasLoadedSuccesfully() const +{ + return m_loadedSuccesfully; +} + +void PlasmaColorScheme::load(const QProcessEnvironment& env) +{ + bool versionDecodedOk = false; + int kdeVersion = env.value(QLatin1String("KDE_SESSION_VERSION"), QLatin1String("4")) + .toInt(&versionDecodedOk); + if (!versionDecodedOk) + throw ColorLoadingError(); + QString kdeCfgFile; + switch (kdeVersion) { + case 4: + kdeCfgFile = QLatin1String(".kde4/share/config/kdeglobals"); + break; + case 5: + kdeCfgFile = QLatin1String(".config/kdeglobals"); + break; + default: + throw ColorLoadingError(); + } + + QString configPath = QDir(QDir::homePath()).absoluteFilePath(kdeCfgFile); + if (!QFileInfo(configPath).exists()) + throw ColorLoadingError(); + + QSettings kdeGlobals(configPath, QSettings::IniFormat); + ColorsSet activeColors; + try { + activeColors[View] = readSet(kdeGlobals, View); + activeColors[Window] = readSet(kdeGlobals, Window); + activeColors[Button] = readSet(kdeGlobals, Button); + activeColors[Selection] = readSet(kdeGlobals, Selection); + activeColors[Tooltip] = readSet(kdeGlobals, Tooltip); + } + catch (KDEColorThemeDecodingError& ex) { + qDebug("Could not parse KDE/Plasma color scheme: %s", ex.what()); + throw ColorLoadingError(); + } + + m_colors[QPalette::Active] = activeColors; + + try { + m_inactiveEffect = readColorEffect(kdeGlobals, QLatin1String("Inactive")); + m_disabledEffect = readColorEffect(kdeGlobals, QLatin1String("Disabled")); + } + catch (KDEColorThemeDecodingError&) { + // perhaps we have recent enough Plasma and effects were not copied to .kdeglobals, + // we have to load them from theme file + const QString themeName = kdeGlobals.value(QLatin1String("ColorScheme"), QString()).toString(); + if (themeName.isEmpty()) { + throw ColorLoadingError(); // we do not know theme name + } + const QString themeFileName = locateColorThemeFile(themeName); + if (themeFileName.isEmpty()) { + qDebug("Could not find file for Plasma color theme '%s'", qPrintable(themeName)); + throw ColorLoadingError(); + } + QSettings theme(themeFileName, QSettings::IniFormat); + try { + m_inactiveEffect = readColorEffect(theme, QLatin1String("Inactive")); + m_disabledEffect = readColorEffect(theme, QLatin1String("Disabled")); + } + catch (KDEColorThemeDecodingError& ex) { + // no luck, we give up + qDebug("Could not load effects from theme file '%s': %s", qPrintable(themeFileName), ex.what()); + throw ColorLoadingError(); + } + } + + m_colors[QPalette::Inactive] = applyEffect(activeColors, m_inactiveEffect); + m_colors[QPalette::Disabled] = applyEffect(activeColors, m_disabledEffect); +} + + +PlasmaColorScheme::ColorsMap PlasmaColorScheme::readSet(QSettings& settings, PlasmaColorScheme::ColorSet set) +{ + ColorsMap colors; + + try { + SettingsGroupGuard group(settings, settingsGroupName(set)); + colors[BackgroundAlternate] = decodeKDEColor(settings, QLatin1String("BackgroundAlternate")); + colors[BackgroundNormal] = decodeKDEColor(settings, QLatin1String("BackgroundNormal")); + colors[DecorationFocus] = decodeKDEColor(settings, QLatin1String("DecorationFocus")); + colors[ForegroundVisited] = decodeKDEColor(settings, QLatin1String("ForegroundVisited")); + colors[ForegroundNormal] = decodeKDEColor(settings, QLatin1String("ForegroundNormal")); + colors[DecorationHover] = decodeKDEColor(settings, QLatin1String("DecorationHover")); + colors[ForegroundActive] = decodeKDEColor(settings, QLatin1String("ForegroundActive")); + colors[ForegroundInactive] = decodeKDEColor(settings, QLatin1String("ForegroundInactive")); + colors[ForegroundLink] = decodeKDEColor(settings, QLatin1String("ForegroundLink")); + colors[ForegroundNegative] = decodeKDEColor(settings, QLatin1String("ForegroundNegative")); + colors[ForegroundNeutral] = decodeKDEColor(settings, QLatin1String("ForegroundNeutral")); + colors[ForegroundPositive] = decodeKDEColor(settings, QLatin1String("ForegroundPositive")); + + return colors; + } + catch (KDEColorThemeDecodingError &ex) { + throw KDEColorThemeDecodingError(settingsGroupName(set) + QLatin1Char('/') + ex.entryName()); + } +} + +void PlasmaColorScheme::setFallbackColors() +{ + m_colors[QPalette::Active] = fallbackColorSet(QPalette::Active); + m_colors[QPalette::Disabled] = fallbackColorSet(QPalette::Disabled); + m_colors[QPalette::Inactive] = fallbackColorSet(QPalette::Inactive); +} + +PlasmaColorScheme::ColorsSet PlasmaColorScheme::fallbackColorSet(QPalette::ColorGroup group) +{ + QPalette palette = QApplication::palette(); + ColorsMap view; + view[BackgroundAlternate] = palette.color(group, QPalette::AlternateBase); + view[BackgroundNormal] = palette.color(group, QPalette::Background); + view[DecorationFocus] = palette.color(group, QPalette::HighlightedText); + view[DecorationHover] = palette.color(group, QPalette::Highlight); + view[ForegroundActive] = palette.color(group, QPalette::Text); + view[ForegroundInactive] = palette.color(group, QPalette::Text); + view[ForegroundLink] = palette.color(group, QPalette::Link); + view[ForegroundNegative] = palette.color(group, QPalette::Text); + view[ForegroundNeutral] = palette.color(group, QPalette::Text); + view[ForegroundNormal] = palette.color(group, QPalette::Text); + view[ForegroundPositive] = palette.color(group, QPalette::Text); + view[ForegroundVisited] = palette.color(group, QPalette::LinkVisited); + + ColorsMap window = {view}; + window[BackgroundNormal] = window[BackgroundAlternate] = palette.color(group, QPalette::Window); + + ColorsMap button = {view}; + button[BackgroundNormal] = button[BackgroundAlternate] = palette.color(group, QPalette::Button); + button[ForegroundActive] = palette.color(group, QPalette::ButtonText); + button[ForegroundInactive] = palette.color(group, QPalette::ButtonText); + + ColorsMap tooltip = {view}; + tooltip[BackgroundNormal] = tooltip[BackgroundAlternate] = palette.color(group, QPalette::ToolTipBase); + tooltip[ForegroundActive] = tooltip[ForegroundInactive] = palette.color(group, QPalette::ToolTipText); + tooltip[ForegroundNegative] = tooltip[ForegroundNeutral] = palette.color(group, QPalette::ToolTipText); + tooltip[ForegroundNormal] = tooltip[ForegroundPositive] = palette.color(group, QPalette::ToolTipText); + + ColorsSet res; + res.insert(View, view); + res.insert(Window, window); + res.insert(Button, button); + res.insert(Tooltip, tooltip); + res.insert(Selection, view); + + return res; +} + +PlasmaColorScheme::ColorsSet PlasmaColorScheme::applyEffect(const PlasmaColorScheme::ColorsSet& set, const PlasmaColorScheme::Effect& effect) +{ + ColorsSet res; + for (auto i = set.begin(); i != set.end(); ++i) { + ColorsMap resMap; + const ColorsMap &srcMap = i.value(); + for (auto j = srcMap.begin(); j != srcMap.end(); ++j) + resMap[j.key()] = applyColorEffect(j.value(), effect); + res.insert(i.key(), resMap); + } + + return res; +} + +QString PlasmaColorScheme::locateColorThemeFile(const QString &themeName) +{ + // Plasma themes are located in share/color-schemes + // Usually file name is equal to ${themeName}.colors with + // first character uppercased. However, it is not guaranteed + // and we have to check Name key in the files + + QLatin1String colorShemesDirName("color-schemes"); + // let's go + // 1. uppercase first letter of the theme name and try to find such file + QString probableThemeFileName = themeName; + probableThemeFileName[0] = probableThemeFileName[0].toUpper(); + const QLatin1String themeFileExtension(".colors"); + + const QStringList probableThemes = QStandardPaths::locateAll( + QStandardPaths::GenericDataLocation, colorShemesDirName + QLatin1Char('/') + probableThemeFileName + themeFileExtension); + + // 2. this is our test function to check "Name=" key of the file + const auto checkThemeName = [&](const QString &file) + { + QSettings theme(file, QSettings::IniFormat); + return theme.value(QLatin1String("Name"), QString()).toString() == themeName; + }; + + for (const QString &f: probableThemes) { + if (checkThemeName(f)) { + return f; + } + } + + // 3. we have no other choice but to try all the files + const QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); + for (const QString &dir: dirs) { + QDir colorShemesDir(dir + QLatin1Char('/') + colorShemesDirName); + if (colorShemesDir.exists()) { + const QStringList files = colorShemesDir.entryList({QLatin1Char('*') + themeFileExtension}, QDir::Files); + for (const QString &f: files) { + if (checkThemeName(colorShemesDir.absoluteFilePath(f))) { + return colorShemesDir.absoluteFilePath(f); + } + } + } + } + // we failed to find theme file + return {}; +} diff --git a/src/gui/utils/plasmacolorscheme.h b/src/gui/utils/plasmacolorscheme.h new file mode 100644 index 0000000000..b212348cf0 --- /dev/null +++ b/src/gui/utils/plasmacolorscheme.h @@ -0,0 +1,173 @@ + +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2016 Eugene Shalygin + * + * This program 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#ifndef QBT_GUI_UTILS_PLASMACOLORSCHEME_H +#define QBT_GUI_UTILS_PLASMACOLORSCHEME_H + +#include +#include +#include +#include + +class QSettings; + +class PlasmaColorScheme +{ + Q_GADGET + +public: + struct Effect + { + enum ColorEffect + { + ColorEffectNone = 0, + ColorEffectDesaturate, + ColorEffectFade, + ColorEffectTint + }; + + enum IntensityEffect + { + IntensityEffectNone = 0, + IntensityEffectShade, + IntensityEffectDarken, + IntensityEffectLighten + }; + + enum ContrastEffect + { + ContrastEffectNone = 0, + ContrastEffectFade, + ContrastEffectTint + }; + + bool changeSelectionColor; + QColor color; + qreal colorAmount; // [-1:1] + ColorEffect colorEffect; + qreal contrastAmount; // [-1:1] + ContrastEffect contrastEffect; + bool enable; + qreal intensityAmount; // [-1:1] + IntensityEffect intensityEffect; + }; + + enum ColorRole + { + BackgroundAlternate, + BackgroundNormal, + DecorationFocus, + DecorationHover, + ForegroundActive, + ForegroundInactive, + ForegroundLink, + ForegroundNegative, + ForegroundNeutral, + ForegroundNormal, + ForegroundPositive, + ForegroundVisited + }; + + Q_ENUM(ColorRole) + + enum ColorSet + { + /** + * Views; for example, frames, input fields, etc. + * + * If it contains things that can be selected, it is probably a View. + */ + View, + /** + * Non-editable window elements; for example, menus. + * + * If it isn't a Button, View, or Tooltip, it is probably a Window. + */ + Window, + /** + * Buttons and button-like controls. + * + * In addition to buttons, "button-like" controls such as non-editable + * dropdowns, scrollbar sliders, slider handles, etc. should also use + * this role. + */ + Button, + /** + * Selected items in views. + * + * Note that unfocused or disabled selections should use the Window + * role. This makes it more obvious to the user that the view + * containing the selection does not have input focus. + */ + Selection, + /** + * Tooltips. + * + * The tooltip set can often be substituted for the view + * set when editing is not possible, but the Window set is deemed + * inappropriate. "What's This" help is an excellent example, another + * might be pop-up notifications (depending on taste). + */ + Tooltip + }; + + Q_ENUM(ColorSet) + + PlasmaColorScheme(const QProcessEnvironment& env = QProcessEnvironment::systemEnvironment()); + void reload(const QProcessEnvironment& env = QProcessEnvironment::systemEnvironment()); + + static const PlasmaColorScheme* instance(); + + QColor color(ColorRole role, QPalette::ColorGroup group = QPalette::Active, ColorSet set = View) const; + QColor disabledColor(const QColor& color) const; + QColor inactiveColor(const QColor& color) const; + + bool wasLoadedSuccesfully() const; + +private: + using ColorsMap = QMap; + using ColorsSet = QMap; + using Colors = QMap; + + void load(const QProcessEnvironment& env = QProcessEnvironment::systemEnvironment()); + void setFallbackColors(); + static ColorsSet fallbackColorSet(QPalette::ColorGroup group); + + static ColorsMap readSet(QSettings& settings, ColorSet set); + static ColorsSet applyEffect(const ColorsSet &set, const Effect& effect); + + static QString locateColorThemeFile(const QString &themeName); + + Colors m_colors; + Effect m_disabledEffect; + Effect m_inactiveEffect; + bool m_loadedSuccesfully; +}; + +#endif // QBT_GUI_UTILS_PLASMACOLORSCHEME_H diff --git a/unixconf.pri b/unixconf.pri index 2280f282aa..f71c723b19 100644 --- a/unixconf.pri +++ b/unixconf.pri @@ -125,6 +125,13 @@ nogui:systemd { INSTALLS += pixmap } +plasma_integration { + DEFINES += PLASMA_INTEGRATION + themes.files += $$DIST_PATH/qBittorrentPlasma.colortheme + themes.path = $$DATADIR/qBittorrent/theme/ + INSTALLS += themes +} + # INSTALL target.path = $$PREFIX/bin/ INSTALLS += target From 3137c24e10b8716152539a39a01d5d5f2ae694a8 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Fri, 26 May 2017 13:04:55 +0200 Subject: [PATCH 4/6] Add alternative color themes --- dist/CMakeLists.txt | 6 ++++++ dist/theme/AlternativeDark.colortheme | 25 +++++++++++++++++++++++++ dist/theme/AlternativeLight.colortheme | 22 ++++++++++++++++++++++ dist/theme/Classic.colortheme | 24 ++++++++++++++++++++++++ dist/unix/CMakeLists.txt | 5 +++++ 5 files changed, 82 insertions(+) create mode 100644 dist/theme/AlternativeDark.colortheme create mode 100644 dist/theme/AlternativeLight.colortheme create mode 100644 dist/theme/Classic.colortheme diff --git a/dist/CMakeLists.txt b/dist/CMakeLists.txt index 0eeb49dc0b..f85c7792c4 100644 --- a/dist/CMakeLists.txt +++ b/dist/CMakeLists.txt @@ -1,3 +1,9 @@ +set(ADDITIONAL_THEME_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/theme/Classic.colortheme + ${CMAKE_CURRENT_SOURCE_DIR}/theme/AlternativeDark.colortheme + ${CMAKE_CURRENT_SOURCE_DIR}/theme/AlternativeLight.colortheme +) + if (APPLE) add_subdirectory(mac) else (APPLE) diff --git a/dist/theme/AlternativeDark.colortheme b/dist/theme/AlternativeDark.colortheme new file mode 100644 index 0000000000..b5d608aed1 --- /dev/null +++ b/dist/theme/AlternativeDark.colortheme @@ -0,0 +1,25 @@ +[Info] +Name=Alternative (Dark) +Description=Alternative color theme. Dark flavour. +Inherits=Default (Dark) + +[TorrentState] +Uploading=RGB:#63b8ff +PausedUploading=RGB:#4f94cd +QueuedUploading=RGB:#00cdcd +StalledUploading=RGB:#63b8ff +CheckingUploading=RGB:#00cdcd +ForcedUploading=RGB:#63b8ff +Allocating=RGB:#fa8072 +Downloading=RGB:#32cd32 +DownloadingMetadata=RGB:#32cd32 +PausedDownloading=RGB:#cccccc +QueuedDownloading=RGB:#00cdcd +StalledDownloading=RGB:#fa8072 +CheckingDownloading=RGB:#00cdcd +ForcedDownloading=RGB:#32cd32 +QueuedForChecking=RGB:#00cdcd +CheckingResumeData=RGB:#00cdcd +Unknown=RGB:#ff0000 +Error=RGB:#ff0000 +MissingFiles=RGB:#ff0000 diff --git a/dist/theme/AlternativeLight.colortheme b/dist/theme/AlternativeLight.colortheme new file mode 100644 index 0000000000..c04ba7b9b0 --- /dev/null +++ b/dist/theme/AlternativeLight.colortheme @@ -0,0 +1,22 @@ +[Info] +Name=Alternative (Light) +Description=Alternative color theme. Light flavour. +Inherits=Default (Light) + +[TorrentState] +Unknown=RGB:#ff0000 +Error=RGB:#ff0000 +MissingFiles=RGB:#ff0000 +Uploading=RGB:#4169e1 +PausedUploading=RGB:#00008b +QueuedUploading=RGB:#008080 +StalledUploading=RGB:#4169e1 +CheckingUploading=RGB:#008080 +ForcedUploading=RGB:#4169e1 +Allocating=RGB:#228b22 +PausedDownloading=RGB:#000000 +QueuedDownloading=RGB:#008080 +StalledDownloading=RGB:#228b22 +CheckingDownloading=RGB:#008080 +QueuedForChecking=RGB:#008080 +CheckingResumeData=RGB:#008080 diff --git a/dist/theme/Classic.colortheme b/dist/theme/Classic.colortheme new file mode 100644 index 0000000000..419a2d4b8b --- /dev/null +++ b/dist/theme/Classic.colortheme @@ -0,0 +1,24 @@ +[Info] +Name=Classic +Description=Classic qBittorrent colors. + +[TorrentState] +Unknown=RGB:#ff0000 +Error=RGB:#ff0000 +MissingFiles=RGB:#ff0000 +Uploading=RGB:#ffa500 +PausedUploading=RGB:#ff0000 +QueuedUploading=RGB:#008080 +StalledUploading=RGB:#808080 +CheckingUploading=RGB:#808080 +ForcedUploading=RGB:#ffa500 +Allocating=RGB:#808080 +Downloading=RGB:#008000 +DownloadingMetadata=RGB:#008000 +PausedDownloading=RGB:#ff0000 +QueuedDownloading=RGB:#008080 +StalledDownloading=RGB:#808080 +CheckingDownloading=RGB:#808080 +ForcedDownloading=RGB:#008000 +QueuedForChecking=RGB:#808080 +CheckingResumeData=RGB:#808080 diff --git a/dist/unix/CMakeLists.txt b/dist/unix/CMakeLists.txt index 63ecbdaf27..8d161e69ef 100644 --- a/dist/unix/CMakeLists.txt +++ b/dist/unix/CMakeLists.txt @@ -42,6 +42,11 @@ if (GUI) ${qBittorrent_SOURCE_DIR}/src/icons/skin/qbittorrent-tray-light.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/status COMPONENT data) + + install(FILES ${ADDITIONAL_THEME_FILES} + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/qBittorrent/theme/ + COMPONENT data + ) endif() if (PLASMA_INTEGRATION) From d7bc0b194826aa7352aca77a40459827943ec985 Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Mon, 3 Jul 2017 10:15:06 +0200 Subject: [PATCH 5/6] Refactor icons handling 1. Use SVG icons and drop png files 2. Add function to change SVG fill color and use it to produce monochrome icon set. 3. Allow torrent state icons to be colored corresponding to state colors. --- src/base/iconprovider.cpp | 16 +- src/base/iconprovider.h | 7 + src/base/preferences.cpp | 22 +- src/base/preferences.h | 4 - src/gui/guiiconprovider.cpp | 280 ++++++++++++++---- src/gui/guiiconprovider.h | 50 +++- src/gui/mainwindow.cpp | 6 +- src/gui/optionsdlg.cpp | 38 ++- src/gui/optionsdlg.ui | 67 ++++- src/gui/search/searchtab.cpp | 10 +- src/gui/statusbar.cpp | 11 +- src/gui/theme/themecommon.cpp | 1 + src/gui/theme/themecommon.h | 3 + src/gui/torrentmodel.cpp | 128 ++------ src/gui/torrentmodel.h | 7 + src/gui/trackerlogin.cpp | 6 +- src/gui/transferlistfilterswidget.cpp | 31 +- src/gui/transferlistfilterswidget.h | 1 + src/gui/transferlistwidget.cpp | 2 +- src/icons.qrc | 214 ++++++------- src/icons/qbt-theme/application-exit.png | Bin 2769 -> 0 bytes .../icons => }/application-exit.svg | 0 src/icons/qbt-theme/application-rss+xml.png | Bin 3564 -> 0 bytes .../icons => }/application-rss+xml.svg | 0 .../qbt-theme/application-x-mswinurl.png | Bin 4969 -> 0 bytes .../icons => }/application-x-mswinurl.svg | 0 src/icons/qbt-theme/build-icons/Gruntfile.js | 22 -- .../build-icons/icons/insert-link.svg | 5 - src/icons/qbt-theme/build-icons/package.json | 13 - src/icons/qbt-theme/build-icons/readme.md | 14 - src/icons/qbt-theme/checked.png | Bin 1420 -> 0 bytes .../{build-icons/icons => }/checked.svg | 0 .../cloud-download.svg} | 0 .../cloud-upload.svg} | 0 src/icons/qbt-theme/configure.png | Bin 3037 -> 0 bytes .../{build-icons/icons => }/configure.svg | 0 src/icons/qbt-theme/dialog-cancel.png | Bin 4144 -> 0 bytes .../{build-icons/icons => }/dialog-cancel.svg | 0 src/icons/qbt-theme/dialog-information.png | Bin 3237 -> 0 bytes .../icons => }/dialog-information.svg | 0 src/icons/qbt-theme/dialog-warning.png | Bin 2891 -> 0 bytes .../icons => }/dialog-warning.svg | 0 src/icons/qbt-theme/document-edit-verify.png | Bin 3112 -> 0 bytes .../icons => }/document-edit-verify.svg | 0 src/icons/qbt-theme/document-edit.png | Bin 2097 -> 0 bytes .../{build-icons/icons => }/document-edit.svg | 0 src/icons/qbt-theme/document-encrypt.png | Bin 2339 -> 0 bytes .../icons => }/document-encrypt.svg | 0 src/icons/qbt-theme/document-import.png | Bin 2016 -> 0 bytes .../icons => }/document-import.svg | 0 src/icons/qbt-theme/document-new.png | Bin 1874 -> 0 bytes .../{build-icons/icons => }/document-new.svg | 0 src/icons/qbt-theme/document-properties.png | Bin 2935 -> 0 bytes .../icons => }/document-properties.svg | 0 src/icons/qbt-theme/document-save.png | Bin 1804 -> 0 bytes .../{build-icons/icons => }/document-save.svg | 0 src/icons/qbt-theme/download.png | Bin 2045 -> 0 bytes .../{build-icons/icons => }/download.svg | 0 src/icons/qbt-theme/edit-clear-history.png | Bin 3978 -> 0 bytes .../icons => }/edit-clear-history.svg | 0 src/icons/qbt-theme/edit-clear.png | Bin 3652 -> 0 bytes .../{build-icons/icons => }/edit-clear.svg | 0 src/icons/qbt-theme/edit-copy.png | Bin 1861 -> 0 bytes .../{build-icons/icons => }/edit-copy.svg | 0 src/icons/qbt-theme/edit-cut.png | Bin 7349 -> 0 bytes .../{build-icons/icons => }/edit-cut.svg | 0 src/icons/qbt-theme/edit-delete.png | Bin 2769 -> 0 bytes .../{build-icons/icons => }/edit-delete.svg | 0 src/icons/qbt-theme/edit-find-user.png | Bin 7826 -> 0 bytes .../icons => }/edit-find-user.svg | 0 src/icons/qbt-theme/edit-find.png | Bin 3204 -> 0 bytes .../{build-icons/icons => }/edit-find.svg | 0 src/icons/qbt-theme/edit-paste.png | Bin 1477 -> 0 bytes .../{build-icons/icons => }/edit-paste.svg | 0 src/icons/qbt-theme/edit-rename.png | Bin 2545 -> 0 bytes .../{build-icons/icons => }/edit-rename.svg | 0 src/icons/qbt-theme/folder-documents.png | Bin 2762 -> 0 bytes .../icons => }/folder-documents.svg | 0 src/icons/qbt-theme/folder-download.png | Bin 2045 -> 0 bytes .../icons => }/folder-download.svg | 0 src/icons/qbt-theme/folder-new.png | Bin 4301 -> 0 bytes .../{build-icons/icons => }/folder-new.svg | 0 src/icons/qbt-theme/folder-remote.png | Bin 10738 -> 0 bytes .../{build-icons/icons => }/folder-remote.svg | 0 src/icons/qbt-theme/gear.png | Bin 3037 -> 0 bytes .../{build-icons/icons => }/gear.svg | 0 src/icons/qbt-theme/gear32.png | Bin 3037 -> 0 bytes .../{build-icons/icons => }/gear32.svg | 0 src/icons/qbt-theme/go-bottom.png | Bin 993 -> 0 bytes .../{build-icons/icons => }/go-bottom.svg | 0 src/icons/qbt-theme/go-down.png | Bin 755 -> 0 bytes .../{build-icons/icons => }/go-down.svg | 0 src/icons/qbt-theme/go-top.png | Bin 1034 -> 0 bytes .../{build-icons/icons => }/go-top.svg | 0 src/icons/qbt-theme/go-up.png | Bin 1329 -> 0 bytes .../{build-icons/icons => }/go-up.svg | 0 src/icons/qbt-theme/help-about.png | Bin 3237 -> 0 bytes .../{build-icons/icons => }/help-about.svg | 0 src/icons/qbt-theme/help-contents.png | Bin 2334 -> 0 bytes .../{build-icons/icons => }/help-contents.svg | 0 src/icons/qbt-theme/inode-directory.png | Bin 2762 -> 0 bytes .../icons => }/inode-directory.svg | 0 src/icons/qbt-theme/insert-link.png | Bin 6072 -> 0 bytes src/icons/qbt-theme/insert-link.svg | 29 ++ src/icons/qbt-theme/kt-magnet.png | Bin 4391 -> 0 bytes src/icons/qbt-theme/kt-magnet.svg | 5 + .../qbt-theme/kt-set-max-download-speed.png | Bin 359 -> 0 bytes .../qbt-theme/kt-set-max-download-speed.svg | 13 + .../qbt-theme/kt-set-max-upload-speed.png | Bin 321 -> 0 bytes .../qbt-theme/kt-set-max-upload-speed.svg | 13 + src/icons/qbt-theme/list-add.png | Bin 1874 -> 0 bytes .../{build-icons/icons => }/list-add.svg | 0 src/icons/qbt-theme/list-remove.png | Bin 639 -> 0 bytes .../{build-icons/icons => }/list-remove.svg | 0 src/icons/qbt-theme/mail-folder-inbox.png | Bin 2008 -> 0 bytes .../icons => }/mail-folder-inbox.svg | 0 src/icons/qbt-theme/mail-mark-read.png | Bin 4566 -> 0 bytes .../icons => }/mail-mark-read.svg | 0 src/icons/qbt-theme/media-playback-pause.png | Bin 693 -> 0 bytes .../icons => }/media-playback-pause.svg | 0 src/icons/qbt-theme/media-playback-start.png | Bin 1950 -> 0 bytes .../icons => }/media-playback-start.svg | 0 src/icons/qbt-theme/media-seek-forward.png | Bin 1690 -> 0 bytes .../icons => }/media-seek-forward.svg | 0 src/icons/qbt-theme/network-server.png | Bin 1870 -> 0 bytes .../icons => }/network-server.svg | 0 src/icons/qbt-theme/network-wired.png | Bin 1859 -> 0 bytes .../{build-icons/icons => }/network-wired.svg | 0 src/icons/qbt-theme/object-locked.png | Bin 2339 -> 0 bytes .../{build-icons/icons => }/object-locked.svg | 0 src/icons/qbt-theme/office-chart-line.png | Bin 1310 -> 0 bytes .../icons => }/office-chart-line.svg | 0 .../preferences-desktop-theme.svg | 0 src/icons/qbt-theme/preferences-desktop.png | Bin 3328 -> 0 bytes .../icons => }/preferences-desktop.svg | 0 src/icons/qbt-theme/preferences-other.png | Bin 4610 -> 0 bytes .../icons => }/preferences-other.svg | 0 .../qbt-theme/preferences-system-network.png | Bin 8770 -> 0 bytes .../icons => }/preferences-system-network.svg | 0 .../preferences-web-browser-cookies.png | Bin 3797 -> 0 bytes .../preferences-web-browser-cookies.svg | 0 src/icons/qbt-theme/rss-config.png | Bin 1065 -> 0 bytes src/icons/qbt-theme/rss-config.svg | 17 ++ src/icons/qbt-theme/security-high.png | Bin 3163 -> 0 bytes .../{build-icons/icons => }/security-high.svg | 0 src/icons/qbt-theme/security-low.png | Bin 3722 -> 0 bytes .../{build-icons/icons => }/security-low.svg | 0 src/icons/qbt-theme/services.png | Bin 2188 -> 0 bytes .../{build-icons/icons => }/services.svg | 0 src/icons/qbt-theme/speedometer.png | Bin 4308 -> 0 bytes .../{build-icons/icons => }/speedometer.svg | 0 src/icons/qbt-theme/state-download.svg | 24 ++ src/icons/qbt-theme/state-error.svg | 30 ++ src/icons/qbt-theme/state-information.svg | 26 ++ src/icons/qbt-theme/state-offline.svg | 23 ++ src/icons/qbt-theme/state-ok.svg | 27 ++ src/icons/qbt-theme/state-pause.svg | 25 ++ src/icons/qbt-theme/state-sync.svg | 26 ++ src/icons/qbt-theme/state-warning.svg | 25 ++ src/icons/qbt-theme/system-log-out.png | Bin 2148 -> 0 bytes .../icons => }/system-log-out.svg | 0 src/icons/qbt-theme/tab-close.png | Bin 3247 -> 0 bytes .../{build-icons/icons => }/tab-close.svg | 0 src/icons/qbt-theme/task-attention.png | Bin 2891 -> 0 bytes .../icons => }/task-attention.svg | 0 src/icons/qbt-theme/task-complete.png | Bin 678 -> 0 bytes src/icons/qbt-theme/task-ongoing.png | Bin 915 -> 0 bytes src/icons/qbt-theme/task-reject.png | Bin 765 -> 0 bytes src/icons/qbt-theme/text-plain.png | Bin 1697 -> 0 bytes .../{build-icons/icons => }/text-plain.svg | 0 src/icons/qbt-theme/tools-report-bug.png | Bin 2639 -> 0 bytes .../icons => }/tools-report-bug.svg | 0 src/icons/qbt-theme/unavailable.png | Bin 3278 -> 0 bytes .../{build-icons/icons => }/unavailable.svg | 0 src/icons/qbt-theme/user-group-delete.png | Bin 7084 -> 0 bytes .../icons => }/user-group-delete.svg | 0 src/icons/qbt-theme/user-group-new.png | Bin 6645 -> 0 bytes .../icons => }/user-group-new.svg | 0 src/icons/qbt-theme/view-calendar-journal.png | Bin 1872 -> 0 bytes .../icons => }/view-calendar-journal.svg | 0 src/icons/qbt-theme/view-categories.png | Bin 1591 -> 0 bytes .../icons => }/view-categories.svg | 0 src/icons/qbt-theme/view-filter.png | Bin 1134 -> 0 bytes .../{build-icons/icons => }/view-filter.svg | 0 src/icons/qbt-theme/view-preview.png | Bin 2293 -> 0 bytes .../{build-icons/icons => }/view-preview.svg | 0 src/icons/qbt-theme/view-refresh.png | Bin 2978 -> 0 bytes .../{build-icons/icons => }/view-refresh.svg | 0 src/icons/qbt-theme/view-statistics.png | Bin 512 -> 0 bytes .../icons => }/view-statistics.svg | 0 src/icons/qbt-theme/wallet-open.png | Bin 960 -> 0 bytes .../{build-icons/icons => }/wallet-open.svg | 0 src/icons/qbt-theme/webui.png | Bin 4452 -> 0 bytes .../{build-icons/icons => }/webui.svg | 0 src/icons/skin/build-icons/Gruntfile.js | 22 -- src/icons/skin/build-icons/package.json | 13 - src/icons/skin/build-icons/readme.md | 14 - src/icons/skin/checking.png | Bin 3731 -> 0 bytes .../skin/{build-icons/icons => }/checking.svg | 0 src/icons/skin/completed.png | Bin 2140 -> 0 bytes .../{build-icons/icons => }/completed.svg | 0 src/icons/skin/connected.png | Bin 2524 -> 0 bytes .../{build-icons/icons => }/connected.svg | 0 src/icons/skin/disconnected.png | Bin 2524 -> 0 bytes .../{build-icons/icons => }/disconnected.svg | 0 src/icons/skin/download.png | Bin 1831 -> 0 bytes src/icons/skin/downloading.png | Bin 1490 -> 0 bytes .../{build-icons/icons => }/downloading.svg | 0 src/icons/skin/error.png | Bin 1934 -> 0 bytes .../skin/{build-icons/icons => }/error.svg | 0 src/icons/skin/filteractive.png | Bin 2162 -> 0 bytes .../{build-icons/icons => }/filteractive.svg | 0 src/icons/skin/filterall.png | Bin 2162 -> 0 bytes .../{build-icons/icons => }/filterall.svg | 0 src/icons/skin/filterinactive.png | Bin 2162 -> 0 bytes .../icons => }/filterinactive.svg | 0 src/icons/skin/firewalled.png | Bin 2277 -> 0 bytes .../{build-icons/icons => }/firewalled.svg | 0 src/icons/skin/paused.png | Bin 745 -> 0 bytes .../skin/{build-icons/icons => }/paused.svg | 0 src/icons/skin/queued.png | Bin 4505 -> 0 bytes .../skin/{build-icons/icons => }/queued.svg | 0 src/icons/skin/ratio.png | Bin 1991 -> 0 bytes .../skin/{build-icons/icons => }/ratio.svg | 0 src/icons/skin/resumed.png | Bin 2101 -> 0 bytes .../skin/{build-icons/icons => }/resumed.svg | 0 src/icons/skin/seeding.png | Bin 1851 -> 0 bytes src/icons/skin/stalledDL.png | Bin 1490 -> 0 bytes .../{build-icons/icons => }/stalledDL.svg | 0 src/icons/skin/stalledUP.png | Bin 1470 -> 0 bytes .../{build-icons/icons => }/stalledUP.svg | 0 src/icons/skin/uploading.png | Bin 1470 -> 0 bytes .../{build-icons/icons => }/uploading.svg | 0 src/update_qrc_files.py | 2 +- 234 files changed, 852 insertions(+), 440 deletions(-) delete mode 100644 src/icons/qbt-theme/application-exit.png rename src/icons/qbt-theme/{build-icons/icons => }/application-exit.svg (100%) delete mode 100644 src/icons/qbt-theme/application-rss+xml.png rename src/icons/qbt-theme/{build-icons/icons => }/application-rss+xml.svg (100%) delete mode 100644 src/icons/qbt-theme/application-x-mswinurl.png rename src/icons/qbt-theme/{build-icons/icons => }/application-x-mswinurl.svg (100%) delete mode 100644 src/icons/qbt-theme/build-icons/Gruntfile.js delete mode 100644 src/icons/qbt-theme/build-icons/icons/insert-link.svg delete mode 100644 src/icons/qbt-theme/build-icons/package.json delete mode 100644 src/icons/qbt-theme/build-icons/readme.md delete mode 100644 src/icons/qbt-theme/checked.png rename src/icons/qbt-theme/{build-icons/icons => }/checked.svg (100%) rename src/icons/{skin/build-icons/icons/download.svg => qbt-theme/cloud-download.svg} (100%) rename src/icons/{skin/build-icons/icons/seeding.svg => qbt-theme/cloud-upload.svg} (100%) delete mode 100644 src/icons/qbt-theme/configure.png rename src/icons/qbt-theme/{build-icons/icons => }/configure.svg (100%) delete mode 100644 src/icons/qbt-theme/dialog-cancel.png rename src/icons/qbt-theme/{build-icons/icons => }/dialog-cancel.svg (100%) delete mode 100644 src/icons/qbt-theme/dialog-information.png rename src/icons/qbt-theme/{build-icons/icons => }/dialog-information.svg (100%) delete mode 100644 src/icons/qbt-theme/dialog-warning.png rename src/icons/qbt-theme/{build-icons/icons => }/dialog-warning.svg (100%) delete mode 100644 src/icons/qbt-theme/document-edit-verify.png rename src/icons/qbt-theme/{build-icons/icons => }/document-edit-verify.svg (100%) delete mode 100644 src/icons/qbt-theme/document-edit.png rename src/icons/qbt-theme/{build-icons/icons => }/document-edit.svg (100%) delete mode 100644 src/icons/qbt-theme/document-encrypt.png rename src/icons/qbt-theme/{build-icons/icons => }/document-encrypt.svg (100%) delete mode 100644 src/icons/qbt-theme/document-import.png rename src/icons/qbt-theme/{build-icons/icons => }/document-import.svg (100%) delete mode 100644 src/icons/qbt-theme/document-new.png rename src/icons/qbt-theme/{build-icons/icons => }/document-new.svg (100%) delete mode 100644 src/icons/qbt-theme/document-properties.png rename src/icons/qbt-theme/{build-icons/icons => }/document-properties.svg (100%) delete mode 100644 src/icons/qbt-theme/document-save.png rename src/icons/qbt-theme/{build-icons/icons => }/document-save.svg (100%) delete mode 100644 src/icons/qbt-theme/download.png rename src/icons/qbt-theme/{build-icons/icons => }/download.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-clear-history.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-clear-history.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-clear.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-clear.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-copy.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-copy.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-cut.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-cut.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-delete.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-delete.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-find-user.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-find-user.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-find.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-find.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-paste.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-paste.svg (100%) delete mode 100644 src/icons/qbt-theme/edit-rename.png rename src/icons/qbt-theme/{build-icons/icons => }/edit-rename.svg (100%) delete mode 100644 src/icons/qbt-theme/folder-documents.png rename src/icons/qbt-theme/{build-icons/icons => }/folder-documents.svg (100%) delete mode 100644 src/icons/qbt-theme/folder-download.png rename src/icons/qbt-theme/{build-icons/icons => }/folder-download.svg (100%) delete mode 100644 src/icons/qbt-theme/folder-new.png rename src/icons/qbt-theme/{build-icons/icons => }/folder-new.svg (100%) delete mode 100644 src/icons/qbt-theme/folder-remote.png rename src/icons/qbt-theme/{build-icons/icons => }/folder-remote.svg (100%) delete mode 100644 src/icons/qbt-theme/gear.png rename src/icons/qbt-theme/{build-icons/icons => }/gear.svg (100%) delete mode 100644 src/icons/qbt-theme/gear32.png rename src/icons/qbt-theme/{build-icons/icons => }/gear32.svg (100%) delete mode 100644 src/icons/qbt-theme/go-bottom.png rename src/icons/qbt-theme/{build-icons/icons => }/go-bottom.svg (100%) delete mode 100644 src/icons/qbt-theme/go-down.png rename src/icons/qbt-theme/{build-icons/icons => }/go-down.svg (100%) delete mode 100644 src/icons/qbt-theme/go-top.png rename src/icons/qbt-theme/{build-icons/icons => }/go-top.svg (100%) delete mode 100644 src/icons/qbt-theme/go-up.png rename src/icons/qbt-theme/{build-icons/icons => }/go-up.svg (100%) delete mode 100644 src/icons/qbt-theme/help-about.png rename src/icons/qbt-theme/{build-icons/icons => }/help-about.svg (100%) delete mode 100644 src/icons/qbt-theme/help-contents.png rename src/icons/qbt-theme/{build-icons/icons => }/help-contents.svg (100%) delete mode 100644 src/icons/qbt-theme/inode-directory.png rename src/icons/qbt-theme/{build-icons/icons => }/inode-directory.svg (100%) delete mode 100644 src/icons/qbt-theme/insert-link.png create mode 100644 src/icons/qbt-theme/insert-link.svg delete mode 100644 src/icons/qbt-theme/kt-magnet.png create mode 100644 src/icons/qbt-theme/kt-magnet.svg delete mode 100644 src/icons/qbt-theme/kt-set-max-download-speed.png create mode 100644 src/icons/qbt-theme/kt-set-max-download-speed.svg delete mode 100644 src/icons/qbt-theme/kt-set-max-upload-speed.png create mode 100644 src/icons/qbt-theme/kt-set-max-upload-speed.svg delete mode 100644 src/icons/qbt-theme/list-add.png rename src/icons/qbt-theme/{build-icons/icons => }/list-add.svg (100%) delete mode 100644 src/icons/qbt-theme/list-remove.png rename src/icons/qbt-theme/{build-icons/icons => }/list-remove.svg (100%) delete mode 100644 src/icons/qbt-theme/mail-folder-inbox.png rename src/icons/qbt-theme/{build-icons/icons => }/mail-folder-inbox.svg (100%) delete mode 100644 src/icons/qbt-theme/mail-mark-read.png rename src/icons/qbt-theme/{build-icons/icons => }/mail-mark-read.svg (100%) delete mode 100644 src/icons/qbt-theme/media-playback-pause.png rename src/icons/qbt-theme/{build-icons/icons => }/media-playback-pause.svg (100%) delete mode 100644 src/icons/qbt-theme/media-playback-start.png rename src/icons/qbt-theme/{build-icons/icons => }/media-playback-start.svg (100%) delete mode 100644 src/icons/qbt-theme/media-seek-forward.png rename src/icons/qbt-theme/{build-icons/icons => }/media-seek-forward.svg (100%) delete mode 100644 src/icons/qbt-theme/network-server.png rename src/icons/qbt-theme/{build-icons/icons => }/network-server.svg (100%) delete mode 100644 src/icons/qbt-theme/network-wired.png rename src/icons/qbt-theme/{build-icons/icons => }/network-wired.svg (100%) delete mode 100644 src/icons/qbt-theme/object-locked.png rename src/icons/qbt-theme/{build-icons/icons => }/object-locked.svg (100%) delete mode 100644 src/icons/qbt-theme/office-chart-line.png rename src/icons/qbt-theme/{build-icons/icons => }/office-chart-line.svg (100%) rename src/icons/qbt-theme/{build-icons => }/preferences-desktop-theme.svg (100%) delete mode 100644 src/icons/qbt-theme/preferences-desktop.png rename src/icons/qbt-theme/{build-icons/icons => }/preferences-desktop.svg (100%) delete mode 100644 src/icons/qbt-theme/preferences-other.png rename src/icons/qbt-theme/{build-icons/icons => }/preferences-other.svg (100%) delete mode 100644 src/icons/qbt-theme/preferences-system-network.png rename src/icons/qbt-theme/{build-icons/icons => }/preferences-system-network.svg (100%) delete mode 100644 src/icons/qbt-theme/preferences-web-browser-cookies.png rename src/icons/qbt-theme/{build-icons/icons => }/preferences-web-browser-cookies.svg (100%) delete mode 100644 src/icons/qbt-theme/rss-config.png create mode 100644 src/icons/qbt-theme/rss-config.svg delete mode 100644 src/icons/qbt-theme/security-high.png rename src/icons/qbt-theme/{build-icons/icons => }/security-high.svg (100%) delete mode 100644 src/icons/qbt-theme/security-low.png rename src/icons/qbt-theme/{build-icons/icons => }/security-low.svg (100%) delete mode 100644 src/icons/qbt-theme/services.png rename src/icons/qbt-theme/{build-icons/icons => }/services.svg (100%) delete mode 100644 src/icons/qbt-theme/speedometer.png rename src/icons/qbt-theme/{build-icons/icons => }/speedometer.svg (100%) create mode 100644 src/icons/qbt-theme/state-download.svg create mode 100644 src/icons/qbt-theme/state-error.svg create mode 100644 src/icons/qbt-theme/state-information.svg create mode 100644 src/icons/qbt-theme/state-offline.svg create mode 100644 src/icons/qbt-theme/state-ok.svg create mode 100644 src/icons/qbt-theme/state-pause.svg create mode 100644 src/icons/qbt-theme/state-sync.svg create mode 100644 src/icons/qbt-theme/state-warning.svg delete mode 100644 src/icons/qbt-theme/system-log-out.png rename src/icons/qbt-theme/{build-icons/icons => }/system-log-out.svg (100%) delete mode 100644 src/icons/qbt-theme/tab-close.png rename src/icons/qbt-theme/{build-icons/icons => }/tab-close.svg (100%) delete mode 100644 src/icons/qbt-theme/task-attention.png rename src/icons/qbt-theme/{build-icons/icons => }/task-attention.svg (100%) delete mode 100644 src/icons/qbt-theme/task-complete.png delete mode 100644 src/icons/qbt-theme/task-ongoing.png delete mode 100644 src/icons/qbt-theme/task-reject.png delete mode 100644 src/icons/qbt-theme/text-plain.png rename src/icons/qbt-theme/{build-icons/icons => }/text-plain.svg (100%) delete mode 100644 src/icons/qbt-theme/tools-report-bug.png rename src/icons/qbt-theme/{build-icons/icons => }/tools-report-bug.svg (100%) delete mode 100644 src/icons/qbt-theme/unavailable.png rename src/icons/qbt-theme/{build-icons/icons => }/unavailable.svg (100%) delete mode 100644 src/icons/qbt-theme/user-group-delete.png rename src/icons/qbt-theme/{build-icons/icons => }/user-group-delete.svg (100%) delete mode 100644 src/icons/qbt-theme/user-group-new.png rename src/icons/qbt-theme/{build-icons/icons => }/user-group-new.svg (100%) delete mode 100644 src/icons/qbt-theme/view-calendar-journal.png rename src/icons/qbt-theme/{build-icons/icons => }/view-calendar-journal.svg (100%) delete mode 100644 src/icons/qbt-theme/view-categories.png rename src/icons/qbt-theme/{build-icons/icons => }/view-categories.svg (100%) delete mode 100644 src/icons/qbt-theme/view-filter.png rename src/icons/qbt-theme/{build-icons/icons => }/view-filter.svg (100%) delete mode 100644 src/icons/qbt-theme/view-preview.png rename src/icons/qbt-theme/{build-icons/icons => }/view-preview.svg (100%) delete mode 100644 src/icons/qbt-theme/view-refresh.png rename src/icons/qbt-theme/{build-icons/icons => }/view-refresh.svg (100%) delete mode 100644 src/icons/qbt-theme/view-statistics.png rename src/icons/qbt-theme/{build-icons/icons => }/view-statistics.svg (100%) delete mode 100644 src/icons/qbt-theme/wallet-open.png rename src/icons/qbt-theme/{build-icons/icons => }/wallet-open.svg (100%) delete mode 100644 src/icons/qbt-theme/webui.png rename src/icons/qbt-theme/{build-icons/icons => }/webui.svg (100%) delete mode 100644 src/icons/skin/build-icons/Gruntfile.js delete mode 100644 src/icons/skin/build-icons/package.json delete mode 100644 src/icons/skin/build-icons/readme.md delete mode 100644 src/icons/skin/checking.png rename src/icons/skin/{build-icons/icons => }/checking.svg (100%) delete mode 100644 src/icons/skin/completed.png rename src/icons/skin/{build-icons/icons => }/completed.svg (100%) delete mode 100644 src/icons/skin/connected.png rename src/icons/skin/{build-icons/icons => }/connected.svg (100%) delete mode 100755 src/icons/skin/disconnected.png rename src/icons/skin/{build-icons/icons => }/disconnected.svg (100%) delete mode 100755 src/icons/skin/download.png delete mode 100644 src/icons/skin/downloading.png rename src/icons/skin/{build-icons/icons => }/downloading.svg (100%) delete mode 100644 src/icons/skin/error.png rename src/icons/skin/{build-icons/icons => }/error.svg (100%) delete mode 100644 src/icons/skin/filteractive.png rename src/icons/skin/{build-icons/icons => }/filteractive.svg (100%) delete mode 100644 src/icons/skin/filterall.png rename src/icons/skin/{build-icons/icons => }/filterall.svg (100%) delete mode 100644 src/icons/skin/filterinactive.png rename src/icons/skin/{build-icons/icons => }/filterinactive.svg (100%) delete mode 100644 src/icons/skin/firewalled.png rename src/icons/skin/{build-icons/icons => }/firewalled.svg (100%) delete mode 100644 src/icons/skin/paused.png rename src/icons/skin/{build-icons/icons => }/paused.svg (100%) delete mode 100644 src/icons/skin/queued.png rename src/icons/skin/{build-icons/icons => }/queued.svg (100%) delete mode 100644 src/icons/skin/ratio.png rename src/icons/skin/{build-icons/icons => }/ratio.svg (100%) delete mode 100644 src/icons/skin/resumed.png rename src/icons/skin/{build-icons/icons => }/resumed.svg (100%) delete mode 100644 src/icons/skin/seeding.png delete mode 100644 src/icons/skin/stalledDL.png rename src/icons/skin/{build-icons/icons => }/stalledDL.svg (100%) delete mode 100644 src/icons/skin/stalledUP.png rename src/icons/skin/{build-icons/icons => }/stalledUP.svg (100%) delete mode 100644 src/icons/skin/uploading.png rename src/icons/skin/{build-icons/icons => }/uploading.svg (100%) diff --git a/src/base/iconprovider.cpp b/src/base/iconprovider.cpp index 8d137556d2..32c01cc4af 100644 --- a/src/base/iconprovider.cpp +++ b/src/base/iconprovider.cpp @@ -33,9 +33,21 @@ IconProvider::IconProvider(QObject *parent) : QObject(parent) { + setIconDir(defaultIconDir()); } -IconProvider::~IconProvider() {} +IconProvider::~IconProvider() = default; + +void IconProvider::setIconDir(const QString& path) +{ + m_iconThemeDir = QDir(path); + Q_ASSERT(m_iconThemeDir.exists()); +} + +QString IconProvider::defaultIconDir() +{ + return QLatin1String(":/icons/qbt-theme/"); +} void IconProvider::initInstance() { @@ -58,7 +70,7 @@ IconProvider *IconProvider::instance() QString IconProvider::getIconPath(const QString &iconId) { - return ":/icons/qbt-theme/" + iconId + ".png"; + return m_iconThemeDir.absoluteFilePath(iconId + QLatin1String(".svg")); } IconProvider *IconProvider::m_instance = 0; diff --git a/src/base/iconprovider.h b/src/base/iconprovider.h index f9c00d63cf..6b469bbdcd 100644 --- a/src/base/iconprovider.h +++ b/src/base/iconprovider.h @@ -30,6 +30,7 @@ #ifndef ICONPROVIDER_H #define ICONPROVIDER_H +#include #include class QString; @@ -49,7 +50,13 @@ class IconProvider : public QObject explicit IconProvider(QObject *parent = 0); ~IconProvider(); + void setIconDir(const QString &path); + static QString defaultIconDir(); + static IconProvider *m_instance; + +private: + QDir m_iconThemeDir; }; #endif // ICONPROVIDER_H diff --git a/src/base/preferences.cpp b/src/base/preferences.cpp index cb81f5955f..9f72efff12 100644 --- a/src/base/preferences.cpp +++ b/src/base/preferences.cpp @@ -102,18 +102,6 @@ void Preferences::setLocale(const QString &locale) setValue("Appearance/Locale", locale); } -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) -bool Preferences::useSystemIconTheme() const -{ - return value("Appearance/useSystemIconTheme", true).toBool(); -} - -void Preferences::setSystemIconTheme(bool enabled) -{ - setValue("Appearance/useSystemIconTheme", enabled); -} -#endif - bool Preferences::useAlternatingRowColors() const { return value("Appearance/AlternatingRowColors", true).toBool(); @@ -1462,7 +1450,6 @@ void Preferences::upgrade() QList> prefsToMigrate = { { "Preferences/General/Locale", "Appearance/Locale" }, { "Preferences/General/AlternatingRowColors", "Appearance/AlternatingRowColors" }, - { "Preferences/Advanced/useSystemIconTheme", "Appearance/useSystemIconTheme" }, }; for (auto iter = prefsToMigrate.begin(); iter != prefsToMigrate.end(); ++iter) { @@ -1490,6 +1477,15 @@ void Preferences::upgrade() } SettingsStorage::instance()->removeValue("Preferences/Downloads/AppendLabel"); + +#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) + const QLatin1String UseSystemIconsOldKey = QLatin1String("Preferences/Advanced/useSystemIconTheme"); + if (SettingsStorage::instance()->loadValue(UseSystemIconsOldKey, false).toBool()) { + // see GUiIconsProvider for the new key + SettingsStorage::instance()->storeValue(QLatin1String("Appearance/IconSet"), QLatin1String("SystemTheme")); + } + SettingsStorage::instance()->removeValue(UseSystemIconsOldKey); +#endif } void Preferences::apply() diff --git a/src/base/preferences.h b/src/base/preferences.h index 135f6a95de..48aff91e17 100644 --- a/src/base/preferences.h +++ b/src/base/preferences.h @@ -105,10 +105,6 @@ class Preferences: public QObject void setLocale(const QString &locale); bool useAlternatingRowColors() const; void setAlternatingRowColors(bool b); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - bool useSystemIconTheme() const; - void setSystemIconTheme(bool enabled); -#endif // General options bool deleteTorrentFilesAsDefault() const; diff --git a/src/gui/guiiconprovider.cpp b/src/gui/guiiconprovider.cpp index 98dead6447..0ba413017f 100644 --- a/src/gui/guiiconprovider.cpp +++ b/src/gui/guiiconprovider.cpp @@ -28,19 +28,99 @@ */ #include "guiiconprovider.h" -#include "base/preferences.h" +#include +#include +#include +#include + +#include +#include +#include +#include #include +#include +#include + +#include "base/preferences.h" +#include "base/settingvalue.h" +#include "base/bittorrent/torrenthandle.h" +#include "theme/colortheme.h" +#include "theme/themeprovider.h" + + #if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) #include #include #endif +class GuiIconProvider::SVGManipulator +{ +public: + SVGManipulator(); + + void replaceSVGFillColor(const QString& svgFile, const QString &newSvgFile, const QColor& newColor); +private: + // !! Both regular expressions contain the same number of caption groups !! + // matches "color:xxxxx" + std::regex m_cssColorRegex; + // matches "fill="color" or "fill:color;" + std::regex m_fillColorRegex; +}; + +GuiIconProvider::SVGManipulator::SVGManipulator() + : m_cssColorRegex(R"regex((color)(:"?)[^;|^\s]+(;"?))regex") + , m_fillColorRegex(R"regex(( fill)(:|=")(?:(?!none|;|").)+(;|"))regex") +{ +} + +void GuiIconProvider::SVGManipulator::replaceSVGFillColor(const QString& svgFile, const QString &newSvgFile, + const QColor& newColor) +{ + // TODO detect and upack zipped SVGs + QFile inp(svgFile); + if (!inp.open(QIODevice::ReadOnly)) + throw std::runtime_error("Could not read input file"); + + std::ofstream res(newSvgFile.toStdString()); + + if (res.fail()) + throw std::runtime_error("Could not create result file"); + + Q_ASSERT(inp.size() < 100 * 1024); // SVG icons are small files + + std::stringstream svgContentsStream; + svgContentsStream << inp.readAll().constData(); + std::string svgContents = svgContentsStream.str(); + + // we support two types of colored icons: + // 1) the file defines CSS classes, that contains 'color:#xxxxxx;' + // 2) the file uses 'fill' attribute with explicit colors. + + // in case 1) we replace only CSS styled colors, in case 2) we replace color in all 'fill' + // attributes + // this code probably needs to be re-written using XML parser if the number of cases increases + + const bool svgContainsCSSStyles = svgContents.find("style type=\"text/css\"") != std::string::npos; + + res << std::regex_replace(svgContents, + svgContainsCSSStyles ? m_cssColorRegex : m_fillColorRegex, + "$1$2" + newColor.name().toStdString() + "$3"); +} + GuiIconProvider::GuiIconProvider(QObject *parent) : IconProvider(parent) + , m_coloredIconsDir(colorizedIconsDir()) + , m_svgManipulator(new SVGManipulator()) { - configure(); - connect(Preferences::instance(), SIGNAL(changed()), SLOT(configure())); + if (!m_coloredIconsDir.isValid()) + qCWarning(theme, "Could not create temporary directory '%s' for colorized icons", qPrintable(m_coloredIconsDir.path())); + else + m_coloredIconsDir.setAutoRemove(true); + + connect(&Theme::ThemeProvider::instance(), &Theme::ThemeProvider::colorThemeChanged, + this, &GuiIconProvider::colorThemeChanged); + update(); } GuiIconProvider::~GuiIconProvider() = default; @@ -64,11 +144,10 @@ QIcon GuiIconProvider::getIcon(const QString &iconId) QIcon GuiIconProvider::getIcon(const QString &iconId, const QString &fallback) { #if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - if (m_useSystemTheme) { + if (iconSet() == IconSet::SystemTheme) { QIcon icon = QIcon::fromTheme(iconId); - if (icon.name() != iconId) + if (icon.isNull() || icon.name() != iconId) icon = QIcon::fromTheme(fallback, QIcon(IconProvider::getIconPath(iconId))); - icon = generateDifferentSizes(icon); return icon; } #else @@ -83,64 +162,163 @@ QIcon GuiIconProvider::getFlagIcon(const QString &countryIsoCode) return QIcon(":/icons/flags/" + countryIsoCode.toLower() + ".png"); } -// Makes sure the icon is at least available in 16px and 24px size -// It scales the icon from the theme if necessary -// Otherwise, the UI looks broken if the icon is not available -// in the correct size. -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) -QIcon GuiIconProvider::generateDifferentSizes(const QIcon &icon) +QIcon GuiIconProvider::icon(BitTorrent::TorrentState state) const { - // if icon is loaded from SVG format, it already contains all the required sizes and we shall not resize it - // In that case it will be available in the following sizes: - // (QSize(16, 16), QSize(22, 22), QSize(32, 32), QSize(48, 48), QSize(64, 64), QSize(128, 128), QSize(256, 256)) + return m_torrentStateIcons.value(state); +} - if (icon.availableSizes(QIcon::Normal, QIcon::On).size() > 6) - return icon; +GuiIconProvider::IconSet GuiIconProvider::iconSet() +{ + return iconSetSetting(); +} - QIcon newIcon; - QList requiredSizes; - requiredSizes << QSize(16, 16) << QSize(24, 24) << QSize(32, 32); - QList modes; - modes << QIcon::Normal << QIcon::Active << QIcon::Selected << QIcon::Disabled; - foreach (const QSize &size, requiredSizes) { - foreach (QIcon::Mode mode, modes) { - QPixmap pixoff = icon.pixmap(size, mode, QIcon::Off); - if (pixoff.height() > size.height()) - pixoff = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); - newIcon.addPixmap(pixoff, mode, QIcon::Off); - QPixmap pixon = icon.pixmap(size, mode, QIcon::On); - if (pixon.height() > size.height()) - pixon = pixoff.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation); - newIcon.addPixmap(pixon, mode, QIcon::On); - } +void GuiIconProvider::setIconSet(GuiIconProvider::IconSet v) +{ + if (iconSet() != v) { + iconSetSetting() = v; + instance()->update(); + } +} + +bool GuiIconProvider::stateIconsAreColorized() +{ + return stateIconsAreColorizedSetting(); +} + +void GuiIconProvider::setStateIconsAreColorized(bool v) +{ + if (v != stateIconsAreColorized()) { + stateIconsAreColorizedSetting() = v; + instance()->update(); } +} - return newIcon; +void GuiIconProvider::colorThemeChanged() +{ + update(); } + +void GuiIconProvider::reset() +{ + using BitTorrent::TorrentState; + m_torrentStateIcons[TorrentState::Downloading] = + m_torrentStateIcons[TorrentState::ForcedDownloading] = + m_torrentStateIcons[TorrentState::DownloadingMetadata] = QIcon(":/icons/skin/downloading.svg"); + m_torrentStateIcons[TorrentState::Allocating] = + m_torrentStateIcons[TorrentState::StalledDownloading] = QIcon(":/icons/skin/stalledDL.svg"); + m_torrentStateIcons[TorrentState::StalledUploading] = QIcon(":/icons/skin/stalledUP.svg"); + m_torrentStateIcons[TorrentState::Uploading] = + m_torrentStateIcons[TorrentState::ForcedUploading] = QIcon(":/icons/skin/uploading.svg"); + m_torrentStateIcons[TorrentState::PausedDownloading] = QIcon(":/icons/skin/paused.svg"); + m_torrentStateIcons[TorrentState::PausedUploading] = QIcon(":/icons/skin/completed.svg"); + m_torrentStateIcons[TorrentState::QueuedDownloading] = + m_torrentStateIcons[TorrentState::QueuedUploading] = QIcon(":/icons/skin/queued.svg"); + m_torrentStateIcons[TorrentState::CheckingDownloading] = + m_torrentStateIcons[TorrentState::CheckingUploading] = +#if LIBTORRENT_VERSION_NUM < 10100 + m_torrentStateIcons[TorrentState::QueuedForChecking] = #endif + m_torrentStateIcons[TorrentState::CheckingResumeData] = QIcon(":/icons/skin/checking.svg"); + m_torrentStateIcons[TorrentState::Unknown] = + m_torrentStateIcons[TorrentState::MissingFiles] = + m_torrentStateIcons[TorrentState::Error] = QIcon(":/icons/skin/error.svg"); +} -QString GuiIconProvider::getIconPath(const QString &iconId) +void GuiIconProvider::update() { -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - if (m_useSystemTheme) { - QString path = QDir::temp().absoluteFilePath(iconId + ".png"); - if (!QFile::exists(path)) { - const QIcon icon = QIcon::fromTheme(iconId); - if (!icon.isNull()) - icon.pixmap(32).save(path); - else - path = IconProvider::getIconPath(iconId); + if (iconSet() == IconSet::Monochrome) { + decolorizeIcons(); + setIconDir(m_coloredIconsDir.path()); + } + else { + setIconDir(IconProvider::defaultIconDir()); + } + + using BitTorrent::TorrentState; + const auto trySetColorizedIcon = [this](BitTorrent::TorrentState state, const char *stateName, const char *iconName) + { + const QString iconPath = QString(QLatin1String(":/icons/skin/%1.svg")).arg(QLatin1String(iconName)); + const QString colorizedIconPath = QDir(this->m_coloredIconsDir.path()) + .filePath(QLatin1String(stateName) + QLatin1String(".svg")); + try { + m_svgManipulator->replaceSVGFillColor(iconPath, colorizedIconPath, + Theme::ColorTheme::current().torrentStateColor(state)); + m_torrentStateIcons[state] = QIcon(colorizedIconPath); } + catch (std::runtime_error &ex) { + qCWarning(theme, "Could not colorize icon '%s': '%s'", iconName, ex.what()); + m_torrentStateIcons[state] = QIcon(iconPath); + } + }; - return path; - } + if (stateIconsAreColorized() && m_coloredIconsDir.isValid()) { + trySetColorizedIcon(TorrentState::Downloading, "torrent-state-downloading", "downloading"); + trySetColorizedIcon(TorrentState::ForcedDownloading, "torrent-state-forceddownloading", "downloading"); + trySetColorizedIcon(TorrentState::DownloadingMetadata, "torrent-state-downloadingmetadata", "downloading"); + trySetColorizedIcon(TorrentState::Allocating, "torrent-state-allocating", "stalledDL"); + trySetColorizedIcon(TorrentState::StalledDownloading, "torrent-state-stalleddownloading", "stalledDL"); + trySetColorizedIcon(TorrentState::StalledUploading, "torrent-state-stalleduploading", "stalledUP"); + trySetColorizedIcon(TorrentState::Uploading, "torrent-state-Uploading", "uploading"); + trySetColorizedIcon(TorrentState::ForcedUploading, "torrent-state-forceduploading", "uploading"); + trySetColorizedIcon(TorrentState::PausedDownloading, "torrent-state-pauseddownloading", "paused"); + trySetColorizedIcon(TorrentState::PausedUploading, "torrent-state-pauseduploading", "completed"); + trySetColorizedIcon(TorrentState::QueuedDownloading, "torrent-state-queueddownloading", "queued"); + trySetColorizedIcon(TorrentState::QueuedUploading, "torrent-state-queueduploading", "queued"); + trySetColorizedIcon(TorrentState::CheckingDownloading, "torrent-state-checkingdownloading", "checking"); + trySetColorizedIcon(TorrentState::CheckingUploading, "torrent-state-checkinguploading", "checking"); +#if LIBTORRENT_VERSION_NUM < 10100 + trySetColorizedIcon(TorrentState::QueuedForChecking, "torrent-state-queuedforchecking", "checking"); #endif - return IconProvider::getIconPath(iconId); + trySetColorizedIcon(TorrentState::CheckingResumeData, "torrent-state-checkingresumedata", "checking"); + trySetColorizedIcon(TorrentState::Unknown, "torrent-state-unknown", "error"); + trySetColorizedIcon(TorrentState::MissingFiles, "torrent-state-missingfiles", "error"); + trySetColorizedIcon(TorrentState::Error, "torrent-state-error", "error"); + } + else { + reset(); + } + + emit iconsChanged(); } -void GuiIconProvider::configure() +void GuiIconProvider::decolorizeIcons() { -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - m_useSystemTheme = Preferences::instance()->useSystemIconTheme(); -#endif + // process every svg file from :/icons/qbt-theme/ + QDir srcIconsDir(QLatin1String(":/icons/qbt-theme/")); + const QStringList icons = srcIconsDir.entryList({QLatin1String("*.svg")}, QDir::Files); + const QColor newIconColor = QPalette().color(QPalette::WindowText); + for (const QString &iconFile: icons) { + try { + m_svgManipulator->replaceSVGFillColor(srcIconsDir.absoluteFilePath(iconFile), + m_coloredIconsDir.path() + QDir::separator() + iconFile, newIconColor); + } + catch (std::runtime_error &ex) { + qCWarning(theme, "Could not colorize icon '%s': '%s'", qPrintable(iconFile), ex.what()); + } + } +} + +QString GuiIconProvider::colorizedIconsDir() +{ + // TODO Application should create QTemporaryDir for /run/user/// + // and we then will be able to create directory "icons" inside + + QString runPath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation); + if (runPath.isEmpty()) runPath = QDir::tempPath(); + + return runPath + QDir::separator() + + QCoreApplication::applicationName() + + QLatin1String("_icons_"); +} + +CachedSettingValue &GuiIconProvider::iconSetSetting() +{ + static CachedSettingValue setting("Appearance/IconSet", IconSet::Default); + return setting; +} + +CachedSettingValue &GuiIconProvider::stateIconsAreColorizedSetting() +{ + static CachedSettingValue setting("Appearance/StateIconColorization", true); + return setting; } diff --git a/src/gui/guiiconprovider.h b/src/gui/guiiconprovider.h index 665a7fabeb..700aad228a 100644 --- a/src/gui/guiiconprovider.h +++ b/src/gui/guiiconprovider.h @@ -30,9 +30,19 @@ #ifndef GUIICONPROVIDER_H #define GUIICONPROVIDER_H +#include +#include +#include + #include "base/iconprovider.h" class QIcon; +template class CachedSettingValue; + +namespace BitTorrent +{ + enum class TorrentState; +} class GuiIconProvider : public IconProvider { @@ -46,19 +56,47 @@ class GuiIconProvider : public IconProvider QIcon getIcon(const QString &iconId); QIcon getIcon(const QString &iconId, const QString &fallback); QIcon getFlagIcon(const QString &countryIsoCode); - QString getIconPath(const QString &iconId); + + QIcon icon(BitTorrent::TorrentState state) const; + + enum class IconSet + { + Default, + Monochrome, + SystemTheme, + }; + + static bool stateIconsAreColorized(); + static void setStateIconsAreColorized(bool v); + + static IconSet iconSet(); + static void setIconSet(IconSet v); + +signals: + void iconsChanged(); private slots: - void configure(); + void colorThemeChanged(); private: explicit GuiIconProvider(QObject *parent = 0); ~GuiIconProvider(); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - QIcon generateDifferentSizes(const QIcon &icon); - bool m_useSystemTheme; -#endif + Q_ENUM(IconSet) + + class SVGManipulator; + + void update(); + void reset(); + void decolorizeIcons(); + + static QString colorizedIconsDir(); + static CachedSettingValue &iconSetSetting(); + static CachedSettingValue &stateIconsAreColorizedSetting(); + + QMap m_torrentStateIcons; // these icons are needed frequently + QTemporaryDir m_coloredIconsDir; + QScopedPointer m_svgManipulator; }; #endif // GUIICONPROVIDER_H diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 9f850cc499..82b8a592bd 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -161,7 +161,7 @@ MainWindow::MainWindow(QWidget *parent) // Setting icons #ifndef Q_OS_MAC #ifdef Q_OS_UNIX - if (Preferences::instance()->useSystemIconTheme()) + if (GuiIconProvider::iconSet() == GuiIconProvider::IconSet::SystemTheme) setWindowIcon(QIcon::fromTheme("qbittorrent", QIcon(":/icons/skin/qbittorrent32.png"))); else #endif // Q_OS_UNIX @@ -1504,10 +1504,10 @@ void MainWindow::updateGUI() html += "qBittorrent"; html += ""; html += "
"; - html += " " + tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate, true)); + html += " " + tr("DL speed: %1", "e.g: Download speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadDownloadRate, true)); html += "
"; html += "
"; - html += " " + tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadUploadRate, true)); + html += " " + tr("UP speed: %1", "e.g: Upload speed: 10 KiB/s").arg(Utils::Misc::friendlyUnit(status.payloadUploadRate, true)); html += "
"; #else // OSes such as Windows do not support html here diff --git a/src/gui/optionsdlg.cpp b/src/gui/optionsdlg.cpp index 153d678888..edabb7da8a 100644 --- a/src/gui/optionsdlg.cpp +++ b/src/gui/optionsdlg.cpp @@ -65,6 +65,7 @@ #include "base/utils/random.h" #include "addnewtorrentdialog.h" #include "advancedsettings.h" +#include "guiiconprovider.h" #include "rss/automatedrssdownloader.h" #include "theme/themeexceptions.h" #include "theme/themeinfo.h" @@ -72,6 +73,7 @@ #include "banlistoptions.h" #include "guiiconprovider.h" #include "scanfoldersdelegate.h" +#include "torrentmodel.h" #include "ui_optionsdlg.h" @@ -239,7 +241,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) } #if !((defined(Q_OS_UNIX) && !defined(Q_OS_MAC))) - m_ui->checkUseSystemTheme->setHidden(true); + // system icon theme is supported on Linux only + m_ui->comboIconTheme->removeItem(static_cast(GuiIconProvider::IconSet::SystemTheme)); #endif // Hide the Appearance/Desktop section if it doesn't contain any visible children. @@ -312,9 +315,6 @@ OptionsDialog::OptionsDialog(QWidget *parent) // General tab connect(m_ui->comboI18n, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); connect(m_ui->confirmDeletion, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - connect(m_ui->checkUseSystemTheme, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); -#endif connect(m_ui->checkAltRowColors, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkHideZero, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); connect(m_ui->checkHideZero, &QAbstractButton::toggled, m_ui->comboHideZero, &QWidget::setEnabled); @@ -350,10 +350,13 @@ OptionsDialog::OptionsDialog(QWidget *parent) connect(m_ui->comboFileLogAgeType, qComboBoxCurrentIndexChanged, this, &ThisType::enableApplyButton); // Appearance tab + connect(m_ui->comboIconTheme, qComboBoxActivated, this, &ThisType::enableApplyButton); connect(m_ui->comboBoxColorTheme, qComboBoxActivated, this, &ThisType::colorThemeActivated); connect(m_ui->comboBoxFontTheme, qComboBoxActivated, this, &ThisType::fontThemeActivated); connect(m_ui->toolButtonExportColorTheme, &QToolButton::clicked, this, &ThisType::exportColorTheme); connect(m_ui->toolButtonExportFontTheme, &QToolButton::clicked, this, &ThisType::exportFontTheme); + connect(m_ui->checkColorizeStateIcons, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); + connect(m_ui->checkColorizeTransferList, &QAbstractButton::toggled, this, &ThisType::enableApplyButton); // Downloads tab connect(m_ui->textSavePath, &FileSystemPathEdit::selectedPathChanged, this, &ThisType::enableApplyButton); @@ -629,6 +632,8 @@ void OptionsDialog::saveOptions() // Appearance preferences + GuiIconProvider::setIconSet(static_cast(m_ui->comboIconTheme->currentIndex())); + const auto applyTheme = [this](Theme::Kind kind, const QString &themeName) { @@ -673,13 +678,15 @@ void OptionsDialog::saveOptions() applyTheme(Theme::Kind::Color, themeEntry(m_ui->comboBoxColorTheme).info.name()); applyTheme(Theme::Kind::Font, themeEntry(m_ui->comboBoxFontTheme).info.name()); + GuiIconProvider::setStateIconsAreColorized(m_ui->checkColorizeStateIcons->isChecked()); + TorrentModel::setTextIsColorized(m_ui->checkColorizeTransferList->isChecked()); + // end Appearance preferences + // General preferences pref->setLocale(locale); pref->setConfirmTorrentDeletion(m_ui->confirmDeletion->isChecked()); pref->setAlternatingRowColors(m_ui->checkAltRowColors->isChecked()); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - pref->setSystemIconTheme(m_ui->checkUseSystemTheme->isChecked()); -#endif + pref->setHideZeroValues(m_ui->checkHideZero->isChecked()); pref->setHideZeroComboValues(m_ui->comboHideZero->currentIndex()); #ifndef Q_OS_MAC @@ -895,9 +902,6 @@ void OptionsDialog::loadOptions() setLocale(pref->getLocale()); m_ui->confirmDeletion->setChecked(pref->confirmTorrentDeletion()); m_ui->checkAltRowColors->setChecked(pref->useAlternatingRowColors()); -#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) - m_ui->checkUseSystemTheme->setChecked(pref->useSystemIconTheme()); -#endif m_ui->checkHideZero->setChecked(pref->getHideZeroValues()); m_ui->comboHideZero->setEnabled(m_ui->checkHideZero->isChecked()); m_ui->comboHideZero->setCurrentIndex(pref->getHideZeroComboValues()); @@ -945,6 +949,12 @@ void OptionsDialog::loadOptions() m_ui->comboFileLogAgeType->setCurrentIndex(app->fileLoggerAgeType()); // End General preferences + // Appearance preferences + m_ui->comboIconTheme->setCurrentIndex(static_cast(GuiIconProvider::iconSet())); + m_ui->checkColorizeStateIcons->setChecked(GuiIconProvider::stateIconsAreColorized()); + m_ui->checkColorizeTransferList->setChecked(TorrentModel::textIsColorized()); + // end Appearance preferences + m_ui->checkRSSEnable->setChecked(RSS::Session::instance()->isProcessingEnabled()); m_ui->checkRSSAutoDownloaderEnable->setChecked(RSS::AutoDownloader::instance()->isProcessingEnabled()); m_ui->spinRSSRefreshInterval->setValue(RSS::Session::instance()->refreshInterval()); @@ -1897,11 +1907,11 @@ bool OptionsDialog::setSslKey(const QByteArray &key) // try different formats const bool isKeyValid = (!QSslKey(key, QSsl::Rsa).isNull() || !QSslKey(key, QSsl::Ec).isNull()); if (isKeyValid) { - m_ui->lblSslKeyStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-high.png").scaledToHeight(20, Qt::SmoothTransformation)); + m_ui->lblSslKeyStatus->setPixmap(GuiIconProvider::instance()->getIcon(QLatin1String("security-high")).pixmap(20, 20)); m_sslKey = key; } else { - m_ui->lblSslKeyStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-low.png").scaledToHeight(20, Qt::SmoothTransformation)); + m_ui->lblSslKeyStatus->setPixmap(GuiIconProvider::instance()->getIcon(QLatin1String("security-low")).pixmap(20, 20)); m_sslKey.clear(); } return isKeyValid; @@ -1916,11 +1926,11 @@ bool OptionsDialog::setSslCertificate(const QByteArray &cert) #ifndef QT_NO_OPENSSL const bool isCertValid = !QSslCertificate(cert).isNull(); if (isCertValid) { - m_ui->lblSslCertStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-high.png").scaledToHeight(20, Qt::SmoothTransformation)); + m_ui->lblSslCertStatus->setPixmap(GuiIconProvider::instance()->getIcon(QLatin1String("security-high")).pixmap(20, 20)); m_sslCert = cert; } else { - m_ui->lblSslCertStatus->setPixmap(QPixmap(":/icons/qbt-theme/security-low.png").scaledToHeight(20, Qt::SmoothTransformation)); + m_ui->lblSslCertStatus->setPixmap(GuiIconProvider::instance()->getIcon(QLatin1String("security-low")).pixmap(20, 20)); m_sslCert.clear(); } return isCertValid; diff --git a/src/gui/optionsdlg.ui b/src/gui/optionsdlg.ui index d980f10143..0d35bc3323 100644 --- a/src/gui/optionsdlg.ui +++ b/src/gui/optionsdlg.ui @@ -201,14 +201,52 @@ Desktop - - - + + + - Use system icon theme + Icon theme: + + + + + + + Default + + + + + Monochrome + + + + + System theme + + + + + + + + + true + + + + (Requires restart) + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + @@ -286,7 +324,24 @@
- + + + + Colorize text in transfer list + + + true + + + + + + + Colorize state icons + + + + Font theme: @@ -294,7 +349,7 @@ - + diff --git a/src/gui/search/searchtab.cpp b/src/gui/search/searchtab.cpp index 786da6fd52..838e283ff4 100644 --- a/src/gui/search/searchtab.cpp +++ b/src/gui/search/searchtab.cpp @@ -277,15 +277,15 @@ QString SearchTab::statusIconName(SearchTab::Status st) { switch (st) { case Status::Ongoing: - return QLatin1String("task-ongoing"); + return QLatin1String("state-sync"); case Status::Finished: - return QLatin1String("task-complete"); + return QLatin1String("state-ok"); case Status::Aborted: - return QLatin1String("task-reject"); + return QLatin1String("state-warning"); case Status::Error: - return QLatin1String("task-attention"); + return QLatin1String("state-error"); case Status::NoResults: - return QLatin1String("task-attention"); + return QLatin1String("state-offline"); default: return QString(); } diff --git a/src/gui/statusbar.cpp b/src/gui/statusbar.cpp index 20927f928b..3fcb105023 100644 --- a/src/gui/statusbar.cpp +++ b/src/gui/statusbar.cpp @@ -38,6 +38,7 @@ #include "base/bittorrent/session.h" #include "base/bittorrent/sessionstatus.h" +#include "base/bittorrent/torrenthandle.h" #include "base/utils/misc.h" #include "guiiconprovider.h" #include "speedlimitdlg.h" @@ -70,7 +71,7 @@ StatusBar::StatusBar(QWidget *parent) connect(m_connecStatusLblIcon, &QAbstractButton::clicked, this, &StatusBar::connectionButtonClicked); m_dlSpeedLbl = new QPushButton(this); - m_dlSpeedLbl->setIcon(QIcon(":/icons/skin/download.png")); + m_dlSpeedLbl->setIcon(GuiIconProvider::instance()->getIcon(QLatin1String("cloud-download"))); connect(m_dlSpeedLbl, &QAbstractButton::clicked, this, &StatusBar::capDownloadSpeed); m_dlSpeedLbl->setFlat(true); m_dlSpeedLbl->setFocusPolicy(Qt::NoFocus); @@ -79,7 +80,7 @@ StatusBar::StatusBar(QWidget *parent) m_dlSpeedLbl->setMinimumWidth(200); m_upSpeedLbl = new QPushButton(this); - m_upSpeedLbl->setIcon(QIcon(":/icons/skin/seeding.png")); + m_upSpeedLbl->setIcon(GuiIconProvider::instance()->getIcon(QLatin1String("cloud-upload"))); connect(m_upSpeedLbl, &QAbstractButton::clicked, this, &StatusBar::capUploadSpeed); m_upSpeedLbl->setFlat(true); m_upSpeedLbl->setFocusPolicy(Qt::NoFocus); @@ -174,17 +175,17 @@ void StatusBar::updateConnectionStatus() const BitTorrent::SessionStatus &sessionStatus = BitTorrent::Session::instance()->status(); if (!BitTorrent::Session::instance()->isListening()) { - m_connecStatusLblIcon->setIcon(QIcon(QLatin1String(":/icons/skin/disconnected.png"))); + m_connecStatusLblIcon->setIcon(GuiIconProvider::instance()->getIcon(QLatin1String("state-offline"))); m_connecStatusLblIcon->setToolTip(QLatin1String("") + tr("Connection Status:") + QLatin1String("
") + tr("Offline. This usually means that qBittorrent failed to listen on the selected port for incoming connections.")); } else { if (sessionStatus.hasIncomingConnections) { // Connection OK - m_connecStatusLblIcon->setIcon(QIcon(QLatin1String(":/icons/skin/connected.png"))); + m_connecStatusLblIcon->setIcon(GuiIconProvider::instance()->getIcon(QLatin1String("state-ok"))); m_connecStatusLblIcon->setToolTip(QLatin1String("") + tr("Connection Status:") + QLatin1String("
") + tr("Online")); } else { - m_connecStatusLblIcon->setIcon(QIcon(QLatin1String(":/icons/skin/firewalled.png"))); + m_connecStatusLblIcon->setIcon(GuiIconProvider::instance()->getIcon(QLatin1String("state-warning"))); m_connecStatusLblIcon->setToolTip(QLatin1String("") + tr("Connection status:") + QLatin1String("
") + QLatin1String("") + tr("No direct connections. This may indicate network configuration problems.") + QLatin1String("")); } } diff --git a/src/gui/theme/themecommon.cpp b/src/gui/theme/themecommon.cpp index fff2197b1b..75827797c0 100644 --- a/src/gui/theme/themecommon.cpp +++ b/src/gui/theme/themecommon.cpp @@ -28,6 +28,7 @@ #include "themecommon.h" +#include #include bool Theme::isDarkTheme() diff --git a/src/gui/theme/themecommon.h b/src/gui/theme/themecommon.h index 45b6a99187..3b0c19cfd2 100644 --- a/src/gui/theme/themecommon.h +++ b/src/gui/theme/themecommon.h @@ -33,6 +33,9 @@ Q_DECLARE_LOGGING_CATEGORY(theme) +class QColor; +class QTemporaryFile; + namespace Theme { enum class Kind diff --git a/src/gui/torrentmodel.cpp b/src/gui/torrentmodel.cpp index df8f9572ea..42234e5ea6 100644 --- a/src/gui/torrentmodel.cpp +++ b/src/gui/torrentmodel.cpp @@ -33,27 +33,19 @@ #include #include +#include #include +#include #include #include "base/bittorrent/session.h" #include "base/bittorrent/torrenthandle.h" +#include "base/settingvalue.h" #include "base/torrentfilter.h" #include "base/utils/fs.h" +#include "guiiconprovider.h" #include "theme/colortheme.h" -static QIcon getIconByState(BitTorrent::TorrentState state); - -static QIcon getPausedIcon(); -static QIcon getQueuedIcon(); -static QIcon getDownloadingIcon(); -static QIcon getStalledDownloadingIcon(); -static QIcon getUploadingIcon(); -static QIcon getStalledUploadingIcon(); -static QIcon getCompletedIcon(); -static QIcon getCheckingIcon(); -static QIcon getErrorIcon(); - // TorrentModel TorrentModel::TorrentModel(QObject *parent) @@ -165,10 +157,12 @@ QVariant TorrentModel::data(const QModelIndex &index, int role) const if (!torrent) return QVariant(); if ((role == Qt::DecorationRole) && (index.column() == TR_NAME)) - return getIconByState(torrent->state()); + return GuiIconProvider::instance()->icon(torrent->state()); if (role == Qt::ForegroundRole) - return Theme::ColorTheme::current().torrentStateColor(torrent->state()); + return textIsColorized() + ? Theme::ColorTheme::current().torrentStateColor(torrent->state()) + : QGuiApplication::palette().color(QPalette::WindowText); if ((role != Qt::DisplayRole) && (role != Qt::UserRole)) return QVariant(); @@ -295,6 +289,16 @@ BitTorrent::TorrentHandle *TorrentModel::torrentHandle(const QModelIndex &index) return m_torrents.value(index.row()); } +bool TorrentModel::textIsColorized() +{ + return textIsColorizedSetting(); +} + +void TorrentModel::setTextIsColorized(bool v) +{ + textIsColorizedSetting() = v; +} + void TorrentModel::handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent) { const int row = m_torrents.indexOf(torrent); @@ -317,98 +321,8 @@ void TorrentModel::handleTorrentsUpdated() emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); } -// Static functions - -QIcon getIconByState(BitTorrent::TorrentState state) -{ - switch (state) { - case BitTorrent::TorrentState::Downloading: - case BitTorrent::TorrentState::ForcedDownloading: - case BitTorrent::TorrentState::DownloadingMetadata: - return getDownloadingIcon(); - case BitTorrent::TorrentState::Allocating: - case BitTorrent::TorrentState::StalledDownloading: - return getStalledDownloadingIcon(); - case BitTorrent::TorrentState::StalledUploading: - return getStalledUploadingIcon(); - case BitTorrent::TorrentState::Uploading: - case BitTorrent::TorrentState::ForcedUploading: - return getUploadingIcon(); - case BitTorrent::TorrentState::PausedDownloading: - return getPausedIcon(); - case BitTorrent::TorrentState::PausedUploading: - return getCompletedIcon(); - case BitTorrent::TorrentState::QueuedDownloading: - case BitTorrent::TorrentState::QueuedUploading: - return getQueuedIcon(); - case BitTorrent::TorrentState::CheckingDownloading: - case BitTorrent::TorrentState::CheckingUploading: -#if LIBTORRENT_VERSION_NUM < 10100 - case BitTorrent::TorrentState::QueuedForChecking: -#endif - case BitTorrent::TorrentState::CheckingResumeData: - return getCheckingIcon(); - case BitTorrent::TorrentState::Unknown: - case BitTorrent::TorrentState::MissingFiles: - case BitTorrent::TorrentState::Error: - return getErrorIcon(); - default: - Q_ASSERT(false); - return getErrorIcon(); - } -} - -QIcon getPausedIcon() -{ - static QIcon cached = QIcon(":/icons/skin/paused.png"); - return cached; -} - -QIcon getQueuedIcon() -{ - static QIcon cached = QIcon(":/icons/skin/queued.png"); - return cached; -} - -QIcon getDownloadingIcon() +CachedSettingValue &TorrentModel::textIsColorizedSetting() { - static QIcon cached = QIcon(":/icons/skin/downloading.png"); - return cached; + static CachedSettingValue setting("Appearance/TransferListIsColorized", true); + return setting; } - -QIcon getStalledDownloadingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/stalledDL.png"); - return cached; -} - -QIcon getUploadingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/uploading.png"); - return cached; -} - -QIcon getStalledUploadingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/stalledUP.png"); - return cached; -} - -QIcon getCompletedIcon() -{ - static QIcon cached = QIcon(":/icons/skin/completed.png"); - return cached; -} - -QIcon getCheckingIcon() -{ - static QIcon cached = QIcon(":/icons/skin/checking.png"); - return cached; -} - -QIcon getErrorIcon() -{ - static QIcon cached = QIcon(":/icons/skin/error.png"); - return cached; -} - diff --git a/src/gui/torrentmodel.h b/src/gui/torrentmodel.h index fd9161ec8c..f04f27d665 100644 --- a/src/gui/torrentmodel.h +++ b/src/gui/torrentmodel.h @@ -35,6 +35,8 @@ #include #include +template class CachedSettingValue; + namespace BitTorrent { class InfoHash; @@ -94,6 +96,9 @@ class TorrentModel : public QAbstractListModel BitTorrent::TorrentHandle *torrentHandle(const QModelIndex &index) const; + static bool textIsColorized(); + static void setTextIsColorized(bool v); + private slots: void addTorrent(BitTorrent::TorrentHandle *const torrent); void handleTorrentAboutToBeRemoved(BitTorrent::TorrentHandle *const torrent); @@ -101,6 +106,8 @@ private slots: void handleTorrentsUpdated(); private: + static CachedSettingValue &textIsColorizedSetting(); + QList m_torrents; }; diff --git a/src/gui/trackerlogin.cpp b/src/gui/trackerlogin.cpp index e2d4252218..2245c94398 100644 --- a/src/gui/trackerlogin.cpp +++ b/src/gui/trackerlogin.cpp @@ -33,6 +33,7 @@ #include #include #include "base/bittorrent/torrenthandle.h" +#include "guiiconprovider.h" trackerLogin::trackerLogin(QWidget *parent, BitTorrent::TorrentHandle *const torrent) : QDialog(parent) @@ -40,11 +41,8 @@ trackerLogin::trackerLogin(QWidget *parent, BitTorrent::TorrentHandle *const tor { setupUi(this); setAttribute(Qt::WA_DeleteOnClose); - buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Log in")); - - login_logo->setPixmap(QPixmap(QString::fromUtf8(":/icons/qbt-theme/encrypted.png"))); - + login_logo->setPixmap(GuiIconProvider::instance()->getIcon(QLatin1String("encrypted")).pixmap(32, 32)); tracker_url->setText(torrent->currentTracker()); connect(buttonBox, &QDialogButtonBox::accepted, this, &trackerLogin::loginButtonClicked); diff --git a/src/gui/transferlistfilterswidget.cpp b/src/gui/transferlistfilterswidget.cpp index 6f750ad970..c07e874027 100644 --- a/src/gui/transferlistfilterswidget.cpp +++ b/src/gui/transferlistfilterswidget.cpp @@ -122,31 +122,27 @@ StatusFiltersWidget::StatusFiltersWidget(QWidget *parent, TransferListWidget *tr // Add status filters QListWidgetItem *all = new QListWidgetItem(this); all->setData(Qt::DisplayRole, QVariant(tr("All (0)", "this is for the status filter"))); - all->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterall.png")); QListWidgetItem *downloading = new QListWidgetItem(this); downloading->setData(Qt::DisplayRole, QVariant(tr("Downloading (0)"))); - downloading->setData(Qt::DecorationRole, QIcon(":/icons/skin/downloading.png")); QListWidgetItem *seeding = new QListWidgetItem(this); seeding->setData(Qt::DisplayRole, QVariant(tr("Seeding (0)"))); - seeding->setData(Qt::DecorationRole, QIcon(":/icons/skin/uploading.png")); QListWidgetItem *completed = new QListWidgetItem(this); completed->setData(Qt::DisplayRole, QVariant(tr("Completed (0)"))); - completed->setData(Qt::DecorationRole, QIcon(":/icons/skin/completed.png")); QListWidgetItem *resumed = new QListWidgetItem(this); resumed->setData(Qt::DisplayRole, QVariant(tr("Resumed (0)"))); - resumed->setData(Qt::DecorationRole, QIcon(":/icons/skin/resumed.png")); QListWidgetItem *paused = new QListWidgetItem(this); paused->setData(Qt::DisplayRole, QVariant(tr("Paused (0)"))); - paused->setData(Qt::DecorationRole, QIcon(":/icons/skin/paused.png")); QListWidgetItem *active = new QListWidgetItem(this); active->setData(Qt::DisplayRole, QVariant(tr("Active (0)"))); - active->setData(Qt::DecorationRole, QIcon(":/icons/skin/filteractive.png")); QListWidgetItem *inactive = new QListWidgetItem(this); inactive->setData(Qt::DisplayRole, QVariant(tr("Inactive (0)"))); - inactive->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterinactive.png")); QListWidgetItem *errored = new QListWidgetItem(this); errored->setData(Qt::DisplayRole, QVariant(tr("Errored (0)"))); - errored->setData(Qt::DecorationRole, QIcon(":/icons/skin/error.png")); + + updateStatusIcons(); + + connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentsUpdated, this, &StatusFiltersWidget::updateTorrentNumbers); + connect(GuiIconProvider::instance(), &GuiIconProvider::iconsChanged, this, &StatusFiltersWidget::updateStatusIcons); const Preferences* const pref = Preferences::instance(); setCurrentRow(pref->getTransSelFilter(), QItemSelectionModel::SelectCurrent); @@ -173,6 +169,23 @@ void StatusFiltersWidget::updateTorrentNumbers() item(TorrentFilter::Errored)->setData(Qt::DisplayRole, QVariant(tr("Errored (%1)").arg(report.nbErrored))); } +void StatusFiltersWidget::updateStatusIcons() +{ + const GuiIconProvider* icons = GuiIconProvider::instance(); // shortcut + using BitTorrent::TorrentState; + + item(TorrentFilter::All)->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterall.svg")); + item(TorrentFilter::Downloading)->setData(Qt::DecorationRole, icons->icon(TorrentState::Downloading)); + item(TorrentFilter::Seeding)->setData(Qt::DecorationRole, icons->icon(TorrentState::Uploading)); + item(TorrentFilter::Completed)->setData(Qt::DecorationRole, icons->icon(TorrentState::PausedUploading)); + item(TorrentFilter::Resumed)->setData(Qt::DecorationRole, QIcon(":/icons/skin/resumed.svg")); + item(TorrentFilter::Paused)->setData(Qt::DecorationRole, icons->icon(TorrentState::PausedDownloading)); + item(TorrentFilter::Active)->setData(Qt::DecorationRole, QIcon(":/icons/skin/filteractive.svg")); + item(TorrentFilter::Inactive)->setData(Qt::DecorationRole, QIcon(":/icons/skin/filterinactive.svg")); + item(TorrentFilter::Errored)->setData(Qt::DecorationRole, icons->icon(TorrentState::Error)); +} + + void StatusFiltersWidget::showMenu(QPoint) {} void StatusFiltersWidget::applyFilter(int row) diff --git a/src/gui/transferlistfilterswidget.h b/src/gui/transferlistfilterswidget.h index 98b1d6e9f6..62b7ca5ad4 100644 --- a/src/gui/transferlistfilterswidget.h +++ b/src/gui/transferlistfilterswidget.h @@ -80,6 +80,7 @@ class StatusFiltersWidget: public FiltersBase private slots: void updateTorrentNumbers(); + void updateStatusIcons(); private: // These 4 methods are virtual slots in the base class. diff --git a/src/gui/transferlistwidget.cpp b/src/gui/transferlistwidget.cpp index da9abad060..ae9ef58b25 100644 --- a/src/gui/transferlistwidget.cpp +++ b/src/gui/transferlistwidget.cpp @@ -850,7 +850,7 @@ void TransferListWidget::displayListMenu(const QPoint&) connect(&actionDelete, SIGNAL(triggered()), this, SLOT(softDeleteSelectedTorrents())); QAction actionPreview_file(GuiIconProvider::instance()->getIcon("view-preview"), tr("Preview file..."), 0); connect(&actionPreview_file, SIGNAL(triggered()), this, SLOT(previewSelectedTorrents())); - QAction actionSet_max_ratio(QIcon(QString::fromUtf8(":/icons/skin/ratio.png")), tr("Limit share ratio..."), 0); + QAction actionSet_max_ratio(QIcon(QString::fromUtf8(":/icons/skin/ratio.svg")), tr("Limit share ratio..."), 0); connect(&actionSet_max_ratio, SIGNAL(triggered()), this, SLOT(setMaxRatioSelectedTorrents())); QAction actionSet_upload_limit(GuiIconProvider::instance()->getIcon("kt-set-max-upload-speed"), tr("Limit upload rate..."), 0); connect(&actionSet_upload_limit, SIGNAL(triggered()), this, SLOT(setUpLimitSelectedTorrents())); diff --git a/src/icons.qrc b/src/icons.qrc index 3f325e9d18..3113624e20 100644 --- a/src/icons.qrc +++ b/src/icons.qrc @@ -242,109 +242,111 @@ icons/flags/za.png icons/flags/zm.png icons/flags/zw.png - icons/L.gif - icons/loading.png - icons/qbittorrent.png - icons/qbt-theme/application-exit.png - icons/qbt-theme/application-rss+xml.png - icons/qbt-theme/application-x-mswinurl.png - icons/qbt-theme/checked.png - icons/qbt-theme/configure.png - icons/qbt-theme/dialog-cancel.png - icons/qbt-theme/dialog-information.png - icons/qbt-theme/dialog-warning.png - icons/qbt-theme/document-edit-verify.png - icons/qbt-theme/document-edit.png - icons/qbt-theme/document-encrypt.png - icons/qbt-theme/document-import.png - icons/qbt-theme/document-new.png - icons/qbt-theme/document-properties.png - icons/qbt-theme/document-save.png - icons/qbt-theme/download.png - icons/qbt-theme/edit-clear-history.png - icons/qbt-theme/edit-clear.png - icons/qbt-theme/edit-copy.png - icons/qbt-theme/edit-cut.png - icons/qbt-theme/edit-delete.png - icons/qbt-theme/edit-find-user.png - icons/qbt-theme/edit-find.png - icons/qbt-theme/edit-paste.png - icons/qbt-theme/edit-rename.png - icons/qbt-theme/folder-documents.png - icons/qbt-theme/folder-download.png - icons/qbt-theme/folder-new.png - icons/qbt-theme/folder-remote.png - icons/qbt-theme/gear.png - icons/qbt-theme/gear32.png - icons/qbt-theme/go-bottom.png - icons/qbt-theme/go-down.png - icons/qbt-theme/go-top.png - icons/qbt-theme/go-up.png - icons/qbt-theme/help-about.png - icons/qbt-theme/help-contents.png - icons/qbt-theme/inode-directory.png - icons/qbt-theme/insert-link.png - icons/qbt-theme/kt-magnet.png - icons/qbt-theme/kt-set-max-download-speed.png - icons/qbt-theme/kt-set-max-upload-speed.png - icons/qbt-theme/list-add.png - icons/qbt-theme/list-remove.png - icons/qbt-theme/mail-folder-inbox.png - icons/qbt-theme/mail-mark-read.png - icons/qbt-theme/media-playback-pause.png - icons/qbt-theme/media-playback-start.png - icons/qbt-theme/media-seek-forward.png - icons/qbt-theme/network-server.png - icons/qbt-theme/network-wired.png - icons/qbt-theme/object-locked.png - icons/qbt-theme/office-chart-line.png - icons/qbt-theme/preferences-desktop.png - icons/qbt-theme/preferences-desktop-theme.png - icons/qbt-theme/preferences-other.png - icons/qbt-theme/preferences-system-network.png - icons/qbt-theme/preferences-web-browser-cookies.png - icons/qbt-theme/rss-config.png - icons/qbt-theme/security-high.png - icons/qbt-theme/security-low.png - icons/qbt-theme/services.png - icons/qbt-theme/speedometer.png - icons/qbt-theme/system-log-out.png - icons/qbt-theme/tab-close.png - icons/qbt-theme/task-attention.png - icons/qbt-theme/task-complete.png - icons/qbt-theme/task-ongoing.png - icons/qbt-theme/task-reject.png - icons/qbt-theme/text-plain.png - icons/qbt-theme/tools-report-bug.png - icons/qbt-theme/unavailable.png - icons/qbt-theme/user-group-delete.png - icons/qbt-theme/user-group-new.png - icons/qbt-theme/view-calendar-journal.png - icons/qbt-theme/view-categories.png - icons/qbt-theme/view-filter.png - icons/qbt-theme/view-preview.png - icons/qbt-theme/view-refresh.png - icons/qbt-theme/view-statistics.png - icons/qbt-theme/wallet-open.png - icons/qbt-theme/webui.png + icons/qbt-theme/application-exit.svg + icons/qbt-theme/application-rss+xml.svg + icons/qbt-theme/application-x-mswinurl.svg + icons/qbt-theme/cloud-download.svg + icons/qbt-theme/cloud-upload.svg + icons/qbt-theme/configure.svg + icons/qbt-theme/dialog-cancel.svg + icons/qbt-theme/dialog-information.svg + icons/qbt-theme/dialog-warning.svg + icons/qbt-theme/document-edit-verify.svg + icons/qbt-theme/document-edit.svg + icons/qbt-theme/document-encrypt.svg + icons/qbt-theme/document-import.svg + icons/qbt-theme/document-new.svg + icons/qbt-theme/document-properties.svg + icons/qbt-theme/document-save.svg + icons/qbt-theme/download.svg + icons/qbt-theme/edit-clear-history.svg + icons/qbt-theme/edit-clear.svg + icons/qbt-theme/edit-copy.svg + icons/qbt-theme/edit-cut.svg + icons/qbt-theme/edit-delete.svg + icons/qbt-theme/edit-find-user.svg + icons/qbt-theme/edit-find.svg + icons/qbt-theme/edit-paste.svg + icons/qbt-theme/edit-rename.svg + icons/qbt-theme/folder-documents.svg + icons/qbt-theme/folder-download.svg + icons/qbt-theme/folder-new.svg + icons/qbt-theme/folder-remote.svg + icons/qbt-theme/gear.svg + icons/qbt-theme/gear32.svg + icons/qbt-theme/go-down.svg + icons/qbt-theme/go-up.svg + icons/qbt-theme/help-about.svg + icons/qbt-theme/help-contents.svg + icons/qbt-theme/inode-directory.svg + icons/qbt-theme/insert-link.svg + icons/qbt-theme/kt-magnet.svg + icons/qbt-theme/kt-set-max-download-speed.svg + icons/qbt-theme/kt-set-max-upload-speed.svg + icons/qbt-theme/list-add.svg + icons/qbt-theme/list-remove.svg + icons/qbt-theme/mail-folder-inbox.svg + icons/qbt-theme/mail-mark-read.svg + icons/qbt-theme/media-playback-pause.svg + icons/qbt-theme/media-playback-start.svg + icons/qbt-theme/media-seek-forward.svg + icons/qbt-theme/network-server.svg + icons/qbt-theme/network-wired.svg + icons/qbt-theme/object-locked.svg + icons/qbt-theme/preferences-desktop.svg + icons/qbt-theme/preferences-desktop-theme.svg + icons/qbt-theme/preferences-other.svg + icons/qbt-theme/preferences-system-network.svg + icons/qbt-theme/preferences-web-browser-cookies.svg + icons/qbt-theme/security-high.svg + icons/qbt-theme/security-low.svg + icons/qbt-theme/services.svg + icons/qbt-theme/speedometer.svg + icons/qbt-theme/system-log-out.svg + icons/qbt-theme/go-bottom.svg + icons/qbt-theme/go-top.svg + icons/qbt-theme/checked.svg + icons/qbt-theme/office-chart-line.svg + icons/qbt-theme/rss-config.svg + icons/qbt-theme/state-download.svg + icons/qbt-theme/state-error.svg + icons/qbt-theme/state-information.svg + icons/qbt-theme/state-offline.svg + icons/qbt-theme/state-ok.svg + icons/qbt-theme/state-pause.svg + icons/qbt-theme/state-sync.svg + icons/qbt-theme/state-warning.svg + icons/qbt-theme/tab-close.svg + icons/qbt-theme/task-attention.svg + icons/qbt-theme/text-plain.svg + icons/qbt-theme/tools-report-bug.svg + icons/qbt-theme/unavailable.svg + icons/qbt-theme/user-group-delete.svg + icons/qbt-theme/user-group-new.svg + icons/qbt-theme/view-calendar-journal.svg + icons/qbt-theme/view-categories.svg + icons/qbt-theme/view-filter.svg + icons/qbt-theme/view-preview.svg + icons/qbt-theme/view-refresh.svg + icons/qbt-theme/view-statistics.svg + icons/qbt-theme/wallet-open.svg + icons/qbt-theme/webui.svg icons/skin/arrow-right.gif icons/skin/bg-dropdown.gif icons/skin/bg-handle-horizontal.gif icons/skin/bg-header.gif icons/skin/bg-panel-header.gif - icons/skin/checking.png + icons/skin/checking.svg icons/skin/collapse-expand.gif - icons/skin/completed.png - icons/skin/connected.png - icons/skin/disconnected.png + icons/skin/connected.svg + icons/skin/disconnected.svg icons/skin/dock-tabs.gif - icons/skin/download.png - icons/skin/downloading.png - icons/skin/error.png - icons/skin/filteractive.png - icons/skin/filterall.png - icons/skin/filterinactive.png - icons/skin/firewalled.png + icons/skin/downloading.svg + icons/skin/error.svg + icons/skin/filteractive.svg + icons/skin/filterall.svg + icons/skin/filterinactive.svg + icons/skin/firewalled.svg icons/skin/handle-icon-horizontal.gif icons/skin/handle-icon.gif icons/skin/knob.gif @@ -352,31 +354,31 @@ icons/skin/logo.gif icons/skin/logo2.gif icons/skin/mascot.png - icons/skin/paused.png - icons/skin/qbittorrent-tray-dark.svg - icons/skin/qbittorrent-tray-light.svg + icons/skin/paused.svg icons/skin/qbittorrent16.png icons/skin/qbittorrent22.png icons/skin/qbittorrent32.png - icons/skin/queued.png - icons/skin/ratio.png - icons/skin/resumed.png - icons/skin/seeding.png + icons/skin/qbittorrent-tray-dark.svg + icons/skin/qbittorrent-tray-light.svg + icons/skin/queued.svg + icons/skin/ratio.svg icons/skin/slider-area.gif icons/skin/spacer.gif icons/skin/spinner-placeholder.gif icons/skin/spinner.gif icons/skin/splash.png - icons/skin/stalledDL.png - icons/skin/stalledUP.png + icons/skin/stalledDL.svg + icons/skin/stalledUP.svg icons/skin/tabs.gif icons/skin/toolbox-divider.gif icons/skin/toolbox-divider2.gif - icons/skin/uploading.png icons/slow.png icons/slow_off.png icons/sphere.png icons/sphere2.png icons/url.png + icons/skin/resumed.svg + icons/skin/uploading.svg + icons/skin/completed.svg diff --git a/src/icons/qbt-theme/application-exit.png b/src/icons/qbt-theme/application-exit.png deleted file mode 100644 index f88e000867af4d66bace246544ef4d56eca9a747..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2769 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 E4dJow`v3p{ diff --git a/src/icons/qbt-theme/build-icons/icons/application-exit.svg b/src/icons/qbt-theme/application-exit.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/application-exit.svg rename to src/icons/qbt-theme/application-exit.svg diff --git a/src/icons/qbt-theme/application-rss+xml.png b/src/icons/qbt-theme/application-rss+xml.png deleted file mode 100644 index 7efeb3220d41e43bf648a8688e8f0934dc2ed0fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3564 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 diff --git a/src/icons/qbt-theme/build-icons/icons/application-rss+xml.svg b/src/icons/qbt-theme/application-rss+xml.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/application-rss+xml.svg rename to src/icons/qbt-theme/application-rss+xml.svg diff --git a/src/icons/qbt-theme/application-x-mswinurl.png b/src/icons/qbt-theme/application-x-mswinurl.png deleted file mode 100644 index 95f49c94d5a3e1bb9eb057a6c25d1cf2cdcc61ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4969 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 - - - - diff --git a/src/icons/qbt-theme/build-icons/package.json b/src/icons/qbt-theme/build-icons/package.json deleted file mode 100644 index c4e5b5ca34..0000000000 --- a/src/icons/qbt-theme/build-icons/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "build-icons", - "version": "1.0.0", - "description": "Convert svg icons to png", - "main": "index.js", - "dependencies": {}, - "devDependencies": { - "grunt": "^0.4.5", - "grunt-svg2png": "git+https://git@github.com/bertyhell/grunt-svg2png.git" - }, - "author": "Bert Verhelst", - "license": "ISC" -} diff --git a/src/icons/qbt-theme/build-icons/readme.md b/src/icons/qbt-theme/build-icons/readme.md deleted file mode 100644 index 97c3fd44f9..0000000000 --- a/src/icons/qbt-theme/build-icons/readme.md +++ /dev/null @@ -1,14 +0,0 @@ -Convert SVG icons to PNG ------------------------- - -install npm - -Execute: -``` -npm install -``` - -Convert icons by running: -``` -grunt -``` \ No newline at end of file diff --git a/src/icons/qbt-theme/checked.png b/src/icons/qbt-theme/checked.png deleted file mode 100644 index 79f7c0d00e0a27e1db7565d1196fb07815467d6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1420 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 diff --git a/src/icons/qbt-theme/build-icons/icons/dialog-cancel.svg b/src/icons/qbt-theme/dialog-cancel.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/dialog-cancel.svg rename to src/icons/qbt-theme/dialog-cancel.svg diff --git a/src/icons/qbt-theme/dialog-information.png b/src/icons/qbt-theme/dialog-information.png deleted file mode 100644 index ab4dfa923becad88bd51ec8d5fd4d7aca736ab32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3237 zcmZ9Pc|2768^_PgXiQ>A_9a&+6eeb~WtY8KjBGK=l4UGo$QEOXXtAYS*|VihrHC*{ zg%&$m%I#*2$VE!{ogw%B?wxp*xBwG?Y z#Jo0ePC6{#W{YqfO)H zMw`Ld$L(dedj@i|#*@G|d6q%4A_EX8jAI9!6S0$P7dH=*mv1-!9sxliVG&U=aS6%2 zQol*>laZC%e?VSA@!%mPWfjz6RW&pghu6?PqNA&)Z(wM2)Wp=x+``i87=cJ4TT^U~ z+uGSXIG%8Frn;OwB6Pt zl+?8JD;Za>W&WO(os*lFUvQ(iq_phjt=o6*-mAF(;9=#X$5qu&YM<8CH#9aiKWlmZ zvbC-K)$2EJJ370%dwTo&2i^@14UfDZ{o~`GpT@=~Ca0!9&&+Khbbss)_8cOQGB2sh+yyd4-W@!-dDI!gXJ)>Ae-lM~>HCU(Q)k zZQP)oS!U(wgq&SS4oAmYgjJ>W_es?nkS!+;3h6iuL(?inm-_BruapaQ9V^o3fmTYK z2)=^s_08-ObSYW-IZ`i64qUF2dd_Dy*zC8KZq~DQUv`g6ck!aEV9gV+^Oxt(YZLXx z-n@?F`y=I>yV8l&VKl*DbZJ#y@0&!JM!c?gb*!?cPO&=FyW>dMXqz82EB^yB?9<00 zZVs!7<9w1*GpM;9Pi(-PGM z^BM;H%nYUc_p!nvS-@}_y!Qc8)eurGk~DQ)q#THVc)fOe36)LIE$-xY0GwtKL0ozNY8<4RyFB700X`~Hb~sg<$Nz?!wft#>H}Iu5wdUd)Hw~zd>#2Lr$GK7i z+*CA+R|gIT73~j>D?qX)QnHTU?3yT_+wtn`l2TFOypHwM1NbicmYW@3MY=Wjxt0m{3vguv>HgESn$f1L40zkEGDpk(*{#Xs zcsqZ0*tzPQT?gQVi>mnh7f#C7u@_!E%}%Hn{y1?{u#wFQJ&Aa`MN_cBUW5JJv(j2$VKYd%P~e8HyXue zrL4ziCOBy~t-7>ZDoW0mXUoT&m~EfTl5>*UvDfKE-+$g~=D zI`b1S!>dM9&|on#MddVELYbis!AyIe{lV=>mKCa`er{+vr*ixnXvE~Cw|5xFj- zt;=(fma>=m4#jYcV6LMIKkSyGN?c^*uK>j;Rg*|&FG^J}lBtbSHIHPHQ4g#mnQ$IB zww;${gCZ#C0JTjlQ^mzwRJeS6w7nwwKqe$!oTG!^x@`Z!6v%UNj+aHGyk}Q9{X?G^ zix)igHI;ye&LkYv%#yCw%8d>5CFvqymi80OrUKyQKDXPpxfi~U> zz*zPAGtNv71L0?!B2WX(7S2h8K~&1#(Gs}9TT@=b&Qq`=PFu(+yGunNz64cEL==%qay;mVRdE-6SLmT7or2c3gpx$#R@{j=&vhuvZD{v)Q9Sa#M^O z9X5QqF-EGDrvhn%u9d^GY;7Odcrin;heTyCEUaz1-2pTUZ@U=%3RtqMm^}PDq>rUo zXY9&sthjw8DdLfD%R=}X)aHtEL;tEXA+cNRP`h^#e_mw_m%&?Nv}lEk8f73CiK!3G zR=7|V%acrs{^3|gN|_I7tPeJ9wSBCinOR<6F?P-Di%YLv@p5PNlYs_ntsIJn92w1x zwM-Wr&4*vN?@8h!K!==C1@i3^XiDo!@+<^?zAzi0h)JB!5!^#XNr=kGu}b}ohYrf< z76M2?Od_H}#jgGEqi)Jizs0JE3hYuHO<1lK zMfArvAMkw0zvyhV_a~VVbEH<&G9fQZ#j7Z9`CHtFq~vbg87HgQjjY#+-BOyh(jqmp z`Mk=>y?g?LZ@nh(Kl^wUkv9I&x7$2V=(p4KcK$`PUMdH1J;8EOe+j_@>8;b!tCBp_ zxtp4E4clQE9`A{$?rW&iz4okqbsu-vQ9r-Juu_jogVT)Mz<9IXd!o0ctt&su9WOJ9 z7^*%Lm$Lq{NzLNjY|yEPyY20(6o#g!h6}#Oo3ST}+qC^P>?j8_WP&f&H;zYGh@2SDza5KW80v<^TWy diff --git a/src/icons/qbt-theme/build-icons/icons/dialog-information.svg b/src/icons/qbt-theme/dialog-information.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/dialog-information.svg rename to src/icons/qbt-theme/dialog-information.svg diff --git a/src/icons/qbt-theme/dialog-warning.png b/src/icons/qbt-theme/dialog-warning.png deleted file mode 100644 index b92e0cfd67a32239bf5b2284d8102f97d306ced7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2891 zcmYjSc{tSj7aoKx8C@p(P~=*Q!OxAl!=RC67CVtLLJ1WK*9h50$Tq7`LR`{9RJN$; z>L$!$lw>I(Yt}5K{J!6z`!s)?IiK^s=RNN^&pgjualjqfA+9J6fk1ZH+8lO*Km>qP z0J2>O_zJ4>aDhMsyB#ntXyCcA0ojO)tE_Zwi8JrW3*c3{4&5+syXxAJhhe9qc@)<- z1-O56Y&!B>Sy^~4&7PO<`kL$jpj|mOY?>oC8_T2Eb>umAl5s4$JtxPpn~LYH`Sqwj$=`Xo=w4WXc#Vq zkCL%$Djt}{pIMD$^v0jHWsJYbrlns8ZEmr( z<1btAWjAMS8u)36zXIO_I0&?{sSG;bS|6zJ*W6s6zcR@A=?c6aNZ2w4o^gx+>%}%t zv}up8wt0lPh8*Dc4w(yg!Z||(1ckN*(&&(>E|Q`k(P12TV*49{Lk$hO)4ovBDLI9ddL=F6 zYGzh;PA-{3r8DxbXv)TMb|+lsx4922w^xA&G4TDUrTrQzSs17!*cr%NHs8 z_GDEKI2G_g8SV3Wa_>T6qfUD_Zenfvq)PHc7CnX-bj46=*yIN>d_c`xES0CFw)+lZ zPtmlp<$xa*CNN-IW@iy;o3qPWT7wc%d|SGPEGsKqXe@@%B};C1zN2NF;~l4ebL!cr zyn*lf?2g#Mr~RF+k*oB}SR38C?)4+nKAxQ{1()3+!G&XzzWz2c64s_A9|TL2Genm{ zhpZ0%U3Sl|mt;CL9;6|+Tu6v_Mx6VgA%y85U3?=yZkVB)7f{q|*c*|R(1-|8M=SYw zSj(Xc;nRKg3M;Kub4S{HRUcjwel_Xi;+Gn#kl9)$(l()iX;&?8UA63g_SieY0`1tg z|Do)1t&u>a4^CUA2HqBh&&zg)2Wy{7h+tA2^ksN*DSN3HkNuK)-;>3Z(poc1FqY~a zjBjLHhE_c66N8eD@a4z~x5*7pVYnfT`?POxV>pnS z`AvK#^t)Q!Ja6ti79_P)aZ!J7zPU5tn=zoDWT&A4v4&Fe?H+2E<8;{+WwQ+spQUC|6!HjmBn zd3YHf0Mj5%Og#n?BaJUh#qY2J@w^dymCXLA>UYWxZxlhz24 zbgFD7Rgg*(Ew2C7PGo4>zzx_DqezUAMxo@AUTGt#UfdR%sKOp#)>d0XlV7*Lfa?7jpyvHN(fEV1fkAI?pRji6(qO-x({}vjJ@Pu>~ zJ#IxQKbMhuzWzi^ubmN{S|WGqWu2&dO{)&}&(!%LiH)W;|6-N#H3B^2jtTD0nrLYI z+XYPRuv&fDETOWC<_^dOYV@olZZO^ij>35B2$2jTuvWW{uF0>ZW|k`xUesnkTWXx*&Uj>4W4MCic@8m>H;Xk;JNtx@&|o zweWo3>p&9l(oI?Qxn(Q^eHZqke&+(S$|CrBY3AfA!BCorc1q95Pz{g^lh_ww-3GlN zS--Mxxf%Tr^n&%HVUycBu?&d@*bD8*)K$XZSIFa;e9_s8Rl;OFCVH`@^id|n1SdK_ zta@OD`SO*fxn?VT32+7jY@vK9x#1O1a+QB&DxWe+FipY3fJ z4?x)yM1;~%hJi=b(M-v!Ep)b$e9EHasdcj-=K3EV9V}QJ)gphcMoQl6V=g0_v>%f` z?0A5boV9ueysUzu%=}IOoZa`1Ik)RzFFYmk>I@+&ed;Zc(SfXIKR_W$tst6q2T`Xy zcb3T%lf>Mw$s22%?A>L!NCWKdY*- z#)u64-y?SPJR(+=x5LOZV#;EIM57rP1^fWBXijL} zto}l`lTE-#*R1ibv-gx0>&`<**-8=zekZlx-pBK-uVq?(d3j5H*BJ-BWVz>Fqg+#o z9!K(#7yCUN;WO1f2Syyrh2QCs%&PVGG>O?0ywIPQjw(WvhR>xOYH6pNH`8z{1;HcP)Jq F{tpMImMH)L diff --git a/src/icons/qbt-theme/build-icons/icons/dialog-warning.svg b/src/icons/qbt-theme/dialog-warning.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/dialog-warning.svg rename to src/icons/qbt-theme/dialog-warning.svg diff --git a/src/icons/qbt-theme/document-edit-verify.png b/src/icons/qbt-theme/document-edit-verify.png deleted file mode 100644 index 515fe69552aa6f79708d282e27a57810cdfe6209..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3112 zcmZ`*dpwi-AAh!C4vn1>+QBB0a?i|=%r*C2SWyy{GAeANlG@yrjyiJ6C0WU(PRi-- zKB+k3q!Hanjt;^$_gm~d&p4Mqe!pk0*Yo{;-rx88{ds@(dY;$oIYaT@j#9uV004k; zb9JHt01Vv10C@zsgx~h_1ps(H#naarETN0Tq0{Mhb{zAA2RG9>uC7Py_Hu~yD05Ga zaRAGX9%k(wP1t?JoPNxN9I@5oICx}1Id1OB+)6)UMP*rf9krmd&8d+PjT(a|GeM>m zjYXid@U%#43LE5G(xNRWOguf>ipI30M1V&YK9P7Ti%5>L^kEaIQ5Iyjl@F6hjRtWd z1q4|TNRfgxwk3s0@QGf*X;B0!C}$EuoC@M>3mPZ{TS##Vh_fJ^!nUA-Le?@)pfZU* z;GStgV-u-NOP?qLm=J6s1udy8u!L}mGz_ScBG4Ti5X=mcp*vHm`nv>=z($Y{Q%Zx# z5KW3h5~+3>1Zg07*=HFC_tGwqgVaZABIQ8kN&v_W^pr}VB+G74q-AqycgPCLwrurp zDo86$2(?~``u8}?_=?XzEtV5XIm^@iI}79wHC^$63|IOtPrWk5KUV)uyZpC6@|9UY z6KMb6c>f+rZCM>I-YMY2*~6xJ`v5RFLPk~&DgT{<;wqGqGWz?~YgE>%s;RHTXlQC- zwb$$DZqVDPziG39p^>qPso54h!IEfYZL`(Zj%4rP=;Z9O-PPU0)61JorTO^MckJA? zJ77=X-k{+92SN^oh8;c{#bm`CKM@$DJ9o=}y?6h?qsLDwDyypN`1Ma4p1){p`mOn8OY85i+63(# zZ@S*Td;hV!=TqAFT=jIo_EiNtW+WiCo2Dg*m;uKB=|PsPyN3tiUoG|yOVsV_s16BEtU6Hlhj zOg$dit~@ZYIR0nPs~N?J+K-JKaqLx=Xoe-MD2VXDE~-|={MlL}N^qEw{HUY1H1^8; zT1(9*rqiC2!Q1d|l5;wD7}4rshkHYbmTTNUwl`8=FX*y~{MWSaP{JQs9fy1TB*B|Ddem-Quq6tvh0iIPjqGOUvh-R}GBBR@{JIOC1cq zBXDm8u5Uk3!M`uwJ-a2fb8*Q;@tXopZO|m)?%BtWX{vS=dR+xzU$UdP^~PBjrJa)6 z%nMks_b;C>e)Q7xY|6nVSA#KTH?KLJO?me`=~QLg0?2lj+ ziojlcGw0j%2Y47Q_G8!>X|zlcxB)yPM4vG*c8hbM+i@dI+UY{GtCCqMV5}(Ng@{-8@qi46SQZ?SS5PZ&YXnxxP(U3d^Q&Kf(lm0X^ z%Vsh{uOP(1_vU(1pv|7C!@s3gwKZ%U6mCd6jqXARVY{D&PiX7cxLS^_PV1qggVuH9 zTN4dwYYWp&w%~Hc=Sq>;k;%q^d1=9$mIQtC;lCHS*pN2lJMRpBa&LHO#7-7nB+}>x zD)z8D=Fll7qjc+&s4a$do(8oVu%jwE-(PEGtK`eAd+M>*>hv9Lm}JtJe?!T7$k1h< z!|tI_n{VQiBDimx+oZPc<_CG+OSb+exGvWI$4$`SNYZH^85{7x36sQoOb&I{gl zyT+qIsR$ODiwLh`l+rOc?}h-s4~`AqMX>95L+-;xeD!TSX(Q@<{d+S^SeD#uZVJ=S zW_!bgI|45#*Xn%F@GHafk@#xZZhyQH6~oI&@hP{+D|RS?-3lF4Y7m&?S2=;QOotx366J$&x+V5!D?M1P#e_7AH!o3@5reld5N>zO#D4V z^+~xVVqc}5$>+zlJ%`^u(nW9|fqq{A#AT%&cA2Qe9$@^m8Ncg|$!KZ!9J6)em&+0A}ycY4@OY_Iep z7%-f-am&nqm275=z!lyW_P=vn`;HWec{mlVZ2pxVvZ+v$!&P{LmsCP2La diff --git a/src/icons/qbt-theme/build-icons/icons/document-edit-verify.svg b/src/icons/qbt-theme/document-edit-verify.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/document-edit-verify.svg rename to src/icons/qbt-theme/document-edit-verify.svg diff --git a/src/icons/qbt-theme/document-edit.png b/src/icons/qbt-theme/document-edit.png deleted file mode 100644 index b4eb6fcac22eefdf47657a8e79ca7cfaee33ab2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2097 zcmb7EeN+=y9(^-OAOxtP5J1XD6hs7;K!GHJltFO?3*?Iwt5j1_aQ%XWC{{5UP*7G- z6j*3kBqCb2f~H^vMPaC0L8~m{)&PRZYPE<^*`D&TV936Sy4&`g{bS$B$^7p9-QRup z&CHnsVZtg~h6@7#U>h3~Ed~IAB?9Oac-dCJCJ_RIFfMT=gyd4IrBZ2Rq&he?)mN&H ziP^!I%7f$7!O|>_ARX4B!ac!pie=IrOGTNy_?=-1ySSp=JV82Fni(ckLIF>_D^#dh zDpo)yRFV+_WfCP>IiVZBtM;ELs35fmu+A~{c(2}k(iOrA&)DpEqo6GI;b zPn5}(C_=?boHm78SLB-!GfB$GDe?$p7}CwmKofHkvin~iI+!(Ni#&q4 zMc$(Sq$PvB$w0cj@iFHy2QWLBHRk(3?)WPIs~yd@(77bJ)EhqEYNa?q0uYo!rCC^7 zG3GJfws&ATI=Q&A7kGLt^7ird^AF$zhVb}dQOj4v#Ky%Zh{TelH6N}`{%C`2)8^Ez z+jq*9dp_Blyem|iww?1g)mgA?*a1y#Ti^LK^~qDa?%kut z(M+AHt;1BlE1|p6^VHPK?ic%X*`*szFBcSCx+~chE`DAezEG5vHhbdYkEVGAZQn*b zzK8UA6;_!-%H{+o8Jh(kEJDYRXfFj7@eFl6_bXB21G@)k=U-b0jkD91!}6T`J{E?z z?tig=%H9#f!=8M-cMK$dWa3HidBUucwtXEA1`0oEUjoZOY2h43vq2;9!2JnJw)HsD z_5Z+))^Tgve)!%%w6Wa&0-_y<-QE3KFNfISb!f><$k@s(7Z5}XQ`uK7TU$!SWXPzl z$bU7$t_70^fCnLvy?bk7UPb?OZtzY z$sj$a(rwYK2xk~L<2(9Q4l;Dw`epDpO(rdY;dBE>+op_Uc-i1+^WyR!SLGZ;gtA@z zs=@qHWYG5yLj{kFhiZG;vSKMMl-|bjDrBa_VtRT>whe7q;7p92_><9DQ%xDK6>aC$ zZvOnp&&Ou_o77JW&hx>OtX4X)T0ghovQBD;r>%TT*44UUy%oUzX!3Lb6)*Ir)oeb2 zdEpnX&UR9lQ(OzF+Uu?AI76HaFFFoXKRwq)w75IUy0^IE*B%;unGVF*;z+bl{oz`k zBEpBTbUF>{C!bm76oZ{3$DKhHCt^m#_QETtS5QG#PrC!|q$(3XFGyW1mT!&F~HI?xUIKU8n4$qZ!*!Q9L>&id6at z<-mbZ4V}?hCAt8b*3^KqEHGqL-AY_2qrrm1&S*bZLk>_86nBh@jKYBi?GZ59pbq?O zPo)E2jWH>jj=BOCuF3^=#2vo@jv@#L9$>}_vZIUXOhjAF#;Am<26)Imk=&yD*Du4* zNfQB5XvM~Z5Ne<|4vte(y%yr&29-%v0MywY11Tt77WXR+Y_cyA)!PxO!Mf1j>wl;c zb9SI871R)^2!ew54FlzV9t=7Y(9tlMy5emNv=Mn#Yz!Ezk}IC>g$H8BgIPDIcw{Au zgqJnw0n@~3fZ$$%{Gp{R1IVCW+(3%~uE?0q?GY%ZYV{M%@8IF%zt72^Z1%%aG|%qp zj{+3!(LV*gxRDFKuV-NGG+bvLlFIi4Y~0v1W720-qFtB0C!aeWIq!xD4VYnYSQ zlQ%g+DSb~_j*TqqePF*)v?A@g)z;4JvklLVf=9gg3En~Z@2=#fs@8>P2;p}UL2f5` m$peZ8a{IXVCY;DmCtMkF{}&RM{*z}(5W6xV`uuWP?!N)fn=Z%z diff --git a/src/icons/qbt-theme/build-icons/icons/document-edit.svg b/src/icons/qbt-theme/document-edit.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/document-edit.svg rename to src/icons/qbt-theme/document-edit.svg diff --git a/src/icons/qbt-theme/document-encrypt.png b/src/icons/qbt-theme/document-encrypt.png deleted file mode 100644 index 39ac5c86fc9f88060fb9b5c08980dc522e7b091d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2339 zcmchXXIxWh7RE2VB%#dG41$yy0Vy&%0R15Gg4{Mbshc!eGa;pn$OVhVp4Y?5E9#-1mLXbN*{P{=+g zO|&Ke04QI)S0Df=Kt}~YT?u+5UI+^Y0L3&4G1wcrE-nI#3`TuD^(Mo8pfp}uPaS39 z$Ew_WPEiL+iK3In#uAzxQqO^2$ztht|&HePGG z&fLQC`ybX@S=-p!**k1>{BhGy7$@f~+uX4@4^J=e?LNK)B8luz2?(TygocGj?ud$x ziQN?!|Lg9AJ&Aki`wtvUPDwqKb~yb=#y=U%tn8!5j^~`rKUHwLkj3V3i%ZJND=K;X z>N7QG&()rpi z{~D7$d;a2I<9|=SeD&t-yZ2KcK7Ic8^vsv9vvc#`7AmjGhyb9HwVa^&UU*Y&z$rxa~0mst@Lpl zpflycaIj8Jj9cwpw0?dbLi70zUVxsn9Xk8FP_J}8ujjn%I9kCwGi#>|oq9@E)WMTw zAylNiwg-v=)FF44__pgeVQWQY>F~gN#I-(l<#1o?m#S&oW2GOS8Jl4i_gIz8qO~^W zB5wgf)6UtC|7Q1hH{iM_tfttVdm~1aOM)L|W1sXDsOJDJ7tLu+ZvE~W2@iF^HWYV3 zFaP{IpXSQJ_IJe#Z4SBnlR%6Tk%7dym^dLSQxOc0@>y{R!g0dk=*On!5Ma(QH-ye_ z;WwUN_x!0}D}mW@QvF21Pl?J#(>msoinwEdjl)smzRFpJ^(khcCg}dHLpP#R|K{|R znKY$tEp6UMr+d)`e^`67_1yY=hDOlm(fddpsx~{>HqByFxg#kjuQpbVn7om21$gOB zJ9l7wCv%@J5FL3iDCl6B_CkM%Ei*}VA?ZH7rM73mBzH~wmYcKQ?(#+JD;E4xX`!ImH9k*SP_XPpwDqWC3V`S?eq!UZhgeBQ zb7QDQ*U$S8Z551VPNE$zBPnKB537+TL<nS8Pf%DY4rI|eE891|38pHKd6-;xwT0GBr+*8#A0iguH%=Y zY~zxzCN=)7Kqapu%D3uiRv&SZ8!%lv9Lu#2cc&m~&~*v~+$W8W8zzsH@_Z%|M7vdf zYslqPn8o3dg^CgBt+|{MCrY0Ff_;~Hd_2lp`+LK;VoqXl&8WWfoe#cF~)t5UEbH)aYB!Wwl03js(Tl1qTAI_?Dvu6@gPe z-M^cm^j+Gr!|IFm%+`TbPW)eNPt>jVRhZ8D==)}5ZESs1A42RL+go(P=3))di%p~d zl}azJ0j#hIdaeeZ#0<6`PZP9??cHmJ*Ock4Wu8--1YDR}y#Mh5BmI~Hlc@O=aJWS2TJ7x^iQwIn!z@3=+9p-VmNP}!7fpv$*GcLQZUd1Ue{;6-O zWf|^@QL^RP#9cbv*HnjZ?yQYT~q14k--bu^fAM*O=A;a zL#*gXgPSe&_fK@sx<4@QXH7ZhH-Fl9mGZ~WJ@&j;7mK9ft%dc`gn&Qy;z&`pxW+Yz zhD!$;ie_#&)A%HMW&7xcxW%`^OlT2xCC4i@lC3`KxHug_d~-!|Mh3hdQz=LAC?rNP QG8(@5dXv4HJZM?}0dT%Hq5uE@ diff --git a/src/icons/qbt-theme/build-icons/icons/document-encrypt.svg b/src/icons/qbt-theme/document-encrypt.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/document-encrypt.svg rename to src/icons/qbt-theme/document-encrypt.svg diff --git a/src/icons/qbt-theme/document-import.png b/src/icons/qbt-theme/document-import.png deleted file mode 100644 index a136848322a6f5b93ea9780bb368cb19f434b026..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2016 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 diff --git a/src/icons/qbt-theme/build-icons/icons/document-properties.svg b/src/icons/qbt-theme/document-properties.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/document-properties.svg rename to src/icons/qbt-theme/document-properties.svg diff --git a/src/icons/qbt-theme/document-save.png b/src/icons/qbt-theme/document-save.png deleted file mode 100644 index b88902a7ac886282a5b9ccc703eebac401f626c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1804 zcmbVKYdDl?7=CArL+p$WlQTP8ED5<{4kAWa6yr0Rm5LRGoSKu<)iNJllr}lECC41H zosG$n>Q0-xf9j()BylQ zPY+i%0619UfSM9~L{)Fu3>zupwb>1}*iR(la5zp*BAc)YJZY%ZN0XUmDR zWAo_MF3nakW7w#8A2`u20&KA%XmcSN{;6nLMOs*hc zg`AHWeFQNY*2=Yt8YY1ousqmEF8Sz!wesnLFP2$>DDuD)sy;8rYPf1aE;ss=_VY-= z{}@=2M6Oy0tO%ocDS2{vU>FkfQhYb;b>zVatk)j!zpfOrS$+VAS0X5@sH!be*Z7J^ z(ppwr&dw z-nlD0A|{p_pOE-tN@`mA{>+1ivJPkGn=Ao z{o35}`<1q9eutQrXMb(=)Sk@8+p! z-Z}sX7M`xon-hbiH*1MtF#y&VtUVlp>$kcZJhIX(`YU+1Q$(Wt3IlMUDQmh@N^QR~ zFTS~J*l};gfeP!xCsHld%+1rB+lIDP4}_#Pnro5C%cTRzlEDY7&1kNK+OicdO4md_ zw$G?G4J&R+=yCYq!=2hYX*|=uqb|AmQbLN6?%9iWU9`WOl1g1v3f~o>%zY8Mba#Be&MI)$Ak06RbrOt$=Avbm z=;ZKyPE0*Gof;UJt)XcZF)u}WA?*z-Q0H0p^lAUWr6C#h5V97 zk2tg@gV8A7XK31YO@`Ytn@6<0xPF*~R!l{owm%XL%w!>PUh>N##qD{U;}%o#H=%AKTQlcg(bP-?7}5(B>%;rAikQF{!H~>Qqrqb=jy9 zxE|oV%Lo*wkdoJrRIN04OUlbP7x6l}yi9xyM|1j_LwZw(TqKpoN!7-8@!8+zJyX|n zX;v!8FrLpgCr$I!<|MI(WE{ZZz;8PA4LRt3b^f^Y44PdaAvgPHhKsXij|NSM7P2yQ W(t_NEuA5t8y{8+?^}>eWw0{9DBBG-J diff --git a/src/icons/qbt-theme/build-icons/icons/document-save.svg b/src/icons/qbt-theme/document-save.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/document-save.svg rename to src/icons/qbt-theme/document-save.svg diff --git a/src/icons/qbt-theme/download.png b/src/icons/qbt-theme/download.png deleted file mode 100644 index 000e2d7304d8aa7ab010a29a4873af0ff6a13563..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2045 zcmbtU2~bm46n#ku#1I4&5m^LLNqG&&|BaL3-dP zdU#Vj06@>z$BPL73Wg|v!@ysA%0q(zKrf;D2YbUM@`yxiHrw4@Pd_ zv%kn;GvA#Zy*4n>nf>{Czhsys(UYD1d9DmTOp+N%EJrXC7f@h^4jUpZDuV~N$P58u2y2+Lyc#1V zJcX=2s|HASmW0g_9zF|ykh5?J8>*REDXni z9@0{qzZVmi_VmsJAdJui=}1d(o3?-HP>$3tgWlReYfGKd-oqS%9|cGKWb@v+}`n| zv+HTMqNlg7f8g1#&wqO{^zzm4>(RI46O&W#rj;{TC*30eX!ZDdc?2hK8G@V)fdK$C z!vd`uJ>mNOrxWq)#53<8jew!MsS* zMeEFLlGfPSEsD`&Mkg_S7Z~om6I~uDd!$ficA3r^U4OE5uTyFHZ^`^St z@q8EiA+P%75#i$ex&ToYA?!-0bg68pk$3g5KXAXDf7zyPS@W}1QD(UI5JPdFmK8wZ zXaH>>2LA)D=xe!95!Oh81|LQZj^tgv7B^m1%aMhK?AAVfQ~s%W;UwNI#ZqPxl8oC@ z#vwex#idl4B$-WzkX5+?bJW}Wq83Fpf23Pt3!R#b|7Bss-RToICdX6(9Idc%%&t&^ zpTo_m!tKU)ByDa=>E1&-(jCxJtaBi0l#eedW&!1C^x&^XH1}`7lqsH;1{6_}Qw260qdu%E4OB>?q4$&ktzp)P25yx{o zGRC&6h6+`FEQU$eaFNusW(l5Qq<664SnUa?d6EUJN|$Y%)>07t^-j(X>nj|iw6iw5 zS60d{ws*A2!%grnUft;Q?QGT^8W0Loh5ODFStuZBba7T={rA|J7LlRpJ@@kF@osYr zL>J#Jj_diZLiAD#VvD;i8!}vm%Qk^1DXSi(=a~|3RnXUdsf8FGC zns=_;PmamK=A5fE7oR%h7AUfcTRYzo{}g?ISY6hNUOyuq*%L9JfNhviI`vX%#?#md zTnJ+)Qd4jo-ZgcTjy*sHbWoX6uVjJo(ve zLl?SV2js7d)lb_SgJ)uz0*bqQ#>xtQ1h-Iw`CkRJ*hHzIT%vds2qq8OQm#MwlsG!S z))!-7AdZg%6tNkkr_fHoRHN{hEWNV6{<*iNr}o|JDg{u6g<#+Q5c9mBE5}P~jv1O- z@ns(>Y9iB%rzF)*c57&7+rLY)5Xf6Of^pdo;3yLnbh?QnvU9U>gyhlQ5tg@B<4Jc1 zuqMIS`%5yPDeYh7FD^NRBdin@G%bIFt};kNW!BmVF5LhYUW!W3?uGk&wurBLDT+Ls z&4N4ZiO{C8WqWmQJt&3vdr?glxb@b8&ajR8o)O~U^sO%mgK>q%(!%2=Kv$$2Bk8AQ zJ>7;Hey-)EO)K3#w$$;X;@H;>t&2B(vNf`YIdS%kM*r%j-{9*jAa<_x{?!zT# zuS^9knt7+A_W(Qf=G({0-8%D2L3RlM_6q-s77xks3@wMcuMAQ;qCVIc*xf>I&FgL- gN!@tOeC}T>0VJlc+SX~N4R#sdHVc+E_WYykiu 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 LTN*VQK6v&&F4U&| diff --git a/src/icons/qbt-theme/build-icons/icons/edit-clear-history.svg b/src/icons/qbt-theme/edit-clear-history.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/edit-clear-history.svg rename to src/icons/qbt-theme/edit-clear-history.svg diff --git a/src/icons/qbt-theme/edit-clear.png b/src/icons/qbt-theme/edit-clear.png deleted file mode 100644 index a04529bcdd01e79cc33b3beb33f352cec2e067c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3652 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 C&agKC diff --git a/src/icons/qbt-theme/build-icons/icons/edit-clear.svg b/src/icons/qbt-theme/edit-clear.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/edit-clear.svg rename to src/icons/qbt-theme/edit-clear.svg diff --git a/src/icons/qbt-theme/edit-copy.png b/src/icons/qbt-theme/edit-copy.png deleted file mode 100644 index f78e267e35d3065a2dfbb3213b4dc3ede91511dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1861 zcma)+c~DbV6vppMfFLxf6-3ztSHwmZ2}wXC5wSoCA$cJct4N9#To6JMkTQ^D5ErKI zaY3q()(wSPw<-vQM6F5%MMVKcHW?5_gBHUQLVDke&N!X^(KmPAJ>R*%^PQ8IH!q*Z z4I|q)*#H2@5#gaI00;~bU`>SEhO*cgDBkfnF-xJuE``EmG6{u377Gjf5);G2H?rat zejH4Ct(3w$OSnFeo9-vv6cm}s6sGy}GW|Fbm=6+e4B$%{Q7L|WF$8GQ637IgQW`1_ zqlF3V>^P#PbiOLu}i9agE zGmw|i1u!F}^QHbg2@{plc``aG@#o7JC@hgM1yTkyx#@6;T^5@daA$#t6BjG41$d(8Em_a$|{kB{#H z8l4%iFesQ6vgE6XNKRBVk1r5@6T2c#l&~f-X>D?{Y3sAL&aUpB z-WM-l^}l}e_TAun{m}5psA0@FE(YUK09eFDgf5QBT-C4fg|D(T!KXgNv@5UUS&9|@ z0)qk1%8cfi)f2a-Wk=c*2<~~-$RvBjT8)NSFMc2b*94xv6TW7@WDX4tKA_dLp1No# zzZ*Q1le5{Bnv~I=Jo39*H)UrstBs~}aosZ3`m$+%|C2*miecx}TeS%}w#K{O1Bt?9#>j4=qT#)ACsGW>8;~D z#Hv=y-S$K`O*4{k=lV-Gs&6o8cs?*{1nTtf-Wv$wMaSi-pzVqNo@i9y>Ymb4?CN7Y zO<`vk*F|v@jYx*6)D3BHomF*(f=EWk3FXV~md&wO8uLl}7h05u)BkpJ_nza@;b2^* zyct7`lW2x`;MV*ku!Bv3pUhhy*%36 zw_26B8{+CYS55kFX_~kTZ4*@4ip1$oY8AEVV#~>P4N|?QzDwJgTq+M@XUFn{+U=JM zPWKw#f;zt&br<3Rc<2q3eY?FtJGM^&nn7D28npyI#`_i>25cvQ0yzRWH2|Ds6@qMR z|5%3MVRlO0r)3ZyUrQJ;CV&hdBcIefpz7Pr)KmqZWOV_@`PgIGrK%qz6&RwJny7u` zb5ySWDT$;RXP#W3Kzd9wNGo1@vu6i14^b6JV6E0^=M_-VEsB>KEt@0t&dmv9mL)S^ z{Sp6tkX0u8vTcuZF;b*@7VJ__TSdG?xzktTcHip=HQ`+jv4qhXjo5eGvu7jN673f& z-`eF7%X}^%H#tp_K8HP(gt`B4>G=(6b?;+ diff --git a/src/icons/qbt-theme/build-icons/icons/edit-copy.svg b/src/icons/qbt-theme/edit-copy.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/edit-copy.svg rename to src/icons/qbt-theme/edit-copy.svg diff --git a/src/icons/qbt-theme/edit-cut.png b/src/icons/qbt-theme/edit-cut.png deleted file mode 100644 index 61eaf4c15dfe78c262a20bb152f1b1c635d2c066..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7349 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 HWEt^4EvYk| diff --git a/src/icons/qbt-theme/build-icons/icons/edit-cut.svg b/src/icons/qbt-theme/edit-cut.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/edit-cut.svg rename to src/icons/qbt-theme/edit-cut.svg diff --git a/src/icons/qbt-theme/edit-delete.png b/src/icons/qbt-theme/edit-delete.png deleted file mode 100644 index f88e000867af4d66bace246544ef4d56eca9a747..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2769 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 E4dJow`v3p{ diff --git a/src/icons/qbt-theme/build-icons/icons/edit-delete.svg b/src/icons/qbt-theme/edit-delete.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/edit-delete.svg rename to src/icons/qbt-theme/edit-delete.svg diff --git a/src/icons/qbt-theme/edit-find-user.png b/src/icons/qbt-theme/edit-find-user.png deleted file mode 100644 index 378a98fcba8d713fca0920df4b8b8e5c4a6ee382..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7826 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 F{SU+Bz$e5N$OVD=`v3p`+uMUk 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 diff --git a/src/icons/qbt-theme/build-icons/icons/edit-rename.svg b/src/icons/qbt-theme/edit-rename.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/edit-rename.svg rename to src/icons/qbt-theme/edit-rename.svg diff --git a/src/icons/qbt-theme/folder-documents.png b/src/icons/qbt-theme/folder-documents.png deleted file mode 100644 index 74efc06456b53d6170fbf3c56ce3b54a968430c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2762 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 HKFR+9z>tAo diff --git a/src/icons/qbt-theme/build-icons/icons/folder-new.svg b/src/icons/qbt-theme/folder-new.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/folder-new.svg rename to src/icons/qbt-theme/folder-new.svg diff --git a/src/icons/qbt-theme/folder-remote.png b/src/icons/qbt-theme/folder-remote.png deleted file mode 100644 index 75a00291c8d42ddfb4f8b35d1f6340b4d52015a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10738 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 d4A*peUy*TPY0-{2x!kC`bSR diff --git a/src/icons/qbt-theme/build-icons/icons/folder-remote.svg b/src/icons/qbt-theme/folder-remote.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/folder-remote.svg rename to src/icons/qbt-theme/folder-remote.svg diff --git a/src/icons/qbt-theme/gear.png b/src/icons/qbt-theme/gear.png deleted file mode 100644 index a4459360b81b3dd5f7fb6e3a01ec6c9f31496f07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3037 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 QmdKI;Vst049f*2mk;8 diff --git a/src/icons/qbt-theme/build-icons/icons/go-bottom.svg b/src/icons/qbt-theme/go-bottom.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/go-bottom.svg rename to src/icons/qbt-theme/go-bottom.svg diff --git a/src/icons/qbt-theme/go-down.png b/src/icons/qbt-theme/go-down.png deleted file mode 100644 index cdce86687664aefc8a091f6f961e15d8130c17cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 755 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5FphX;1l8sr2qf_Z*N}@BI7|M z5ZH%inMLOshn54`HleweLB%FP1?EAeCZVO~0r_U3#iqdpCV|Bk{)OhjC1!zzKxLM} zMHYdjKylN+60@LU^PnOiX%<*)9#~`^2xJt2MT&q7GoTbu9I6H=4pal-7JoT+Fc9b< zy^%)7I2lq7(?2l~tU&r{`p6OaW%bNcj5&s1@ z{8LW&>we%@f5TUKgoMTam%qXrOa11cX%B9wU(WC!i@9hL=G<%KElVdf889$A2u$Rv z(0w7C_5Z(Pf3e8IrHyC#(>xE^?>$i0R{ywP^g+HDv4~%U;rpQ0JR&Sw9=ykCxM zhp$G#!um>{JB^?JKC^woweHjX`N97W+1&qsXVL1)@Yvr%wY_Hq_k)rx2H0cLI8D51VRk-9 N#?#f$Wt~$(69A}~G%f%D diff --git a/src/icons/qbt-theme/build-icons/icons/go-down.svg b/src/icons/qbt-theme/go-down.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/go-down.svg rename to src/icons/qbt-theme/go-down.svg diff --git a/src/icons/qbt-theme/go-top.png b/src/icons/qbt-theme/go-top.png deleted file mode 100644 index a6cbbbba03e952415502289b1382c7cc96c5b6ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1034 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fm#&z$e5N$YrRn|NsBLy*-FD zPD|4Y1u^tuih-n+U#VGiu5oC&MQEXEK!veS5m3-Hw8S{D04M?xHxDiW3YrHLn*fDmjfIdfS%~2fi;&C*Dn>F5WFrvONPk)b42Q6i zAirP+CMFgZRyHnfZeBiqAz={_2}x-=6+HuEQ(H%O|Io;o^o;D>(yE&J#+J7J2@|JG zoi=^O>^TdUEM2>P!^Um94xTuD=G=vgm+m}x^6cfCx9{G6{PFYm-+wPdS3PH7V2bl} zaSW-5dvm~$lR-g%;lOzXj%@`cB^BzcS%27!>V_8dhma9i~UhoUrmd<|NERr z%>NUio*RC*8Z_9e9>3P~YkAychLUB;3}If={`N86@MA8JV%{*D?ST?ofumEV7V|2^wKZ~mRVUyJ@;et2H(Jli&_rBj|S-FIx~!pY~;t@C&P_THHr{abLu zH|2!4?gwu5H*A$>%(iE`R>!jDFGmDeLg7U@*M;{Y3+`(=><@0JTh8#;kMY-BrZ3j4 zFU+~O_?-$bzby8Jo8?6~E>$?S110jsGGwQ(xa$M43dIdCf9=-4Fn@u4P(p=?WBrl? z{VabcGBr=;{N>EL>q5RDhI?kSM!7HDy?Y)$zo1xv>`9=6!>#@U-!&SVCneXXC;xix zJuae_x2LibGt!2Pgg&ebxsLQ08%ltm;e9( diff --git a/src/icons/qbt-theme/build-icons/icons/go-top.svg b/src/icons/qbt-theme/go-top.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/go-top.svg rename to src/icons/qbt-theme/go-top.svg diff --git a/src/icons/qbt-theme/go-up.png b/src/icons/qbt-theme/go-up.png deleted file mode 100644 index 37827553eeb939c5686ae0b64dee129453a16cfd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1329 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Flq^fKP}kkozADjMLJzLhC&| za_!^mEkX;8ed>Y2dNIX7(mpiH%CFQcI@dU~T;D(6#=8Qjz%-!3*ry06YZIDl8CY!Y zn`atYVjNfiR0)(d3oJA7F9NE!3@SGF&o>J#HVG=Q3Mc_enFp1c1{9fumRbfCnFoNR zOoIzd0*fvD3(bQ|%mNEd{Y!wxS_T(c1eTfyz+?k}vc*7T3ep8qW)@gv9#~`sGmf zOJ1A&J^mx~_oU7HGv)_>x&Cqa`Ov1nD<8{0Pd)eV(VmJo|MH98D6MT&;5lS4ZDs=J z!Mm|$cNpXpcCb2eynFX9dPVT&HL{G8=9PT^fA7KSRMl7PcE8rVyYJv6zt`yZ%e}|1 z{d-_l_jGM^n*H9=lW&$^*W>-Q*Ymiq!Vt-JW*U#iO6ZGma_cTFU2%R76;TtEG0 z`D-iT-`q(aGgn*9{96*49rIr(=+&aIH2c^q5?AG2Pt6SnsxeL$JJIdbd0ET(m-xaH znM=>qS*=dAe=AfB>x5O{X{BL8kDO_pu z{IYJ-H}jj@%eqp(T`u!jUsoPtKhJ{tO_zRhsnocCo97H}{KurNp{b~HQv4_WqM;r64fk=64qXg?0eNM}HS Z0tShdlQ*B^Y5D<@^>p=fS?83{1OTh0L^l8c diff --git a/src/icons/qbt-theme/build-icons/icons/go-up.svg b/src/icons/qbt-theme/go-up.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/go-up.svg rename to src/icons/qbt-theme/go-up.svg diff --git a/src/icons/qbt-theme/help-about.png b/src/icons/qbt-theme/help-about.png deleted file mode 100644 index ab4dfa923becad88bd51ec8d5fd4d7aca736ab32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3237 zcmZ9Pc|2768^_PgXiQ>A_9a&+6eeb~WtY8KjBGK=l4UGo$QEOXXtAYS*|VihrHC*{ zg%&$m%I#*2$VE!{ogw%B?wxp*xBwG?Y z#Jo0ePC6{#W{YqfO)H zMw`Ld$L(dedj@i|#*@G|d6q%4A_EX8jAI9!6S0$P7dH=*mv1-!9sxliVG&U=aS6%2 zQol*>laZC%e?VSA@!%mPWfjz6RW&pghu6?PqNA&)Z(wM2)Wp=x+``i87=cJ4TT^U~ z+uGSXIG%8Frn;OwB6Pt zl+?8JD;Za>W&WO(os*lFUvQ(iq_phjt=o6*-mAF(;9=#X$5qu&YM<8CH#9aiKWlmZ zvbC-K)$2EJJ370%dwTo&2i^@14UfDZ{o~`GpT@=~Ca0!9&&+Khbbss)_8cOQGB2sh+yyd4-W@!-dDI!gXJ)>Ae-lM~>HCU(Q)k zZQP)oS!U(wgq&SS4oAmYgjJ>W_es?nkS!+;3h6iuL(?inm-_BruapaQ9V^o3fmTYK z2)=^s_08-ObSYW-IZ`i64qUF2dd_Dy*zC8KZq~DQUv`g6ck!aEV9gV+^Oxt(YZLXx z-n@?F`y=I>yV8l&VKl*DbZJ#y@0&!JM!c?gb*!?cPO&=FyW>dMXqz82EB^yB?9<00 zZVs!7<9w1*GpM;9Pi(-PGM z^BM;H%nYUc_p!nvS-@}_y!Qc8)eurGk~DQ)q#THVc)fOe36)LIE$-xY0GwtKL0ozNY8<4RyFB700X`~Hb~sg<$Nz?!wft#>H}Iu5wdUd)Hw~zd>#2Lr$GK7i z+*CA+R|gIT73~j>D?qX)QnHTU?3yT_+wtn`l2TFOypHwM1NbicmYW@3MY=Wjxt0m{3vguv>HgESn$f1L40zkEGDpk(*{#Xs zcsqZ0*tzPQT?gQVi>mnh7f#C7u@_!E%}%Hn{y1?{u#wFQJ&Aa`MN_cBUW5JJv(j2$VKYd%P~e8HyXue zrL4ziCOBy~t-7>ZDoW0mXUoT&m~EfTl5>*UvDfKE-+$g~=D zI`b1S!>dM9&|on#MddVELYbis!AyIe{lV=>mKCa`er{+vr*ixnXvE~Cw|5xFj- zt;=(fma>=m4#jYcV6LMIKkSyGN?c^*uK>j;Rg*|&FG^J}lBtbSHIHPHQ4g#mnQ$IB zww;${gCZ#C0JTjlQ^mzwRJeS6w7nwwKqe$!oTG!^x@`Z!6v%UNj+aHGyk}Q9{X?G^ zix)igHI;ye&LkYv%#yCw%8d>5CFvqymi80OrUKyQKDXPpxfi~U> zz*zPAGtNv71L0?!B2WX(7S2h8K~&1#(Gs}9TT@=b&Qq`=PFu(+yGunNz64cEL==%qay;mVRdE-6SLmT7or2c3gpx$#R@{j=&vhuvZD{v)Q9Sa#M^O z9X5QqF-EGDrvhn%u9d^GY;7Odcrin;heTyCEUaz1-2pTUZ@U=%3RtqMm^}PDq>rUo zXY9&sthjw8DdLfD%R=}X)aHtEL;tEXA+cNRP`h^#e_mw_m%&?Nv}lEk8f73CiK!3G zR=7|V%acrs{^3|gN|_I7tPeJ9wSBCinOR<6F?P-Di%YLv@p5PNlYs_ntsIJn92w1x zwM-Wr&4*vN?@8h!K!==C1@i3^XiDo!@+<^?zAzi0h)JB!5!^#XNr=kGu}b}ohYrf< z76M2?Od_H}#jgGEqi)Jizs0JE3hYuHO<1lK zMfArvAMkw0zvyhV_a~VVbEH<&G9fQZ#j7Z9`CHtFq~vbg87HgQjjY#+-BOyh(jqmp z`Mk=>y?g?LZ@nh(Kl^wUkv9I&x7$2V=(p4KcK$`PUMdH1J;8EOe+j_@>8;b!tCBp_ zxtp4E4clQE9`A{$?rW&iz4okqbsu-vQ9r-Juu_jogVT)Mz<9IXd!o0ctt&su9WOJ9 z7^*%Lm$Lq{NzLNjY|yEPyY20(6o#g!h6}#Oo3ST}+qC^P>?j8_WP&f&H;zYGh@2SDza5KW80v<^TWy diff --git a/src/icons/qbt-theme/build-icons/icons/help-about.svg b/src/icons/qbt-theme/help-about.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/help-about.svg rename to src/icons/qbt-theme/help-about.svg diff --git a/src/icons/qbt-theme/help-contents.png b/src/icons/qbt-theme/help-contents.png deleted file mode 100644 index 5e4daff56f4dc1f825c9886d802b7b2bc9cc8017..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2334 zcmah}2~-p37XGtiScS5w$RaL}-9Q#l4v_*v705O`5X68K6$L^P1d$~eMBE_a6Q~u5 z0w1s*L+iJ%q~EFwh|(6laCv}!?Q*Up6a>^twA*Ew@${`=i~zwdtknSYKl{5ES6 zmk|K~nm*nhEC5jO5(U&S@M~{XAO`^SVa8UDCmbSIS{ejFZfnXl zG!-Zy!<8%{mC2{Dg*0Xyl_8+A;wVf3g(0M{_++N=Gs5K4*a9k?V)Mx?xR_66$5B`a zGmO9s1W|@$m;^3^ITu0L1&a@JDxU}lGs6W)h}0up$N(x_1uE;6I83!zui{4<7YSh; z?m|RA@hhp6p^_6BV=?s~6$Dw7Lq<}nD;NJelCn`Hu{a+5{Jc==Dnn!*#Lg!zWIUDq z#gx(}BC5jw;z*f-+m)N3a`AaLRGaW=5~Vvt>o2BME*4GwcM2J)k}P(HKf(ba%a09E zXbcvIC#WqUs%vO!Y3nT2)%!xc88mA~FgVl9Jjnc|ERE z=(_CDbIonFikhE_>+Xln_3h3%iGF21quG+Sp~h)#b3wTQ|FxXn{#rY!{?k zfu+~4WDU_PQN4ANK|V{{?40(V)dYR4wC&QS0N)Y|(2Dmd)x5lf*QM?JbM9GCug@Rj z=qsE`gpL(Ny0L_LvzIqqJyZQd>#sl+&dzqvIE2iuBU zEI-!ZoShSFY#+%Q<2yaUuBkI$|M=^%LjWIW%mQku$@);P!m60 zx{vrOcyQzHHFDF^^}K-bOED7wZO@qSiDd$3s*g9?@=RcVpcBsB$vL86ZhVw(-4VreWHE4{6MK2Br5&<&eXG8(E- zXq>Q(Ex<+}kw&_rUd+4h1T6d9@+7s{5H=v*zaCyc9iaOjT{V&UZbYkbdNXRwdpIgE z-)9!hkm&%%7i;1Y+MDKtc(ckae@r*#NWN>^88))ba9F*c&M2M%Wi>~n9XBz;JL%HB zcwfRa33qY4YoEyNxOq(3UC;_0)ft@`;ffeNPJ;~@CvdbMo_h^WeNzFValAeYlAg4& zTYc?~m1I5X4eec!D51VM}qKkOOEAmV%^-$+CI{KPBJw(2|!1nc| zr3zb`jU#;xI{A&bE+7-eA8}|_sbv=$J4$(+{i1H{^i2$*=RjVwY@vITU#phD+NuX`qD{$+YO zo@An+W^Hr7iK*Wt8C^SpLhEqoc7*BPXW+_$9ih`QAJd(Hk=M#%DwYGUNcq*#5kN1x ze(mD9mH!027dRfb=D6A)nSIFs&xLOhz2kLOtDcY`HwZkF+@}c)!?{7HmV;DL{P!_M z_*jA7|35-<-`HlLu)#vjKy)lDh+noGWPTfv?^)Ayy0L=@{`LSm!H3o=;@#CI&>*=h z7(-WyPXv^!%T|!imfFx0T}p%;NCcj8YOLh*g!(ij96z&ym?fEC`8uD2F}fx0&zroA>&+*0^|;pP%1>?ewol!eV+F2_(?U+>o}Xc&L_9^? z`zI12SBD79aFIdUM9~hkhKa1jbfvgxsJpN^we<0DbhrM}XY)t>tDU3#>_7cMF;^bA Urbl0oxPkyao_-!R?%YFv0yBi3_W%F@ diff --git a/src/icons/qbt-theme/build-icons/icons/help-contents.svg b/src/icons/qbt-theme/help-contents.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/help-contents.svg rename to src/icons/qbt-theme/help-contents.svg diff --git a/src/icons/qbt-theme/inode-directory.png b/src/icons/qbt-theme/inode-directory.png deleted file mode 100644 index 74efc06456b53d6170fbf3c56ce3b54a968430c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2762 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 + + + + + + + + + + + + + + + diff --git a/src/icons/qbt-theme/kt-magnet.png b/src/icons/qbt-theme/kt-magnet.png deleted file mode 100644 index 3bab5e4990c329d3f76bcc7e2d2d80a0396a859f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4391 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 hSU&pK + + + + diff --git a/src/icons/qbt-theme/kt-set-max-download-speed.png b/src/icons/qbt-theme/kt-set-max-download-speed.png deleted file mode 100644 index 2cd657da4d54ce5cdedc2cc467f749b12e352f22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 359 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}OMp*^YxbUq|Ns9N9f$`qfat)D zPdR%dfe69{lDT`M;OxTvab<^+OAjR%A555ZvAOPe-i#|#H(~YlxzOo`-f;?5kP8lbK-ua49n&&l5(yY}9q`PV1j{&=Hf#)MC-uttooM$~{P6K(Y-!eCplpMui(^PdT+Uel~o zHdwfOQ@f0~RKuia-LqE4gkAcz^wpL1N6rSCY&&EAb>#!?D5zuiyY?>(VWV_D*i qE{CS+`|T?iG`fUNba439Y=0?;FSvP0 + + + + + diff --git a/src/icons/qbt-theme/kt-set-max-upload-speed.png b/src/icons/qbt-theme/kt-set-max-upload-speed.png deleted file mode 100644 index f5d14e556a65daa12b0f73205b783d9ea4047143..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbK}QGic~>wh5VW<{VrZVbpGEG_y55j zkoFl0|F13kf4cAgrzihkUHm^m@c#ni|EoL_4OK*dw)2$)`2{oBuzAZJZ$JBSqGIoR zzwL)t?*hscc)B=-RK%s8aOZ0=5MaI7fAXZ6&2?WU%@NZlg!W^ zeWmo_qi3nUx6NjSiKpZzYI@u|yXJJFO5oOwT3!r-)8E>;~7A^89ZJ6T-G@yGywoC*Oom1 diff --git a/src/icons/qbt-theme/kt-set-max-upload-speed.svg b/src/icons/qbt-theme/kt-set-max-upload-speed.svg new file mode 100644 index 0000000000..b12e9b8dc5 --- /dev/null +++ b/src/icons/qbt-theme/kt-set-max-upload-speed.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/src/icons/qbt-theme/list-add.png b/src/icons/qbt-theme/list-add.png deleted file mode 100644 index 40bded949c95bb342fa0580299580368a5cce22c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1874 zcmbW1X;c$e6vy985>}CbAZP_a#3Ba}4ao!qCJCSc6|xYbh>9B^OHF1bEGjZumwL2{ z7H~hMctqtWD!8K&==CGpZcNq!_2+!{qOJn@0>YrgCusU zoy|xa0DxVzI8p`x0#gK7G2koX@XUAs&?%DX@lmieMF9+;P$=*M+*eVcDDV}Fv+#KZ zu;eS$oaqI)B0VHl6QT(bXYn|SoX8x`gt(=l({e*|Lvex=EG4-LiYLtuiX-4|kW3XK zp)i?-DxI8I3Ngd`>;csv=&ml7g^kI5jP6p>tPPz=|3Qs|$AdQ&cg8XjyH64>Vi zDlsWBs3ayQB|-w!!=d0hgqurv5bQOtn-(ElX6k|*C>U%v??N-CUDyt-LSusj0+wcz zA`_4pB>ZzCv;nbZOOW|*``}QJ1AW2)N%$R1PpAxEA`VZR3gPBi%(fu}GR@-8W=wA3 z`k){9G@FNwroqk5O;eakxCP-~#*vZ1GgHG-;^5KY-Svs^FRG7*}+1a_d%a-TUt5$!%X6^d*8#Zh#EG#Z5 z*|Br?o;|Gkc8pFMy1s^e|vJHz|;Jv|>j^nLvJ>66jefA3!HTL2iw=tyCFZfl1w=O-tH)4F$) znbsT2#yVf}p5}N3q)e(DTR(#793@P4TO^T`ZF6G9k3F}IV>>3$F2{2Pv(3&@Xeov|ifvAhEk>mvL#-m^rhO$`=;ws}LV-vp58DJsn@a65E05 zr=aZhJ}2O}Ws~g+_Yp2L-A1^uEec(Hn7?fgHK1#OW6q9af-2CK$C`2%RSVfr#4{K6Qs!63cPSE1QKr#v@}{^A=pZ@X{86=%BDvm6M;WUfEXqdp{&H{ zK{lJ!;Nf9gDiFA8Cj{29=`%E+K0$}l$7mGHLhL{p>I=rQC}3sdgA@*HK=m%UcOXrl zHah~$U3HYR4xC3hen>B~V)AUX(>gPdr61;+Y@_v(EU_)E)wWEU4GgSuSB7fzU8MKw zNI}YCw^adkAgSfJh(6l{belxS zs)ly1)6i8L>k!?6Cd7Sm`Y3I&a)hPI?Y66>Dy(7?<4i(z&$Af}-J!e#;rV~=^R^qR z58rLNHveCEf{^nyhUUbM`~0)}$I}ij?dOaS8`*+^Z`8)vQ^y&dGv2%oWaMl*? zRv)Sf@{9sIjcR)CG<$8e=lg5-8ySHUt+Y@70@H0#w(0W!64#M&%$9+v%RnCs=?xD9 zJM%rkxN=MFh4?Q^H63$yfu!n3H>z6RJX*c*UFM8=&MiCqTT{Dh zws*Dn2BL#VK^I_Tj8rm{lV$mSOx5X&8$skG1PIO~lq01|0sV3bc;U*{*U#=lDt50~ z(O!AazB8*qxw$Lj72i;_eqb8Fl8Mh_UI4s>*M!kzjJ-YeZb+yHR3WDgXVP+R)&y>Bswo|lIV zZ$(}h52OyfYsv|1JDl+ zB|(0{42;aI?A!t(a`H+l`bK6p_Kr@j-hTc;p^?$?Nhzsm8HE*<^{tbq&X_fC(XQS5 z4<0>v=G=u#x1PUv^X1$3A3y&#F4S!XhLg6Zi(^Q|t+zMBgO~yYTo0aXx{2BfuFe&4@-s>0`d$?yEps%MV5@B3T6SvBCb)y+T8|9%w8URPaG mH0wxVy=s*mcK?Ay>)&yUzs@Xpqu2ft#PxLbb6Mw<&;$TMJl);^ diff --git a/src/icons/qbt-theme/build-icons/icons/list-remove.svg b/src/icons/qbt-theme/list-remove.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/list-remove.svg rename to src/icons/qbt-theme/list-remove.svg diff --git a/src/icons/qbt-theme/mail-folder-inbox.png b/src/icons/qbt-theme/mail-folder-inbox.png deleted file mode 100644 index 7f3b6db51d4a9f2836bc7443089f6744bb6edb0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2008 zcmZ`)dpwkB8-54HXod;J=Fn&xB1|$TL+dbRF@rgo`qGF(Tel1oxt}RMi4waR*RYR>Jq0R0(?DLMa{qwzlJnwa1_kCa2_56Nw$Yuw4qjk6F zLJ)-Z_3`3D5CT91q@xL5F&F<62tgVIwqGC}l<)J+9I@pm`}oAUg(Oq> zA}7CO2Z6+mA59HNARUNv;wR!+$6T2wK#Rye;p8WF<;OX5BxL`1B46sn5dxmXIZj}S z!K5=+LgGsZTp^V$1w5IXKxB)_>|+Fugu)V$c~TNbL}W>wd4QABrXtyF#r@W35?(wum!}$ zfB^uMBo4^13f{KVGw>Fy5AwsiU|_X`O#xmb0fxIE!|FWT0v7P_d*mtxBCx621>RDR z!Ha4UwI;myp5UrG%&fYvS*w$)_0_@DQn2h=U^Rfl|4XjLeiskce0#6A8CK)1$--W6 z$hY@;{|azO$ql6a0Qk&Yk#Ylg5JE#!Yu$Qn9i;9C6k1Oov(doNXwzn6lMhVI%q_NB zZu@XM&dSEl-T}YM(TPALkttMHH+PyB{bO%mzW^4S!{r6;-7g3ZIUE)q8Fe%|CNBP% zP$ZTnev))bmYS9>&&X8dVwr+;wh?!EiNBcl(0eKhu1H9qn5+2r#V(=TUU&CbogezWlB zUw|XrXMMdq0#6)#(b0*9Fc__lT2wDTW%yI}UdgL@7(Ljvn1Q)gGlpBIIO<(Hz!F^T2+#QBf>zAU{Qq z9&kB6?N<3l_;O@!X{vN!K5vA2yQmH`G>a$n@6A+j(F9(lC#Cn~mS_g%mR{LNW)wAQ zQZvowOXYsW`1U+=`i>{E!QuQfig5i~aWrhYOVl)9R}?tVxm$kb@<6A*T&b|wy-x91 zH`vSrGq}R#E#h1~{a=*`hgj63xk|aqd7EW}x(D#Nm(5?qU1jy3yD&PL(;}aScv}e>m-6W4ndC)5*K&UtqYR$ZGJ%P zyIZuWjGoo!M`5(qJu7A$|I4TM5GBat=8qTin&kFItv*$j?bag(n|X~NP|IrU$DDK8 z^wK}A31w20B{d(H7tV!roicjO$|#;?Gbt)3dP%j_5^2C7z9!aken=~*OXWZ(lzp8)s)YDAevF?Z z%S+8LVC;4Zt-}`5QREG(tk8+({iqT?6+d=1B-2r#r)pz1m;V~qa4!L=-Ac|I6Jy^9 zx)SOf1@}}x$o2ignlJWP10a z8y}e;ZZ_*VRV+**IgVNugrqmjo0gb3Xp8f4f>M7}B2uMYJ=wrSm3&UM8*{z!bEn5_ zpA3m-lZ-7c^tJa|Es1i0dDFqJieI{gP3|)7=xOI`Lg#`97OG)chDigaheh+v@I>9$ zQ9TTbcr5os?L(?!s-7q#!F7V#`kyXw6l1oji{^oS*$Z=r&2dkv4{gFtAzjCL-*xX= z=bDCRkUVL7aC=zVB-541slikZcLVzRiZb!KEt)1Wx>m@nrB&4;4qe(s4#X%Fl3We2L&e zh8DCEE3RKZb8njiwg?jX3DOyet0ZP@!t!=#;lm3%bu>>9-?{$O(nh56Ums{@`rTrE>JyMaCFn-|O&kPJY5W9bWW60&(O4g E0C&|V9RL6T diff --git a/src/icons/qbt-theme/build-icons/icons/mail-folder-inbox.svg b/src/icons/qbt-theme/mail-folder-inbox.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/mail-folder-inbox.svg rename to src/icons/qbt-theme/mail-folder-inbox.svg diff --git a/src/icons/qbt-theme/mail-mark-read.png b/src/icons/qbt-theme/mail-mark-read.png deleted file mode 100644 index e96d81f409d819292becc3d3c820875e5fc9d7ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4566 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 diff --git a/src/icons/qbt-theme/build-icons/icons/media-playback-pause.svg b/src/icons/qbt-theme/media-playback-pause.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/media-playback-pause.svg rename to src/icons/qbt-theme/media-playback-pause.svg diff --git a/src/icons/qbt-theme/media-playback-start.png b/src/icons/qbt-theme/media-playback-start.png deleted file mode 100644 index bac2ea958ceeec56a76b5716e27a2787a497fcb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1950 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 diff --git a/src/icons/qbt-theme/build-icons/icons/media-seek-forward.svg b/src/icons/qbt-theme/media-seek-forward.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/media-seek-forward.svg rename to src/icons/qbt-theme/media-seek-forward.svg diff --git a/src/icons/qbt-theme/network-server.png b/src/icons/qbt-theme/network-server.png deleted file mode 100644 index a8f38a12ab96810b2b16e9cc20b6924cbb74fcdc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1870 zcmcIldpJ~S96n=;8kuNC?ktrik;}|5MMIQ9V=kS_ol%pf7<0>|&8Rk+M5P`j?M7E3 zg|5^#$+WqTnv^b-YF$D$Y*Mt}IiuZuo_+SuJxx=IKd&1ztlew;6z5EbAZr|DI%|mBf??|T|#1RbqN##jvGrv4&=MA;wcO< z$`rc55;vBR%;1w?5s@A5!W6j%3dn3RF;MKvl%Pl)0Lg3-X$^1|yRn6?EHQ~KAp$D^ zf)Z0m0(_Rxl_?-IL}Zo#fJBB6!5LyAQw*jgrqGoQm?9F80~|2Fjma!P7LiyYfCG@s z0#!r;2A~9llOSjZga83JAfP3brbYlC4TDtG!bu0D5%5&Y5nD6{8VT)%($sxH2{}Q4 zNl$ebBmfcvF+tXdMp7pP@epUEDWd&n?7#8JJb;PP)RJ!@Q4ldfLV}VyArcr_1=tYt24Pi8}Q#G}wO~+}^z|YjxoAsT(f#DouQ!{f5 z%kQmi=FPWVKv-zE$bPYt3z0~6b)zhC_n>bjQwJKkiPKWn^X@I-GOlXzsDR<0lHv78VtklwQ14R&n{t)$5g2 zzuc+5d$&fRxOcy{uD+qES=sX7q3TiF)8{YRJ6?6ZdE3?9)7$&5Z{YplhoRw-j~_=r zjeY(yKJi;^t1$#kF{XKYu1*Z^tFzKerRqX*Z73{8-X-_ctno?IGTfau#|5Y8>&@gN zFAW4mKPx{mQtF;mL`g0k(v>>)KW=O{8&{d8VN9j?3tYb_rG6x3a|tnOPNwdLbhn2q zHh9BMC3dGCTyi8C^;DlG&7ou-ZyM?n2)JFUi;X=uE8M%rQ}`#kdWXV23@=VBm&is2 zY9f1^@U>}v1I4^bNH*3g`;@i)@osGQHDkx{Q@nZ5c|FG$QycZE&9YbLiK5g|565S9 z4tQud`rx|$vz3r?t79;&K}Rkwd(yYJ5~DOIYdg9yHGxy!*o&h+&QS1PU`+Kgh&Qk? z`WayfT1tXJ)hm2{m|bf>J|7EZs27T^_J6rVF8&YOmm52B-QUjMdWFO2`a->@~r3d2qs8o%AG@u7 zY?CL$371D}=C9Jq54T%$rsCL*ZH2zxULn?}HnmSBC^$)M%C+AQw!}Q$bFkLbG3a7( zy)w3}EoCiKrQjAsk)dV<52iz%vpH8uhR_Ahwddz@u`}MLzrsauaf2tR0Y^Gc7|Cy) z;oMYy>aNDjGx6fw?rgHq#vbK`Shq2ww!inTgkHN#>TU7}wu`jSsY+;JUz~0Iwv_7Z zsrMV2`)-NR;8-j2ng7>ex$*s((t)JplQj3A`NhuVs~QZ>o3XWY;`H+t^|Hu5Gxyd8 ztKi#PWp}Ctl2-46C+~77B|#Gjw`;FN8)$Sc&U)QE*KECYQ{;{%hwq4YweZ+=k>yV= zITe~bx5uVeTVfT1+mhO=MdM$Kwhau;N*Q^Pk_Pi_H{B{|xzNU7?PXf#wiuN!otM;E z{F7yK#qvoln@I{!4Xv?oI QdC2b3eCXb#UXeTh1e0OW4gdfE diff --git a/src/icons/qbt-theme/build-icons/icons/network-server.svg b/src/icons/qbt-theme/network-server.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/network-server.svg rename to src/icons/qbt-theme/network-server.svg diff --git a/src/icons/qbt-theme/network-wired.png b/src/icons/qbt-theme/network-wired.png deleted file mode 100644 index 0fb3162034b6a5b850f7883970afabb9eb163cc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1859 zcma)52~1O26n!leuoYnx7(o#N0j zCZJ;31hop7Mqxlv5sDytL6C6}E6WIoE%W~ulTkCtyu7^Ld+xdCo}2Wi&?uX9u_jmm zfUcLPI|Bd|6rzBR2J{mp3Gf2|jivecc|a+AghCdJ<>Df=XR|#$qe-k-dmrJt9b88W zpRhgJo)u?H-S6yu0K)OK1NJ@~XI3Sc0?bS?p=@kn$I0jfe|1c71*A<`h`XK_e@1DED$Jg6Nm!57A% zDip&U=!H252nCP`{KA8f03yH_LLd&(f&_>HB8Y%c7or1Cgvm(yrE6XRHueRF$q*B{ z2sm#BmiRY1mYPHMBKvuKQHpd*cT`87W4k$HIa1QNHN?p3#PDJ-t; z8g83Ww@c~-y;`z;Yo&LM4yhBYjTL!h*MdP6zuj`TNUIrqw2`ZDp~_Nf7W&)*?QlEH zOWWntNHF;XY;^@KysD;S~^ug+AzsUGgv^i(S|?}!&G+6R?6T&GjOo+%wYu8(%O%IVT` z(@F2_TXS2iXP(oNG>0{lWrV!LeLXduEjm$e)7V~JL$>OP8xvL+oV++Z$JbLR7t6!! z8CG*$7OAMbrTH7Wq&Fxi_X@wlWqwM1newjn#OcJrg|1We*2!B)8nk5%YU|lcHo)cx ziuR%e7-(sh)f$SbMc}m*t^ZsdY4Y{h|B<=UK*j*RV%EhoeIlYGb4I17XJvJL#bQEy>_Bm+p$Kyr7(|AFR4sH_ovG+UGYYuBtJ269E&?H$0v(w$ju@de z{plDJ^mN_afGe9e8#NHM@jZ++mo6D?D?x=PMMRBR$b+WbK0O#0zZo&>rC3m+240E# z7xq=ihl{<3>asTIDA?ay`8V=N5IC(4ECiWijana6q*%it8|{bFmWE)<7$nzQR1PDReF;^8T>eiRRx>6g#+=p@kXq8Z|gM!DDkz?%TorVwfN7{sfn5>(<3g33Iq;ER#@MbEe svFOl^s>G)~B|9WD<$KSp`sPq=QG{{xleTz;5MIH{gW_KDYsis*0KT8{h5!Hn diff --git a/src/icons/qbt-theme/build-icons/icons/network-wired.svg b/src/icons/qbt-theme/network-wired.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/network-wired.svg rename to src/icons/qbt-theme/network-wired.svg diff --git a/src/icons/qbt-theme/object-locked.png b/src/icons/qbt-theme/object-locked.png deleted file mode 100644 index 39ac5c86fc9f88060fb9b5c08980dc522e7b091d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2339 zcmchXXIxWh7RE2VB%#dG41$yy0Vy&%0R15Gg4{Mbshc!eGa;pn$OVhVp4Y?5E9#-1mLXbN*{P{=+g zO|&Ke04QI)S0Df=Kt}~YT?u+5UI+^Y0L3&4G1wcrE-nI#3`TuD^(Mo8pfp}uPaS39 z$Ew_WPEiL+iK3In#uAzxQqO^2$ztht|&HePGG z&fLQC`ybX@S=-p!**k1>{BhGy7$@f~+uX4@4^J=e?LNK)B8luz2?(TygocGj?ud$x ziQN?!|Lg9AJ&Aki`wtvUPDwqKb~yb=#y=U%tn8!5j^~`rKUHwLkj3V3i%ZJND=K;X z>N7QG&()rpi z{~D7$d;a2I<9|=SeD&t-yZ2KcK7Ic8^vsv9vvc#`7AmjGhyb9HwVa^&UU*Y&z$rxa~0mst@Lpl zpflycaIj8Jj9cwpw0?dbLi70zUVxsn9Xk8FP_J}8ujjn%I9kCwGi#>|oq9@E)WMTw zAylNiwg-v=)FF44__pgeVQWQY>F~gN#I-(l<#1o?m#S&oW2GOS8Jl4i_gIz8qO~^W zB5wgf)6UtC|7Q1hH{iM_tfttVdm~1aOM)L|W1sXDsOJDJ7tLu+ZvE~W2@iF^HWYV3 zFaP{IpXSQJ_IJe#Z4SBnlR%6Tk%7dym^dLSQxOc0@>y{R!g0dk=*On!5Ma(QH-ye_ z;WwUN_x!0}D}mW@QvF21Pl?J#(>msoinwEdjl)smzRFpJ^(khcCg}dHLpP#R|K{|R znKY$tEp6UMr+d)`e^`67_1yY=hDOlm(fddpsx~{>HqByFxg#kjuQpbVn7om21$gOB zJ9l7wCv%@J5FL3iDCl6B_CkM%Ei*}VA?ZH7rM73mBzH~wmYcKQ?(#+JD;E4xX`!ImH9k*SP_XPpwDqWC3V`S?eq!UZhgeBQ zb7QDQ*U$S8Z551VPNE$zBPnKB537+TL<nS8Pf%DY4rI|eE891|38pHKd6-;xwT0GBr+*8#A0iguH%=Y zY~zxzCN=)7Kqapu%D3uiRv&SZ8!%lv9Lu#2cc&m~&~*v~+$W8W8zzsH@_Z%|M7vdf zYslqPn8o3dg^CgBt+|{MCrY0Ff_;~Hd_2lp`+LK;VoqXl&8WWfoe#cF~)t5UEbH)aYB!Wwl03js(Tl1qTAI_?Dvu6@gPe z-M^cm^j+Gr!|IFm%+`TbPW)eNPt>jVRhZ8D==)}5ZESs1A42RL+go(P=3))di%p~d zl}azJ0j#hIdaeeZ#0<6`PZP9??cHmJ*Ock4Wu8--1YDR}y#Mh5BmI~Hlc@O=aJWS2TJ7x^iQwIn!z@3=+9p-VmNP}!7fpv$*GcLQZUd1Ue{;6-O zWf|^@QL^RP#9cbv*HnjZ?yQYT~q14k--bu^fAM*O=A;a zL#*gXgPSe&_fK@sx<4@QXH7ZhH-Fl9mGZ~WJ@&j;7mK9ft%dc`gn&Qy;z&`pxW+Yz zhD!$;ie_#&)A%HMW&7xcxW%`^OlT2xCC4i@lC3`KxHug_d~-!|Mh3hdQz=LAC?rNP QG8(@5dXv4HJZM?}0dT%Hq5uE@ diff --git a/src/icons/qbt-theme/build-icons/icons/object-locked.svg b/src/icons/qbt-theme/object-locked.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/object-locked.svg rename to src/icons/qbt-theme/object-locked.svg diff --git a/src/icons/qbt-theme/office-chart-line.png b/src/icons/qbt-theme/office-chart-line.png deleted file mode 100644 index afa1720be4ec855a5baf7cb50849ab58f4d67a27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1310 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 rL6N{K3|_r@>Dm?hvgHBxKNHL2I5_gjh diff --git a/src/icons/qbt-theme/build-icons/icons/preferences-desktop.svg b/src/icons/qbt-theme/preferences-desktop.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/preferences-desktop.svg rename to src/icons/qbt-theme/preferences-desktop.svg diff --git a/src/icons/qbt-theme/preferences-other.png b/src/icons/qbt-theme/preferences-other.png deleted file mode 100644 index 70067b644b12f8d51641fbaa96798a9cb9a0698b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4610 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 F^naaDDQN%z diff --git a/src/icons/qbt-theme/build-icons/icons/preferences-other.svg b/src/icons/qbt-theme/preferences-other.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/preferences-other.svg rename to src/icons/qbt-theme/preferences-other.svg diff --git a/src/icons/qbt-theme/preferences-system-network.png b/src/icons/qbt-theme/preferences-system-network.png deleted file mode 100644 index ad94a6b142c5da908fa1be7b9af0676d16eafb25..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8770 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 diff --git a/src/icons/qbt-theme/build-icons/icons/preferences-system-network.svg b/src/icons/qbt-theme/preferences-system-network.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/preferences-system-network.svg rename to src/icons/qbt-theme/preferences-system-network.svg diff --git a/src/icons/qbt-theme/preferences-web-browser-cookies.png b/src/icons/qbt-theme/preferences-web-browser-cookies.png deleted file mode 100644 index 956587b97d2011c2ba47d6861f1f231c4363be11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3797 zcmZXX2|UyPAIIk`b5w33Rynp(YKQxrG1J)PmNVHL#WqLEnI*(eqWp#&bCV=j7ek4X z+(mMfkY7pt3~gn?*~eh9K_(tCy7nRPBQXcu z7$)}q`nI7c*C4ok_(8jqhBgrZLJ}h2N9cz3L3%`n4*mqvo(U%g12O=ih+zmjIv~~~ zF?8%sqU;$6Qm{UO2_PL(D3U-&*oW$o=sE-*LXv|KM24K5EDrP%0qy1olQgl5QB#ZOcaTZ zBmy0NB3&}Dpz9DBC^8*MV(Jp81iS+zI*JJR z-#|PW4*}zV<~+2q!>ihK@;BO)0k1sShDpH8W)(1Tv(L|-JPm+=RzMaW;!XTHju+u? zw7CY*hKv`Sx3h8k3jy|c<2E|*#{JjlrsoawzZ`A`;SB<6H=diJ{`RmL`B$rd+4~pz z+3;72pZ5MU>p%8*V&1r)k^kxZU%56SZ{*$3Z}|LG^)oUUPxK!_&*#=a}ztKPt^XATa2} z$>0z=gBcnY9&sx2^qHvWnAo`Zvk9zoiRY7&Q!b>Y{g!?)<5FhUiRX zg&9R&;XOAh7w^lzWoa^WE=s#UmMF`Q&?Lmy$x!)<%C|ds1)$6-9RxFACC4nehcDqja?eQq)LNUYbqd7fn=eFGP=u(V@i>hC8xzA`tbuxuZTEsP4%}fa266D?>?Kb0S z)7k6U#3O1X2d9~js>Nq ziQc64yzQ;Mpgt;{X)N8E;)L-5`{dT1Q~Xg}kf50fZ_Mtz|5v=4p^aJ6XF{8g>c1N({aXH)vlI-1Zkh@eC-fXhX zUXJav_3o@svJ2P|S<^3lXId+q@Ep+`k~}*v@FDn&ofmnkGladz803B^?bU2sstuys zFanJQKL|Qk)rqj_R+$#EBeuWsY|geAoM9$BWR;LRead@w*!_7dj8$fYhIUVv&p_DF z7=&TftlFa_3o>9#zh)FQdKrLTx4u!Pt+ zf^=m(C?;oRIme_Hrg8Oz5UBTn=)r;gUm0j3ajK`-Q=Xw=-=#Fi{b23^D|J55LyP?( zqMVOiSLm!R;kPuA zN@4+ZSzsBA>6IXgm%;eft^ypVz^YHCk}$NrMwnRPG~a*8fB)I4?-ZC&WKWSICXX;G z2pf^r59I7_9kRl_{8aH=dOqFEKH5L|)2dskzY5wtpptRQTl`ziY>^}^T=r8ZspP(M zzXZt4=(6vC)B<{p1PjypI6o>G*=34-VHR^(ZeU>E4rMlyy1dWC%)xFo%Uok`Dkp}< zXMM1*b@^I$k&j{(6EyJx;HIk#%W#~oF5B{X~i-XUo zct=Rtwl{8W$hsr}kW!5N=S4Laf_AZ3@dW|20Kt~K^ns=q3h~u^kf*{Y$05-U>7XBJ zf?v37IWhFoGJqxmeXZ#)GS0YbX+sl*NlN(90yfvxo>2$f} zH4m!tHC10R*0OoSA}18V%AA(IA*9$+>|FEil;6swOFptOk!h=l_{=SuMWTptYw}F> zg7W#vhU`;tTfsyUQqhy_H^5ql7%!BhJ_x`8X5ty zPZUL`6jsOxm6$rD?i)gY*}F=kzZYtydN-oS%=}jc*~Xmc&xP+rlbr==AIO6ZxBCdK z>9>8+TzayC0Bx}1y%5z2`&|;^Df?g?ObaKvhDA~K!G2qPfaYG3&QJl-Aef;>+2Jt@ zfiyF&sC3;)5(_4@iqr%R5Nh?6^Oca(R?vcq64~{BU;&K zl+sxrSISnCCXz(;hYoVi-)##Hh%gpsgYbJa_e$JWD$Q>4Z^PU-Kmd�NRT>}jPv-c zeB|Q}eAeASr=}BVck80azqry`Hq@)4K6zhKU$;?UjXTv(C6n61AJ02qz^_sKoFcW9H)d!lP!5;;Ou_>|LN_S|$kA^%Rd5+7(*U^T+ z%@GN>>NtKMDuv%|KL=daUf3R~I4qJige~I794)lC@2t422UD<-IgY+qBZQ!e!KfK# zLM_3jS=NYof0fL^FM=}IyL=1Pg=Wvxr*E$fl$%B)q`^rX;+n89DE8(DIf^$TGg;rR zgC2I>wQ23}aKw(}(5{lKYb^SA8|u+J0)-QMT}E!~oDzZ4h)Lqp3I_)>GIF?Nhraj& z^$8Dk9R}zFV{Ml%_j&g=#`@jE+UT8v8@|8pTc4I7yma>vt3EleVM_d79aX$aU`jd2 zc98$kEH_|xc>f=C;f|DCn|a@dE^T)#XZmwctd18hDy7fdqWERE*B4)yxY#E#(x;Q< zPFQi#t}g1Gd>c}>%Ehg!_j8ivSX`I(%QAzES0~PXu76>@%{reTaCw;vjWnGe7^|%; zPvXATDEYLecnJGT1hEVrC75=4OSPJDwzW#+}q_h;pcTaZL{-SEp zoKCB@n1q$9H;vB5fdOMhTcNH2!oxv^aLF_{=2(XaWa05E zg$?J%!z~WyM(d_b!FA0RXM?ic;DTZ{yu`UM5WIO}ERy0&c` z5e=%oFt14DYrowvl%)>=5Tj;ec5ze1(&R>QoD6sFD)aY-cvo!XwVtc!f5PB7^XlAq zm5y;-Dc-hji)?*m1ylhy0h2WdKiNd`DalW z_tgBCB=4>Iop48dO+ibX5SVo&M-Sc_untpj6PonUQv(GG^fDn_1!p*_gG<;3`d@+{ z#>DP(+P|Ha6d|?!#zaO;))!dfCk8qtH+B)!l5}oq=p!fbB>ze@kM(V+HAC_%ovIYW zsepX=kvR#;ibW}!uDf53G%coh!ne)46Dp+>P+=E~*PqpJq3!WR6Ey+Pc{LEDTm+LK z>VCp=kWpcesw|Y%CN^&3vCp}EsC4rt^n-E-bt3j6obE75PQ-cwJdk>_BYXDVy;u*$ zt!5r$?yFUi=R0c;J=ijI;jpTCUP8^=6yh%RP&>uUQ-mh0M zDwcSeK|JWTfnKB4yMFF6%uFyd#ehc`vF`@nXCox;-Q+pDPdf3~LdIa@dzpPfw6*

8*N0UVBQM;RH3?{N%9b9CD&`vKYX^2KQ3nNIAD1^QPF z8a)`cgKX6B4atKjPW)Ea?>LiD4mjSiq_2~)VQ*1Ma?WqBWSkk>6memg%&~iQapP=JfHmW*`t<>@ZYJmjY zm!Y*@CdlrNYTP2}3i~ii%^tI<(9fjzt57;c%4WjZL0l{65`x(TlqTpYxA%payyhwU zrI69dQIl(7MKUX!>xM&*GX}>>TsQeM4R5X*0-<%_;XJ=onbBwwFZz7a9&H=Hi$D9W ionz`o9oHmlXa3(Hsi>)MvIKSgnqfBO8C{#%_P+p^xQn#_ diff --git a/src/icons/qbt-theme/rss-config.svg b/src/icons/qbt-theme/rss-config.svg new file mode 100644 index 0000000000..1388eed3b8 --- /dev/null +++ b/src/icons/qbt-theme/rss-config.svg @@ -0,0 +1,17 @@ + + + + + + + + diff --git a/src/icons/qbt-theme/security-high.png b/src/icons/qbt-theme/security-high.png deleted file mode 100644 index 74fc5c7066898423c336706eb5910f3b0890a447..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3163 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 diff --git a/src/icons/qbt-theme/build-icons/icons/security-high.svg b/src/icons/qbt-theme/security-high.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/security-high.svg rename to src/icons/qbt-theme/security-high.svg diff --git a/src/icons/qbt-theme/security-low.png b/src/icons/qbt-theme/security-low.png deleted file mode 100644 index 01b3ca9e0b0364875f0a87756e30b02913717e62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3722 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 Qe`hN*&^6Ji&~}OX533M&YXATM diff --git a/src/icons/qbt-theme/build-icons/icons/security-low.svg b/src/icons/qbt-theme/security-low.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/security-low.svg rename to src/icons/qbt-theme/security-low.svg diff --git a/src/icons/qbt-theme/services.png b/src/icons/qbt-theme/services.png deleted file mode 100644 index dc3fdae8f4c78d978052cb4b31c57df1bc645eef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2188 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 + + + + + + + diff --git a/src/icons/qbt-theme/state-error.svg b/src/icons/qbt-theme/state-error.svg new file mode 100644 index 0000000000..5291d9d01b --- /dev/null +++ b/src/icons/qbt-theme/state-error.svg @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/src/icons/qbt-theme/state-information.svg b/src/icons/qbt-theme/state-information.svg new file mode 100644 index 0000000000..a16cfee931 --- /dev/null +++ b/src/icons/qbt-theme/state-information.svg @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/src/icons/qbt-theme/state-offline.svg b/src/icons/qbt-theme/state-offline.svg new file mode 100644 index 0000000000..185e69ffd4 --- /dev/null +++ b/src/icons/qbt-theme/state-offline.svg @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/src/icons/qbt-theme/state-ok.svg b/src/icons/qbt-theme/state-ok.svg new file mode 100644 index 0000000000..0f49bbf869 --- /dev/null +++ b/src/icons/qbt-theme/state-ok.svg @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/src/icons/qbt-theme/state-pause.svg b/src/icons/qbt-theme/state-pause.svg new file mode 100644 index 0000000000..b9b551815a --- /dev/null +++ b/src/icons/qbt-theme/state-pause.svg @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/src/icons/qbt-theme/state-sync.svg b/src/icons/qbt-theme/state-sync.svg new file mode 100644 index 0000000000..2f7ef018a8 --- /dev/null +++ b/src/icons/qbt-theme/state-sync.svg @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/src/icons/qbt-theme/state-warning.svg b/src/icons/qbt-theme/state-warning.svg new file mode 100644 index 0000000000..a951dad807 --- /dev/null +++ b/src/icons/qbt-theme/state-warning.svg @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/src/icons/qbt-theme/system-log-out.png b/src/icons/qbt-theme/system-log-out.png deleted file mode 100644 index da4844309158dac1c90d8f52bfd0cf0250c0e69a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2148 zcmb7Ec~nzp7XMx#1i=Il0f&HKix4)0WCIE(A;1Afq^T^5+89761zD3o7$5`~8LXu! zwiXlx%diBYjT<5gq*YNAp&E!l&nRL|WruMPF%8U@1Z+G1%;`Jtyzk!M{Vn&Mlb0i` z&_Jw#r2zl{8yw`n3jhR`2+-GoM^f{iZ~#z#tdQ^k*upCxfQX2Qd^$azM9Oz^N)8Hw zb-IT~K8eKLwk?rP=X-f2Q>j@bQYw)s@b(r^C>bPDvbQ(a(=&xe<54JSBogFjQmGka zGNeH~l}6)IscB>~&&vyrGAI;2nVhkPbID`~rcf8MTB88--jLsH(Z&@h0Ybac^r82xny zhU>97BV!ZOjb`Q+oBo2gvfgZCyXC$2?d%;0j!rJFM7QnkBr=6c^YW(q`uPV028Zkn z{b*NMctqsxJyHAif6V4Y$HX3t`y?ST=}>A~I+vH3CCL6;PHvtsUsO<3eB`swOUsTO zKk?PcuPZ7~Rh_N6zKN`G3Fq&%*0BOUhqW%k61LjQ~I!2mAYm3)oZr=de;+ zV;~)|??P?XA#_J?RJ^ox*;B?maUDA|tp21{FaLXWXPVN(RMWA-Nrzc>byHKV+ZS|v zjjc(^v5WQB#f~SULNZTF?1Nj79gT$cnY_rj@W^wK;_}Q(?#`};&d!76-~{)bDgD)Q z=Z4BWoarH4l8TeJQur#DT}8`LT=fw5b$Vki)xKS@sg6B~+h16D;PRL%I(}M~(A}T9 zTpTtY**lf8R33KT%(RiWR8)4^rNnsupifoeUoL9!)lv+(qR|2!9dctb#np`WRsP&>W(qJR3{##Y)*6hgXS3mZA=66*uIn&m$d)Mce6dy~%SJ zxR#TQ&oq&;N0aKkqQv?fB8z$}oXCI(XN&A(3q5fAC4CN)fEqI7xeeM!fE*;cDH9$A zr6K&UokSfBqcB&ab)s)pVl9hMHH|thSVPg6_5Zmym@__&l0S*>w%a6XT)K%^+7*C- zJZ7z(z9<{>=}BF{dX2`K=7=&+*((735p}y>Md0Ku^P1y|BaTw{5r-!T;m_X{0?cUQ zEGW9thYUTlu6g`{lsyY(kW2w4Aq(fmdTv#N?nKTWP8DtHL}K3Pl{~}S7XQg6XcTW- z;3#D(Rjt6xPp&LQB=-efo{Z-uv`qCH5V}Z<@gK^C_u8K> z;on=At7A8ZJtn0wP*1^c4XzW(fG~IN;^k+;LorRKDah2~bAEmM`vg(da@{rRPM}l? zJ{PlPx{{}5@%1AO>o{FDJ1P^KeNCi7x>I1~#5@CJ{3tFHR5#+|+OZ1YNoYMi-ktJT2hJiD{0U2ndgk@uhA_oV_pa}?(%xCdmFi2^+Y2pC3mGx-RqXMJK9sH7 zY_ZV1;p}=)2=@MZeFGz_LRoEIQ63A_wNbjQovOY60t_ z&wvViyOR4BVJ-J%i!L~r?A_X;lHo)N(?q+Tj-C3FYdzI6EcntTYH%c%f=W*LWlQ|b z*52Z8>St={>W#P0s2VO5+O;i? lIoB;zB^|(1o~-?~!E+Sgm(8pDo4aLdFgPI8|63-f@V`nnViW)X diff --git a/src/icons/qbt-theme/build-icons/icons/system-log-out.svg b/src/icons/qbt-theme/system-log-out.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/system-log-out.svg rename to src/icons/qbt-theme/system-log-out.svg diff --git a/src/icons/qbt-theme/tab-close.png b/src/icons/qbt-theme/tab-close.png deleted file mode 100644 index 627f4ac919ea34d1043930b45f147afb01cc3d7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3247 zcmb_edo+~m9{y$w8P_qAV)1v zqivU4NVX!^%22K~uEQAT(?0v0v(8#)t+UoX??3PJ{NCU9d!F_CzW05<+qTwbf_x}G z000EdamMxl00AKc;N<})_mGl{03Z-%ZfxXm{r%#@q-05NsgBwA_DVOMCNhkzT7KHfEMy$W#qKwL6{a`;R78LO4pm}0pqF%9&L?)Bm z9g&_tk`$Ni{V8hh@5{}X>dyAHv`maoEWOgtw_)yZ9oya}%-p|}*B5aJbn*Wj*zPaz zMf2x#(+@dqFVU>sRe@~ny8|!lGc7W>E%~RRQWeWXorKfq?OfA3i{g96>tgU;n;k+V zt4e3xrs6zs z9_f*OyWz$=60WT`+UM_U;e1)W9ZFv$6>5ZE1ncMf{_J3vc(m0~wmK)Z&O7a^#bF`) zx-XZODY^cU`-h*3ml@uF^0UM1QIDU_%0`kr>w?7)@BOm%aUJ7^RXIxDqtaY?=b18U z&`k--0tx0Bi5lFegdj!aov1S;&|P1w8ljE?8+M&Syyx4>y|)TJ*}m+P*u>4DBfA0Li-;dngwT~A}^ zZ#&(H*CI?Vj5o<1<}4ZIsxoCGGjFc*z!&+!5-IM#jTLb*ya(^cym{YEM!BkxN8&*7 zuJdv=y8@4x-6O9~*x)D8g)Bj^eR5|;mO2=i8qY&7ow#NQpiSJ-qnn46f6K|N2|3I+ z|5mDy+$aosN?r2a9Ul+&zEC}hfybJdu1TtB;Y|Xn(BUrRGfAC}-sDgf${TV-3bquc zIXE8&;GSW&16K8EepQp#hBuPy(HIHxS*O}#u8E!MDj}s}dTKq$?5BWRa0>$PH52l| z`&UoaENrVJb`JLPG#Z&E&0Wh_T8eW`Z@U6ZNl*7+SvM2HmeB+rLd7(HZjlsdP)E^w_bx7s?ss zy7y);nM1Wju>9Tm(Qw;x)iG9YHD``_M`?*|&d>EOAK!545+CR>*TS| z?epoM=L8>HuWvi*2j+=27G^MLqhFg0RFK*CfSCgJNCv=tY9oR`CvI+<_e_qryrxd* zh%;zCSqiQGxFVR4GZ5;+xne;|rL0NOBMK_0A;074qXnIwrCXo$)QOA1Q+Iu{+CK0W z2r~NfV2Wo@81{mcDCWc5h>K$L05u@cj5R+Ybj7L~R*b|R?8#Sy+cx~(GB^5WVFRUn zpkEVhQ&-E5uac+4$JJpX9p%8pgc_QS-vI48V~LXU@d4if%L3;RnJz-{?LdsiW6g5{{8L)|`Y&#BD7A_T%* zpsq^9CV4F6IH7a)xD_E!y|hW*>IKaP9pV}C_1(KF#6lnZNbTJSr+_d zol?GP#Ix!F)vziz&Q%K%I&3v+x9)H_=b4r*hw5mMQc~`l2CF*9Sv3dO)LV8Kg9>`@ zhy>GakK>9plRVE&LRDj$)9GQoOZTt8LO~j8*~F_=&**kiU8%rJVZKFe^iHT;jC%&% z8k&CsSPI}oKmDM&@A)%rXHHWx-i5q!Mm5Ggljsighq3KQT44)m=i1Ynm+42^p(Usx z=N|NI9S+(Edi*H?$kk_Mxxcjq(8SJ7taDQ5gzoew1 z(=|h<+MsM?P$}DsWdIEd6%E3tY6HoPD{ZBwcr$cW6d%07g+mpIKtOc2qIW0wKD7GzyNSM%cIag>EjO@4SK`xCT*8}e28YYGrWbhPHStwr|>iru|rdFiJWcS5O~ z|J7I|q#^CnVZw&Sy-zHswSi`#W|4?v@K{Q^N2%!=qi|xv3qcxf4Eq?E3X5?eJBLKR zI~{%b=eZ}=ldKLWV@&A&Y@3+Hm3^;91n=9m3&@dRiiS`uG(CBb zV87#=f5IRuu(KZNY2Ue>(q7&_*Zzd=>U-heK77xS{1=I*D-<*dz;(}kmnF6TVM5pa zzf$!MwroP039fCgl-VxA7oV3k9EN!i|9qt{@}WpX3K;%)ktH28v!qcq6e?w5#CoVo zzdV${9@x*P(4avk!!#9_wVXSo;$ zW-7;kXPh5CpvV>^Y~2DftK!y-YqtsOb`essj4DYfJWC@>6#As+H$=I7j$Kpm^XVIi z!CN67oWdRZxRFzDN00-sEHYqA=uU=_n4)q(dcF*#fDMBK3m@Os>4`eb<)xYMOI zsk9lkpway&@i!o2RxA(M7)PgTKh{HS#|_5bg{!6sdvR$n>zgx);O&#&rK7Y>@G)6u zI6;lR9yu(189IE5b+9Zkb_!k8WSE6SjC4=84;P%~TnsdO>oUZp7bVb;)D`~#FjXQB zioH;g}4&(wxQ-P%hy^oSi_iR6uaKE_+{c-9guO@m-gbJ{a0 zz0b#YyY9^PdND6ti8u&5rQJL*RL6V=U+GQ^1cbELG{5z&uL%e-anE`@>W{c|eV(U_ z^Ozja{`M6GPG`u5cAWO&o|1D}dXPyM#~I zTg6ymcf!~h?H4J&a6DzN-;_784pC>w%#$keugT6g(aHEHY@L^em0{A1eR7(2nF>Zh z?oKpk%CpEq#~lb5n{r{zAKG`XhH7~Elf*9HX}*z6taZ1C?Dszeg>>l@k{5$^AxrJ} z`w~tr^JIW#+^=x846JpJhgV7c#@~vzRQ};-*g;YC2$k+v2-IoDrTD{j?K!CS=;#jA zkVv<1;}7uIPlO7LnI7G~?B6v*on&NXDqp4jM zU*t=-hU9oNLtX$(b7v&%R1$bAu6fRH`}rf>D~#3_gC+ZCnZW-#bYJZP;#8Rnu9k53 Py=Tl#tc}Z0oR9rGYPNbm diff --git a/src/icons/qbt-theme/build-icons/icons/tab-close.svg b/src/icons/qbt-theme/tab-close.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/tab-close.svg rename to src/icons/qbt-theme/tab-close.svg diff --git a/src/icons/qbt-theme/task-attention.png b/src/icons/qbt-theme/task-attention.png deleted file mode 100644 index b92e0cfd67a32239bf5b2284d8102f97d306ced7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2891 zcmYjSc{tSj7aoKx8C@p(P~=*Q!OxAl!=RC67CVtLLJ1WK*9h50$Tq7`LR`{9RJN$; z>L$!$lw>I(Yt}5K{J!6z`!s)?IiK^s=RNN^&pgjualjqfA+9J6fk1ZH+8lO*Km>qP z0J2>O_zJ4>aDhMsyB#ntXyCcA0ojO)tE_Zwi8JrW3*c3{4&5+syXxAJhhe9qc@)<- z1-O56Y&!B>Sy^~4&7PO<`kL$jpj|mOY?>oC8_T2Eb>umAl5s4$JtxPpn~LYH`Sqwj$=`Xo=w4WXc#Vq zkCL%$Djt}{pIMD$^v0jHWsJYbrlns8ZEmr( z<1btAWjAMS8u)36zXIO_I0&?{sSG;bS|6zJ*W6s6zcR@A=?c6aNZ2w4o^gx+>%}%t zv}up8wt0lPh8*Dc4w(yg!Z||(1ckN*(&&(>E|Q`k(P12TV*49{Lk$hO)4ovBDLI9ddL=F6 zYGzh;PA-{3r8DxbXv)TMb|+lsx4922w^xA&G4TDUrTrQzSs17!*cr%NHs8 z_GDEKI2G_g8SV3Wa_>T6qfUD_Zenfvq)PHc7CnX-bj46=*yIN>d_c`xES0CFw)+lZ zPtmlp<$xa*CNN-IW@iy;o3qPWT7wc%d|SGPEGsKqXe@@%B};C1zN2NF;~l4ebL!cr zyn*lf?2g#Mr~RF+k*oB}SR38C?)4+nKAxQ{1()3+!G&XzzWz2c64s_A9|TL2Genm{ zhpZ0%U3Sl|mt;CL9;6|+Tu6v_Mx6VgA%y85U3?=yZkVB)7f{q|*c*|R(1-|8M=SYw zSj(Xc;nRKg3M;Kub4S{HRUcjwel_Xi;+Gn#kl9)$(l()iX;&?8UA63g_SieY0`1tg z|Do)1t&u>a4^CUA2HqBh&&zg)2Wy{7h+tA2^ksN*DSN3HkNuK)-;>3Z(poc1FqY~a zjBjLHhE_c66N8eD@a4z~x5*7pVYnfT`?POxV>pnS z`AvK#^t)Q!Ja6ti79_P)aZ!J7zPU5tn=zoDWT&A4v4&Fe?H+2E<8;{+WwQ+spQUC|6!HjmBn zd3YHf0Mj5%Og#n?BaJUh#qY2J@w^dymCXLA>UYWxZxlhz24 zbgFD7Rgg*(Ew2C7PGo4>zzx_DqezUAMxo@AUTGt#UfdR%sKOp#)>d0XlV7*Lfa?7jpyvHN(fEV1fkAI?pRji6(qO-x({}vjJ@Pu>~ zJ#IxQKbMhuzWzi^ubmN{S|WGqWu2&dO{)&}&(!%LiH)W;|6-N#H3B^2jtTD0nrLYI z+XYPRuv&fDETOWC<_^dOYV@olZZO^ij>35B2$2jTuvWW{uF0>ZW|k`xUesnkTWXx*&Uj>4W4MCic@8m>H;Xk;JNtx@&|o zweWo3>p&9l(oI?Qxn(Q^eHZqke&+(S$|CrBY3AfA!BCorc1q95Pz{g^lh_ww-3GlN zS--Mxxf%Tr^n&%HVUycBu?&d@*bD8*)K$XZSIFa;e9_s8Rl;OFCVH`@^id|n1SdK_ zta@OD`SO*fxn?VT32+7jY@vK9x#1O1a+QB&DxWe+FipY3fJ z4?x)yM1;~%hJi=b(M-v!Ep)b$e9EHasdcj-=K3EV9V}QJ)gphcMoQl6V=g0_v>%f` z?0A5boV9ueysUzu%=}IOoZa`1Ik)RzFFYmk>I@+&ed;Zc(SfXIKR_W$tst6q2T`Xy zcb3T%lf>Mw$s22%?A>L!NCWKdY*- z#)u64-y?SPJR(+=x5LOZV#;EIM57rP1^fWBXijL} zto}l`lTE-#*R1ibv-gx0>&`<**-8=zekZlx-pBK-uVq?(d3j5H*BJ-BWVz>Fqg+#o z9!K(#7yCUN;WO1f2Syyrh2QCs%&PVGG>O?0ywIPQjw(WvhR>xOYH6pNH`8z{1;HcP)Jq F{tpMImMH)L diff --git a/src/icons/qbt-theme/build-icons/icons/task-attention.svg b/src/icons/qbt-theme/task-attention.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/task-attention.svg rename to src/icons/qbt-theme/task-attention.svg diff --git a/src/icons/qbt-theme/task-complete.png b/src/icons/qbt-theme/task-complete.png deleted file mode 100644 index b54b0aefa93e80c3241338a6d08142a6d42f8d91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 678 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 b?-gG*0k1 diff --git a/src/icons/qbt-theme/build-icons/icons/text-plain.svg b/src/icons/qbt-theme/text-plain.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/text-plain.svg rename to src/icons/qbt-theme/text-plain.svg diff --git a/src/icons/qbt-theme/tools-report-bug.png b/src/icons/qbt-theme/tools-report-bug.png deleted file mode 100644 index 9ddfb0b4daa370a45e602665ac3097781a972980..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2639 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 bM~bS<7wxM8cr}&vFBVfnoWWgv*Vz96Hb|+C diff --git a/src/icons/qbt-theme/build-icons/icons/unavailable.svg b/src/icons/qbt-theme/unavailable.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/unavailable.svg rename to src/icons/qbt-theme/unavailable.svg diff --git a/src/icons/qbt-theme/user-group-delete.png b/src/icons/qbt-theme/user-group-delete.png deleted file mode 100644 index c22fb6c62b629252071a4ef14b8745673145cd15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7084 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 niaVj13FHDdrvICw55N1;WN zJi<4!Vqt~|#cg!pn$dZn<1P|C26T!bv3Q#pkrapz?}ChIBE;RqiUuKsCo&_+PEjC} zPohT=o%m)E|CuRa>+~{$bfsf zh|e4bAwJ095g{HdATfCGE(oVW9AFv3Ab^4F!ZO4V!7wSg)4%gDDN#x^2$l$7pC3G; zMB3*~q`MLaiC#MQ$1I7@cL!+AdVXk=_+x?vNEOxe8E+{$`8)q&;&(OE989$wxY|A4@t(6I1b5nO(B-0t{< zq~w%+sc9LR2M=ZEsolc&#|Jy&w!V(F#JW&f04si?eqt-kSk(~aiV zw)We1?{(aN(E0FD_v0r$&z|?b=zIC<^_#cv-VY27e;674G(Iso_3xLj(=*@HRXZC2 z0K>Mowsem38oGB`$pSuuB{j`OF5F!;xPzfm_K6uyz)AX3rO`I|Qdl6lPP4#> zmfb!1b$3rjG*<=f4-llcP_6`g?EY%9$~b1Q;nWqAjF(d*&gq34!d;nV!I;(h1SX-f z{C-YQVTh`;es%sJP62lnedY8S7g4W3eg84H&2P=NY1Xb1rgjhF6T@8Yv~*Nlex^}4 zQ#8(j`g6Sha2vMu*q{0Mdi{ce?8Lwwzni9XR}X#a?_3`?RyNMdwqPGLAJ0wFGZ=SO zw6tdi2Vazh8^wpx{6v15wqJx=8U_T?tdh~B%;y-b3Nc48gfMNO5;M#uCTXQ#k6c)u_7@42 zhPi;TBt&D<4sd*y5khsuVsdV4rVTsHA8%tg)b%MZNl3QLGW^i$NuEV3-fmfZwt(jE zJ6O?<%Mxb<$cf!6#R-DCIJqDV&se-gv4ODAQ9~0&)z;zz9QL>@TXP`@KHm@_n|1afKekw)nN2H99k_L z@beL}mp3@8HH4rGo~;rB7%c#WwGcj?MHxapvaRwe5Dz7%dTvCfYp?uNb;6&CAw^mp zV=u@0Jk1m|ffoN=vqwq^T>}ZeTq^)bvIS&R=RD?N;^S(+#VIGWu*InnQRQ0N{u8>@33cUFA3V#id?Zngca+pDw&k>;6>y1V@c# z(Brj%)vmM4;vdFh42i)H1(t^i6-np2nD(&Iyk%IqSo_>irNt|?> zps#q)Us6$n5-ul5beH(U)}aGsiu9+VX1_h%+pzQ94e9gn7toM;)hv*pn{mn{5dvQu zh}BwGlL8hVY`a*)C~N<_&|a>2t;i&@C?dEDogF$=|M^(&bXSw{+tJE$_f)sM;Hp-| zQ-bFQ07vV21>u|#=(niX6R>iZ`5RO*Bc+u%mm!A+df1W|^jXV7nY zz8KIwRzHs4M-A9MyK*3Mo!ZfNl|831XOk!RyxsSAwAHL6!w*s@1kNPU^mi^vnh6k- cIzP`PU*U7Jq0ObOFasg%ZD`gPtvJd50p-iZ;s5{u diff --git a/src/icons/qbt-theme/build-icons/icons/view-calendar-journal.svg b/src/icons/qbt-theme/view-calendar-journal.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/view-calendar-journal.svg rename to src/icons/qbt-theme/view-calendar-journal.svg diff --git a/src/icons/qbt-theme/view-categories.png b/src/icons/qbt-theme/view-categories.png deleted file mode 100644 index f139b65fa469260d104a668cc53b6cb640d93130..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1591 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5FlrNfKP}kkP8C!^`W7m_V)G0 zX=z%a^&TF%_VM)=p@qgi^?EVIR(_>s(YgBm`8M7a#y&-sfyL&&dB%YSW`SiU{zc~g z`DUTTCP4*O0VO~!CZVN3u7!W0d2oqYV4V{ox~K#@fNP`21C zsL%{35(tt7GAx2XY_lK;x5zxO*fglb0w@~{R90vX6b}Sy0jewnGJssOz!H!kNCe0R zGZ1Qk3V@11T0rK5lmXR%M1UqhYynvf(GF4uk_D-R3PKG8>4F&owi>1Y>=Lj!5Zgfx zgPR6687cx6hqwf4HQ2!j5s;HWmV&fH84!0u+yfQ_c@XSua0tMh3er-%#dEm1(e$SNo*DXXY!>FVhl7#f?Hn%merI6Ap{di(kX z1cgRKMaRS?Bqpcl?Z(BUITPo6q+_S}U_m#^KtbMOAcM^BzUfAR9w>o;%TfBf|M%hzw;fBgLQ z`_JEhjz9KaWnf^Q?CIhdQW5v&z(!sM0R{$xjhiHo9^&mQ?0O%oI5Fe!d2kwp5)C20 zE26Xw?@W4rtNpIkg#ZPH#Tqe9Ob#Iznm86Q2r*_h80ZV=Wb2AdbmE+~BJv&ccY*)? zde3bR9e?`j^Xj_r__JD*?dbgjZr4N;8{{Lu%d%OV z-jyuzK=ZX+BEw8}2NQ-KCS*4wvnw{2v+HvgNz`Ug;q-fuEryWB44S%+J#`>+E z!eAxdur1iMTKlEnj;WhGw@m7*W>AHwMF@`OV?*i(bGMYTlr9<>U@Rp9!2&8p%M`N4erUgilM0u(OwN&!VQzegM9pU zPhl|BYxuaC-`XU2)|@TP;z|wgpHF#a#PAO4Qix8AugnKL>ly7_8=kd1XS}lW`oDi= z-`i(dl_@Ip9Jcu9^J2~V$x57yC3<>JEzrx`lT_Lr6j5?crP*lDdHI}uKmYR1J3s$} z>^|3}&vWhM{%yW!l73WnVUd@$QixNgbjz&3TPzC~nYZqh;+Pf`(Nyqp`X)PFiHP89 zTw<@%yR5DzDCudgEHJoK9duzaxA9!1%xF z{+`Xw=fTk6$j~5pfQ2dP|CD6{eD@!Dg`K~=%gBxmDHs`aw(%5IeVZS43nb|2>gTe~ HDWM4fbuCZ4 diff --git a/src/icons/qbt-theme/build-icons/icons/view-categories.svg b/src/icons/qbt-theme/view-categories.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/view-categories.svg rename to src/icons/qbt-theme/view-categories.svg diff --git a/src/icons/qbt-theme/view-filter.png b/src/icons/qbt-theme/view-filter.png deleted file mode 100644 index d49ec895b0de0aa22d52b023e859ce36d4e9db77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1134 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5FqtGz$e5NNP|FqeQ0Q?aax*I zXuU;fpXM0;NELKxIIqK&C+$5M>|*#UKSh2FO?-3FU&dgEa!(0I~(7 z7iu!pSg?UX#cT!d(tzF%DGBlmW?*DuW@Y2#=HcZR77-IyP*l;>H8wT3vaz*ya`W)^ z^A89N4hap9iiu55NzW)MtEjAL=;)a>d(MI-OIL5$df>>>6KBp{y#4I?%UAC|efj$1 z*Y7`nn+sjvFfcHk@^o<}TcCL+Wf7OE`9F=!=bAuy+fuSKM zxo*kzp6RD;q9oaJo>rWvBEN2)^7|x9lLGg z(^5*^d{d9b1)laMS-q z&lI=BbG#LI`rUe=4nLE%`QHxKW0ikZiBJnP?BM$Q^^JvL|2Y@_b;{T;a7(}C8~4J$ zP0suOGd-RzYh|%gfq_Y478i?lzz^|6y+a)w8QhC*)$3n-aIb7~$%OA5>H-D-4xjp; z`1JpVPxTQ$?brN~|HkrPUF3(=c@R77AHVkh_No8TlwcFCkzuHK=CoIqVFrU<2m>RF zfCFVj%t8hx4uu9F@!%@oha~ojP0V-xo?@)n&U~jHNd1_`T=0AS0R?f1Crr&T2@|+^ ziW(jD3^-U?81B^ZF=()|?Zl9*e|upgmm{Nu`^Vx)9j`08FK4YgVIJ*sicPcfe|jL> zY#p`#pR1dTe-!_n&g}Z5QR$C^VBG=^`+ydCjYIq*581muFuQhL{d>3pNdIUweaQYS zMSe%`3A+vLFPNuuUSwa#{YmHi`+tY0xIDi5a%%k>DJS0azh#&Cen@&wQh_5|M%mb- UvQ~G**MU;3r>mdKI;Vst02^<{m;e9( diff --git a/src/icons/qbt-theme/build-icons/icons/view-filter.svg b/src/icons/qbt-theme/view-filter.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/view-filter.svg rename to src/icons/qbt-theme/view-filter.svg diff --git a/src/icons/qbt-theme/view-preview.png b/src/icons/qbt-theme/view-preview.png deleted file mode 100644 index 316b3cffcf6d34c9888dedbf2a2fc7f999a51476..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2293 zcmZ8h3piAH8~@K3Od_KcpG!t)t*6XP;h;}%hUR4R>`aY=SeBvYJ7;LyI_Es+egD79`@a9@`Ja=?VtDH5nCJii z^ypq58~{*oiUL>-IPAU{VVMBI*)T35vttn>tYL|W907q1>xCpvESU?x1thkRz=1Ua z5;vB}QP=#86S)EyK`54pG)EyucoG2-E&_WI5UBv?YA=kyOPGZpA)Fx8-%CWJW)UOe zg;^MZjdMyQpL3~^xg4>;%Q-J%|I!N<{B8d-2HbAWj?9LLks;L;)Lz6g4}PPZn{%#( zno`&N++E!Z*$YzbYY=Ito@9P_WEb<^uW)!6;nU7Q3VfWJMH~hfpwJo^O)YKg0-c4r zdW-aN28)*%E?s71{4Wzz^W_$JODk)emEYNZ|L;|+?bobzbaEyTNo30U4I5pkkej;) zZIc(>m&sytxB-DdA)7Yun}?9N&P z2_69GxU0@q5CUNW%z7`;C_Y#CA4&h?uR=bg`Ahyp=|pl&>Ua=76VyK$8`x@#MYGIq ze)4; zO{<`%qD#lSAU+I=?7n*?UNe0%=jFyTxWa)E$P{|*W)wZ5`=iAVZI<0#nF+d?tDlfv zpZSt*;?NFCHdblH@SiC%zcq0?liD~nB=<0Gjs5sibi>=n%99#)G^EaMiJcvN6D^OP zZkWC`&jTNf!(j60KLbvYa-uUX^ zDBV&PgX4F5Ie3=gBka;0wywsWC(7F+o9R!XWG&1dCwcpp=3my#KBC}oj&fg{XNN+K zA}Sz|pw))?a@(HoHPBIpncx$j&RWkFSd5U(`I`aLkBU7qd3a-tPR$F0Wr*xj-x#G_}TUe5L^9LtewvE<3cbS(cgAEsRBj<`5^X zZ_%PItfpV5Ud=WWoom`=rczDsDl!4OZ+xo#ImH>WF)ZTmltkG!40VAbmZD>O-jKsx zN14xgor1>$AId{p0hblm^;{g0Ty_}sQhK3tOgyMcQlX*Xv=No8&EyT*LwceAqj)eb zI|j8FQV3 zr&7oqEF^E;=++TQ)VNnW4I`+he%oAA60>7;iR^>1&e_O-v5NR=5qP-VU9k85ScPe@ z9Cdyv{n*R$nt=ytn5zB1Ef_R)Tbylodx~4>Nd}ixhng9|S4!;Z+R_fL*SQwC>fS1I zNj(EQrrqhIE!DdbA*aw9-8Novr+hK$`E+-y)C2sbQp6OgLwub&M4v{2 zb12>b5>xeF_#k%Xnb*d$?K5JNwjKvrEu-Yk%t&$gWzf29_)~E2vO*y;9R~Bjlg*$!^H9lrYLu!F8ovC#)H3upj zw*N#??=Tq7fZmDs*th_tCGHQ4>JmH&GXV1OkFa;m->pSGCeWpK;G#F8Dy=<~bXg93q zzaukhX16OIEHWzux@Z(gmY?Hii5LboOPk%MEm~~$G&dG+%O&L!^&MY-+8Dd~^UoCk YiDvSpjxknrf2kp7PFaQ7m diff --git a/src/icons/qbt-theme/build-icons/icons/view-preview.svg b/src/icons/qbt-theme/view-preview.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/view-preview.svg rename to src/icons/qbt-theme/view-preview.svg diff --git a/src/icons/qbt-theme/view-refresh.png b/src/icons/qbt-theme/view-refresh.png deleted file mode 100644 index d0597294ff9d7031ead09f8eb9b787666760267b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2978 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 b(8-U?`_Dx`sj(8W1qpb%`njxgN@xNAcaLiO diff --git a/src/icons/qbt-theme/build-icons/icons/wallet-open.svg b/src/icons/qbt-theme/wallet-open.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/wallet-open.svg rename to src/icons/qbt-theme/wallet-open.svg diff --git a/src/icons/qbt-theme/webui.png b/src/icons/qbt-theme/webui.png deleted file mode 100644 index 03604e1ea218d335974f713de0d8c41f2d798970..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4452 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 Y==|EgF3YiGtD~DM+Qyg5VYXra0iS2b!~g&Q diff --git a/src/icons/qbt-theme/build-icons/icons/webui.svg b/src/icons/qbt-theme/webui.svg similarity index 100% rename from src/icons/qbt-theme/build-icons/icons/webui.svg rename to src/icons/qbt-theme/webui.svg diff --git a/src/icons/skin/build-icons/Gruntfile.js b/src/icons/skin/build-icons/Gruntfile.js deleted file mode 100644 index 2a88a46395..0000000000 --- a/src/icons/skin/build-icons/Gruntfile.js +++ /dev/null @@ -1,22 +0,0 @@ -module.exports = function(grunt) { - - grunt.initConfig({ - svg2png: { - all: { - options:{ - size: 256 - }, - files: [ - { - src: ['icons/*.svg'] - } - ] - } - } - }); - - grunt.loadNpmTasks('grunt-svg2png'); - - grunt.registerTask('default', ['svg2png']); - -} \ No newline at end of file diff --git a/src/icons/skin/build-icons/package.json b/src/icons/skin/build-icons/package.json deleted file mode 100644 index c4e5b5ca34..0000000000 --- a/src/icons/skin/build-icons/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "build-icons", - "version": "1.0.0", - "description": "Convert svg icons to png", - "main": "index.js", - "dependencies": {}, - "devDependencies": { - "grunt": "^0.4.5", - "grunt-svg2png": "git+https://git@github.com/bertyhell/grunt-svg2png.git" - }, - "author": "Bert Verhelst", - "license": "ISC" -} diff --git a/src/icons/skin/build-icons/readme.md b/src/icons/skin/build-icons/readme.md deleted file mode 100644 index 97c3fd44f9..0000000000 --- a/src/icons/skin/build-icons/readme.md +++ /dev/null @@ -1,14 +0,0 @@ -Convert SVG icons to PNG ------------------------- - -install npm - -Execute: -``` -npm install -``` - -Convert icons by running: -``` -grunt -``` \ No newline at end of file diff --git a/src/icons/skin/checking.png b/src/icons/skin/checking.png deleted file mode 100644 index 58d3751aa1191c343bf45b30f2fd85114c037097..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3731 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 VTeF*mDxUlD1{tIdgkeL7g diff --git a/src/icons/skin/build-icons/icons/checking.svg b/src/icons/skin/checking.svg similarity index 100% rename from src/icons/skin/build-icons/icons/checking.svg rename to src/icons/skin/checking.svg diff --git a/src/icons/skin/completed.png b/src/icons/skin/completed.png deleted file mode 100644 index 4e23903633467ecb5419748f302f3261f4ab8199..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2140 zcmdUvdo+}J7{}k4F{P0d8bu5hJLOuW!Wx$erPUB2mzlK7DIIOoP3WB&cUHMX7pWm- zOH))T5i>DDZfQfICd^bWn_HM+ytD7joOSGJ_rE=R&c5e&KJWMWet*yN{PUhSiR9+2 zjM2mZ0HD0xh3EkQ2v{NjMHKuBW%+ml0Me1P({meK0)PYn=m1bC<0Tn0WIQY5FES>{ zm?&d{jPU>fAGk4Y9%E&CK4WCgKQUUC&L=z&F69oa=StXN$Vxfo(R@AUz^42%EaXRC z&T)P^-~3j~=YLCh*W7Tqp1)mwf6n>a3v=yrOXr;bnYaR~Nk1dbF%P%h00N0pKrdLR zxCo=PSb2%c(q*b@%dr|OR%&Xk($>N0>aAY0R^Q+|{JQmqM#d(lW*f~nS#Ghi{+?j( z;7D|G*}h|^8_8q0*B)F=8k?G1T7P@p-tp#bXIJ;T z_q-21y?uPa$4{U82L^|J|1vx>IyU}wVsc6-nw}BQLN}S-699l#+)lLj3=bT7xgqQs z0&qIw!zysfBRZ}js=U0Re=j?y3e9~U#=5?qU*zy`h0%ialNRUfOX*R(;RVBSU(zrA z_4(eynjHBkX422I*mkUyK*g2>1&Mm5c9}G4?z;hnUofmFaiay*DVJyOkn|;9UUK{l z#NUj^xty^V*##qCEWBEf8>Op7A7gYc&Q#&k>_nXLRhcU4*xabxQUw9Zlnsj#qyQx# zkZeh!g#uLDCOj_uT~6KOd}dCySxR3d?{S95vNR_S!cr|yA==;${ro-)U8B{&0Z$)f zG#9_>2%wtzerDIvpzW2ePwaX^mVHFJvJ=fTd?vl%x^**L zH?SMp8JridoC0tboQkLra>8qq=TuukzX%BnV%n-+eik; zsyz{Xd7=&uu09zxUNmdm`o+ZunxL)ieTR8L#y%lmP2ls)@UIb;RwJ(aw?Ivfy%fPS zVS}V>MCD^_FRzztYMduDjIXJ;MECLr>UbA4t{Fdp}kaz4pkCJmDo}xAXS2Jgrbwn;-@<^jxnK_ zVDST$3NbV6gGah4$ZAez7jIp6vBY??k8p^~?6T;kTV)BJ(OxIg?3pS4>Xy^Q9E}I)ZV?Bm)`8 zr7OA) zN*CofB@!z9hZsM8RM_)WfqupEi_=wUxKOoS=z`;ZWBUiW zyBJS(c7sMIT3i|ZMJb|t`qerZKHKtB?Ev=_W98u?(LLhrL8Liv@7MirQ@gSF&uvpP zY!ZpmZv6urWNaPYG&_y{2$CiSHH0?@J4`9OR3r;jr%dDnw{d8nSv+UJ8L@|eDV}zx zxBcgl?ua2I5f}l45QK265~sx%0Gp8`N3nF~13;XE{_yGFiOjKd2|4oQA=Fa!ICo)k zpx(jrx%Z_@#w4NfYgq+Riy~@hmCDToPDOCGk`Qb{N3r?HN;1&~oM2|v zD-O=Ku`>(Sp0@Gmp04AnH}i~{om_>V&Rk9n)h@FsX2ZYoKOedlUJ2am?=86_b+&JF KBi?nOME?Q0YEn)B diff --git a/src/icons/skin/build-icons/icons/completed.svg b/src/icons/skin/completed.svg similarity index 100% rename from src/icons/skin/build-icons/icons/completed.svg rename to src/icons/skin/completed.svg diff --git a/src/icons/skin/connected.png b/src/icons/skin/connected.png deleted file mode 100644 index 043eb18423bb6baa1d79cb01528a5281ef2b5142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2524 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 Crj927 diff --git a/src/icons/skin/build-icons/icons/disconnected.svg b/src/icons/skin/disconnected.svg similarity index 100% rename from src/icons/skin/build-icons/icons/disconnected.svg rename to src/icons/skin/disconnected.svg diff --git a/src/icons/skin/download.png b/src/icons/skin/download.png deleted file mode 100755 index b61efd5416df0335370426fd8fb87cc8a398f301..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1831 zcmcIjdo+}39R6k);d2)0SDq)3!<31za9E_*1ptJc2XP-oAc{deDUp6`8r@Av$k-}BD-COas=*H9m;4?&Qj zADADMKoHtJ$UnpzlwhT%LZP9d%v2^Rjue{e!r#mXoGzyOr;@y- zL}onGQ|`&%Oywn$n8KwD1;a;7=PD>n35l_p;Vt#xB+{5NikFDQlY4T+bY>FOM?wZ- zw$y_uq;W-Lw#<_$rt{=9u7tvtlX*fKM@nUjC`>7tC#G{`G`5(^meQCa3TWrZsaz?I zEv2%6ScW_~Qlyb3qjF>vAY+MX90}0Vxf0+*V@s%937sQGOt?}CM}nMiBy^x;0|DT` zN(u;#BLiJPtmy&)G;e_n2{ZTnMl^a&48%|h3^n>$B9zwM#d(lX6ExPEUgw;V{r>@ z7JY}eTWs&(=(NPemEcBPN+MIeSRAg8ub+S5%HUO@tJj2uuZ@geCy0rS+nBH^Q795i zq;kd9l{rT?0 z$4{T9zx)+AZBzt7TCe<~rt>(1+XkO>5_mOGwNRt*bX*IGX?YV%FTMJkYg2fmn^ zICYTOSJm)t{r=r6%%O7Uob)71cDie&nYs371A(oNEsmacA-$y1yg6e2Hr$G*WgRwC zi&N;yJ0_zU{WC+yqf(~Fe`fSazMr_VkGt@q}#w z%3ivHIB^i_#6;^{mnxs5CL-}e#-;GcCzVuL6+IEDb~h@88B=M`(eEFt8&pwN3ZiI0 zuM{4Xfur6()D0}EPAME)0p5k;6vX^QOecmI0h%Xufznc^6BBR<7#BJMt4pQ~D|$Sb zWyA$?wl2e}uXbK1=G{vmFX>N}jA1M)AOo$jkK;EeH`@DSAyX8e&(mJtblPoXpvg8| zEnHrw8ZU}fmg%*kCjo};*uyDq1%wF?$8hzJ{&lL)S+UBCrmg7OTzmM6fj!JH1~3F5 z<`X9F6%s^40KEVM1q9IpfX4vcdkLaP0QUi&-l$Svn0LmzPc$00opztT9VFjiq+cIo%guv&V%H=-Vl?P8>l-{Ci??9Pk47r4O z?z-AUbXr9v|(~=ovm)q1Bc_kNR-LOwk6xb-@LRtDnBte zbKbNtFOfM}h8;T**sOV diff --git a/src/icons/skin/downloading.png b/src/icons/skin/downloading.png deleted file mode 100644 index 35d9f43f253e603512336d0d0369f16d0285c68e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1490 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5Fn={z$e5N$YuD?z|g?Ju!_N< z!NGW@vC1SBnLZh*1}W{S+Ca8ahmu0Sf<~K$T92A?x3X-ftV*Yfa<4K-yj?-QTVAQVx- zK~mjHKxIG?AQvd8*sTau2^0acfh3R%VgngHii%x|ATC%VL>E*UPy}cWSPM`Mlnpc% zXaW!c84xy50fgNRRu5AEG!yC!m@LE=pkg#}pa{@>bVDHK!1TgpaWUfZS1$wxdv!^W zUoZnB6Eh1dJ0}+pAHRUGh?ta&tek?PikiBnu7R&FKYsrD{pat${~~8=85o!+dAc};RK&fx(&)yVAmZ?_ zSFt%LWMzxc0*OVNT3Z*cSi!nTiAU(_ncAOnN&k;tEth+E_~nvq=2i3l9tqOj7ngtD z+*AjI-ge$Lmcj2O^hzjbM79b!paA1_}45?mX6p z*C$qgzYj{m^aTfQT|AjEbJ0e00I!W{*&Jn`Lm;mfR`# z<`iw~y%ZAn@|Z&Zu5+mHFof6g=hd(QB`xZ%I$f&VfO>iIs{vk!#ub>^wg?H(*` zj0`UJ%G`VkGbW0<28b+LaB7yyALE#~JCb|~d-fi@{pUvGpJy~iPa6ODSl_WvdoKTP zi)_&6$J76Bl#7^sd-t--Nd;%a+F$?uS!Mrz`ro2IYx$>bblIYKsau diff --git a/src/icons/skin/build-icons/icons/downloading.svg b/src/icons/skin/downloading.svg similarity index 100% rename from src/icons/skin/build-icons/icons/downloading.svg rename to src/icons/skin/downloading.svg diff --git a/src/icons/skin/error.png b/src/icons/skin/error.png deleted file mode 100644 index ae2513198d07d1033ebb149d98345bd9115d3918..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1934 zcmeH{Yc$k(7{`DA|DTz0pM)8=Ol6u;)FdoXMvWrQG_H{?|LSuyF(nO}3NvmAC7RqGMvu#GmCPC8uyx)4o5Kk(HBsA+O+KVNvnr zt0kpnyo#!8)iu{^>u)wRHs5M(YroTR_g)vj`@y50UO`{~z~Io+XCtFymrdUwYpQ*d%|_{Y}gqxeKC zEj8ZVW@nzD%YLKglAoj@?qNSF+mc8s>I{L~MW&LcZy%aGvANwnIUhK@)ptg;h6bi3 z6F#x`bhN1cnaswS9SPuyvtx^%1GrEz!ukk4;Obg)(LB!<5yt`84Y6VpfWr_ATF1?e z1O7v-^$-Oa1j`j88(O*1XeH4O>WUdChK$n3VI{tv*oeV9i2DQ+`t`&o8Q*Xxa-u;~ zC4q?%WN_oql3=N3RGdBy!iJ;shcyYNfC_dS^Rds2(@NveF7z~`^p-L>7C>Z2Wdgcf zJ%Gx=>=PJcIRazC<+Ri|kYCM}Z0D-*tC7M?ULv~2Q8@_~6KLoKeBl~N$mz#&$~-It zQVXmlf`zIsLjqEFu1pV;EVUqnLk!@*lWGU@EO>Go7xc2oIR6@gPrI={D1&DNW_y@A zW&l?#!DTW#QAD%_|&9A_N?HJu)1QO9Jj*gc%S z9>Wdt$Pwa^!xIKc>F9=zUj)Ht?h8m!AfV$$-Ka@P>FL|MrneoqvZcdZEp{#)H8>a< zQ2xQvimN6g(nler#$gkqN(0Xi%657~XhKYLyaD2(>t0}Ok5cB2sQ3#rsmAv4uS4}7V;ry5#ot#8ua>>C T6m{Auo+WT~rqk;8Fw_19kHYu- diff --git a/src/icons/skin/build-icons/icons/error.svg b/src/icons/skin/error.svg similarity index 100% rename from src/icons/skin/build-icons/icons/error.svg rename to src/icons/skin/error.svg diff --git a/src/icons/skin/filteractive.png b/src/icons/skin/filteractive.png deleted file mode 100644 index 7bc43f4d3d897fb8e8392e9a1ecfe7e984f7d8c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2162 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 Uww%(-OhWDu>khh=yZ9&l4YU&nE&u=k diff --git a/src/icons/skin/build-icons/icons/filterall.svg b/src/icons/skin/filterall.svg similarity index 100% rename from src/icons/skin/build-icons/icons/filterall.svg rename to src/icons/skin/filterall.svg diff --git a/src/icons/skin/filterinactive.png b/src/icons/skin/filterinactive.png deleted file mode 100644 index 577a8d023b225af00583a9947b2549bc727aadf4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2162 zcmchYdpJ~i7{`xsi)pAOrA16j7iQ4h7$(-GY1lM0V|UYvWoq1N7$%Wskgif%g>)IQ zF~g`QiwsK}c3mooQ6jNoHpC*b6#JVw)$Tw2xqJRN=Y2ol@B96|&w0-CoD*~}DoT5` zHUvQ^+EzCo2vPy13baHOJi>~QaN9kk#QKoFD36gWHY!Qlj!mJu`>s3Yy| z1vp$Z78~m9%yV#vAdwE>a2y+(SVu=79V8ODI9vpU5=|!WCy`RXV}B3i6=_X4nH8-~`|S97Ms%zzm1L1V{>- zau5)BL}5^_0nDIK)XF=25KP|Z0Im#&+mFc#k1`n^1X}?D7J$wFFKX9Sh>n@_2)*$CTmR1)_!4bv2Oi_jh0pzthJ5pCLEqXvL`z@ zQZ_p|f9c}t=1$$}vCV5c-P>me^Bcci{<{MLgMwLm_Oe66!Xr45+-Tl`xcI|@#H8dS zDaTHpN=-}8IG>r7opVK)o0osRKqM}fl-#&^>!-5virbaas_LI>YJa&~SKsh!V^ed> zz5A_gkJ@FOkGr0B_dM%;-uL^!i@_oJA1{YTMqiDM|2Z)^^?G{d&Fo)u^KaiRq?fvu zK#J=D+wuS?6cWH@sGRhpVmK15U9Neq8Qj{?r+!j6^`TaTeV)G_ts- z9`$Uc*7n#8Y7Giobx!K*2)`Dd+C;dXN1b%=SbEfMwl(%IWq8Nj?)9K#| zgN*0$H|IOP3VUd6zBS}-(Vy%1C{~DHV&b`?4YZM{x0shEgKVw7-6syb7~P%p%NM>r zM~A|fV*4%3**lNq)@SbE=UOerl%z`MrBL0(d7u5KvsYaiUmY`JuDW)@KeuM{{kq2L z%)+8G+~rzRi0RjXM0C&vI(2+6+ULsm!v%pFXt}-TvySald}@0~OLxfeG;g=d)!8T6 zhAAD?XZmif>xEeVftRx6-OWz8>@Pb7F;yRzl)9+T?^2*D$N-dP1Lzm9rm`BHQns+YS8Z4 zmef#g$?W5yttuor&4phHP*HrJ%ky5NZ6 zFJ@Gg+$vx=%~-}?t}`FMIsnH zD`poisUCVRsz2}aRUFMH!#cwFF({#Z2qKT`2y@0DNsc;nPt9crVa827Tj|`m z%QP6fY}3jm*~laJ)c*s_@fbo-S=gJNy@=B9CJkcI2a&H^`~rd#i`6ZpgN%_*K9on9 z6bH@j7Gx*#DrLNcVe32e8%86J2j{zHE1F2j$NV;$yi++mG}pLGFFi@|3Tf_MZY3@O GNq++}Qd{W& diff --git a/src/icons/skin/build-icons/icons/filterinactive.svg b/src/icons/skin/filterinactive.svg similarity index 100% rename from src/icons/skin/build-icons/icons/filterinactive.svg rename to src/icons/skin/filterinactive.svg diff --git a/src/icons/skin/firewalled.png b/src/icons/skin/firewalled.png deleted file mode 100644 index 9a1ef3425cb7cf4f3ef1aa3dfb03fd69882170dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2277 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 diff --git a/src/icons/skin/build-icons/icons/firewalled.svg b/src/icons/skin/firewalled.svg similarity index 100% rename from src/icons/skin/build-icons/icons/firewalled.svg rename to src/icons/skin/firewalled.svg diff --git a/src/icons/skin/paused.png b/src/icons/skin/paused.png deleted file mode 100644 index dd99800511c1b3622f6e79cfc17202d25bcb2190..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 745 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5FnKt;1l8sr2jWG{BN)L-%$9! zHUCdT(a*-BpACh-8j5~30#Whr#=_qXg+GB@pcI${Ng*MiEE2aEi49dIwq>gY&>Dr3 zAirP+4nZMtpU{Ye)coR_mbshv9XfpJ%FV|wUcP?w_QRLoe-v&mRA69W67_U(45^5F zd)d5?*^$T9@szjn`@Khg&o62|+9v&l;cnnw?wSP-Z6by-@ABrax%j;F))%)n zy7t+ZnWokHi_*Kxuf4JSD=np0zTN-Yi)#Bd$1d*v_^RN4TCd&qyG0T~e;B%Ns~=c? RP|OPy=$@{AF6*2UngH3V^QZs- diff --git a/src/icons/skin/build-icons/icons/paused.svg b/src/icons/skin/paused.svg similarity index 100% rename from src/icons/skin/build-icons/icons/paused.svg rename to src/icons/skin/paused.svg diff --git a/src/icons/skin/queued.png b/src/icons/skin/queued.png deleted file mode 100644 index 873672939e982dd6c5ebc48aba10e17bc1b5d2cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4505 zcmeI$X)qgJy8!S635{K2Euu7tQcF>^b}6EWpmwzjs@2lJy|u*>wWXnIYs9_||gbxA$0GRdl zbT9w_@NWnNFwp+(yvi-j003G5`j#2;?+|c$3J41Wl$M_P;>DQ+!kLMQXU4~$85ehE zZ0wmaF=s|c|F<~YS^Qr{MV-a})5yrP%>QOY#M$is#qjX63je;r51%*Y$C8cHM6_m=V>Q^0^0~0Rl)_n4O*6%m0#uYo^ z8t=SV-77mokAX)qdo_KNM>_{+TJy1Jd3u!KA14nv_YJTzG!Eu?+nhWST=opevLAIC|e!lw?`a$j!2 zYNw0p?+@OG-JzYj^jWItv=^2XsSXw>6#U1Q6(%3@Y`i#2FkZYSdcjmIb6lhpV}ZHq z4tvF>N^6W!zq~Ahnq4q4hzS;!7{6OoC;_XRZoVF0T*>)px|(Y1x%Po&!)(IVld`Y7 zfnI4InsVlP`*04CF`cxzanmi?ZGT@Pz|k+NaP%u5rKWIDNUX8V^|oRHW{95h%0AyQ zB63F93z%T445d`tlY=E#DR*{1&eO|X9jNsBMz*SPtDvlpd-ZRe^LD_|hTeD{330p3HwVXLf3i^9pn;(tSP;pAP2RuWz8(A&U)<*Vz^eZ+T}G!~p% z*3kP1g2wBT3vGUq@^qgk1ai-FmOZg&t+!20wb6{}y^k|({;))yx;Y#}y8|27b4Lx% z+&T&wzg=H^mEY_1+o0d9S+G*dAI>!uWd&Y}UeCBbJxgKRyM~tj!nyOFZ3-jaE7+;R zjH)%zxT$;r*Z1KS?eSePM#TwT8(~Jw^t-1OwJYaF2bJ}%EBfQa%3p?RXRb#HJlY$K z{*xlRftp=?IF1QX7_z$mB^r*{z%

x*7`;6UdFnp);~8Cp6>L&{CB&ld<1%8}@U< zwR394aZ^ZhT{$++5n8yJ#Q+!Tv9|eT0=ty=YxG2+rFes~mI9}<6u^3l^pfSxezTeH zC4nyrwZu{h745q!!*{W<*cHFz()w=A#pQ<*fdyc)w5zK5F+^@eMI!Kf1Z>u~SbP*B zEK)4&ryj!5Q%F`w){`Pd`1-f0w-l1E3ngoVT#u)VWX+z5DOpdTK<-D>J9))!!lloW zb>H~%`bZvxzwkYA{i)4-V}c$+FiG$rmhm%mAKC|WAOz=^9td4{{`KwChwU?#dBXO^ z<(xzpQ)Ct5%8Ej-VYF|{d}mG+L4(CylKNvCJw^a6*w1#_<1+Sl%+OzGp1UFLdV2HQ zRwZ+P2qzOG&8pa*E2cZq6LJj!ei8+?fu^=72kwGi7419#4+_-RSp7m0%L(``Zeh)8 z&bXR8gu!wNJ!bq-Nb>YISuVRYK|}IB*O}OrD>0%7!42fv0d8o#2}Y-$5Hrp((^{4x z>Vf8gNm|$E{FuVJK+u(_csqk!pKDlNz@F(U()KP8_bS%|;3ZW6@tW0oWPtc>NT2}w zDc@URW7W_@*;?kXG2$VByXqekw~B%XVIA#I$Q>oFhH$x=719I1cg+%AX$F~>a?;u> z088!MihZ??>@*glJZnFNpyhpcO{GukHz1&OGNFwhPb~0+3DpthGB;GubwUGK#_6f1 zP|xxc#$v3SMi{Y%$cuYoB`FZO2-8sGw@&y)XN1m=X9rqGBQShPPnL~R5@dt{x6z{7 zkE}+Uqv?7`A5Hg*5{NyED&a$-ezV;%in{^^VNoeH)k>9Oa26{th=d8bS|@v-WsFyAQ)7&c1 zyA0UFkXsyqhZq;OuouwSAw@}zYzDX}Fd&W>f<*ba z9aP}&zy$FWN87MlsHiy~DL5Z5H%SC(-CKAOm-Yb2AxvCMV26&<%+XAX!`D-!8UhBX zfR|_|;ha2;`f%VRG_mVcBm5i~9FW5ipJEW+#LTq81Hb(qT>P4cXPTR688ZQ0#5#mE zA*uyp#QQs_fMY~8Obn6yHm2^-U*EI)A0>2`gNouRpG6#?m&K zj9z6J%pqrW`P`F7-lT27Pkx6b>Q})hBQB(wxdi^7DCEn`W4*1AdseMA;Rt#>wckvmqhQn-!Wwaia*{ zLiA68;lZCR?F`|OMBb!d^BAW}(0L{@I(V2qUKt>|59{Tx+Q^P(N0r9_8!?NZkUm}L z0dRW{j63|6E>uxNYAO>UDxZ(}rO#|Kuc&o9JFju&5Fh;LwoB;c^${l4?3KD7HDxsm7p9aT_=-N3vsg{ z{=@gA@6N>-dQ?SH_&q`rS~5MNv?6~<9@}L-)5T4Hnt*Yf5T$iSaC^iUye}BqyxFfG z1p1LSN4Q5CjppmuZ5J`?XMSE!aAK5NBzJ)&dOBVGo}yPBv28&(iGc^okZ%yyXhFdu zyuXi?hbBICCyHgg2(RaEJIUY6Y0G#z!Ar)w7T;W(BVHfjdc5MFC?R3p)TA3a$ak`A zdXx8{#y(sM1sZQN=5;Tb#|q4pI=^xL+NMt1XJRON$-V#|k+bn(1669}tw}byXij8~ zmM(v9W|jedA#29*cvNe9Fp{^r_>V%pUeJIyBitIT!*g;(!Lp))`qC!RIN%0ovcelPhorEDHn_rifV z?W^O|xKZGT%S$~slw6v1+!fWwA-i-zpVT#D(z>Z7>0g(IJ}Y1A)-uWd*eSL+dPt{a zF=wY@QR_C4u*rrJ+#eFV*yvzm*KpBM%Fg6nU~6&a^2|e;3hBTovyHT-Ete>EFQQgI?FK9MmpO`klH>I~V_V2bXJuB)XMlZ$DdiWSu zs1M2qdiaXhMPL)-8v!_YUxl3tL9mwfSr2r&L`e@n!LemW(QzNDpJ zFF?#y;E_c#P`Xo9w>fl#Pq3+o$oD}%YJoClXqTE)&jwQ9MjIbB3ZvwHm*m3rV>1eW znO-ZBV>cXG{u@r*M57yyP_|tMboQ9lN1}WLbNU`f8DPOj^RaLu&vtSgm?lhEw2i zaF+n{15n9?Z^!-HtCDVYkk?XAB+7IJY;%|G)TdiZexK~GcTL0?anWmEYUeCC(B1R4 ndA+F&bUf!=_#$;{q?IYa&@22{#f*pMmiKNhlqaxww3Su diff --git a/src/icons/skin/build-icons/icons/queued.svg b/src/icons/skin/queued.svg similarity index 100% rename from src/icons/skin/build-icons/icons/queued.svg rename to src/icons/skin/queued.svg diff --git a/src/icons/skin/ratio.png b/src/icons/skin/ratio.png deleted file mode 100644 index 9665d69de7a14ef2892c8ee958a90525bc5bbb46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1991 zcmcIlX;c$e7@c51mV#gvv zh@erd)*^@)N)g210znPg*byoSYSp0P5~2a=n*`gQ{_mV~&%FD6_q*@ToLSQ8@Jd_j zZ>%8*vJDC(uZAEDSYjZ{G2pbbXk7>dnFZ0QAu9kK8G%L;6AKHO(nLSGD6*-L*^wRi zNbFaa#gvPvs*Dv)d}eDtT%R2%7crHbV2yy%l*er0(Lq;{9jFp8G+bH}f0bOsPzovP zY(^sz+$5ql@K-5?!Kxe@&^Kn&oA@*Z=n7y>4z&@XD}=C;Pg4mfYF@Agp(**nD$o+p zH9S};q^tNaFj3~v)B@0@DtW<51XlB@8Ud^X6oFL;T2~=76_2XsgF&Mk4`^r_J`BcD zTLDc4rVy$IY=l;5KnW@;gsKLE2u+Q80^ zD+#NpMan5}Xi#1<>lO zV0VU`9$}=HgOw5-u3EuP z(D@h!nn&gi`}K9HJ(Dq$(gs?O&8xL~cok#MfbFe37Iq)YnYr@B0nDl=P9kayIkzu=ZJ@WiE>Mh}Na;BpD ze)+nFJG`h>a=V^-L0j#K=-#p*v)oHH>Ah>MBD~Yy%zSMg9X*^O<{`(i6T0-v*G0H< zQ_JH&asWdsDmgL^OUmM< z^Dqg9N>GlN!xFQw6bwy6IZ{GT%*7}wL)lU`VSxt;n=9tRKvYWD*)ld)!i8Q4i3BMJ zlVV&MF@Y>c!hsV)EF(gQvxG~qN-qIr$|y*wlrRb^VU$t;ji16l=O`Dc3aH1bT&lgJ z8ey+npM<-_&H+K(D;UaI5kMGiDe*S?$D_4bthOG(zHe&sTjZx8? zx5mWA#qZdOC+OkNclId;VhJ<>0HK*Kghqzk5G2 zj6K~10Cl3k+0i$4Wq11ni`~d%x97D_CkHz@p%X~rOf!L*hpr%SubBY-A+yvOH9}E@ zQrcg|&+20>mtU*e(=pVwcqFy(eR*IHN8h?)i8e(ur>tQMgTY>ZZo7#f5i!1>_W+#iuKlIBSA*k>fM-?@iMggfXYzCreiLzz#SH#5S zfIj&|ZTT(BPN09F5jrXtFJ$uXy?T=k`i|TTArzXX!IT(U&;TrAzdFMU5*kp(K{119N?d%PM@#_Z19z8|Q zm2Avkm~yvWkf0l1o<3ss_F?brdcg8tu8)I`(~6&Pknq&kKn$dVVfy^fek%t@#UUc>G;#|Y~pD?z#pCIj`6ecDj_m?_` zfUQv&-xSk{N-&sP6hNnwe|4C}u&zHo@c7ZX{=C*%hr9Yt6=Z-~k&yJ#)lTQxNO$JD zhO3p0Q@X=rM(*b3vjPIzQWsP#ZRL{`cG+Mn9pkScYl)OF147iKd6*LA%F7f(`!6eiUb`#2?}R@)F`Ts=YvC zc4QHSmK{z125*m<^*gAd+3-so@4V@-^PBgsnzo^FcwYpl+}>?Os~Q|+cFtt==@0ij dE<5}rft+a@o9u~vcar%37r1yimpBFQ`U|Jv09pV5 diff --git a/src/icons/skin/build-icons/icons/resumed.svg b/src/icons/skin/resumed.svg similarity index 100% rename from src/icons/skin/build-icons/icons/resumed.svg rename to src/icons/skin/resumed.svg diff --git a/src/icons/skin/seeding.png b/src/icons/skin/seeding.png deleted file mode 100644 index eb51988366bc563f2c5ee3b9792eefd4fa37128a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1851 zcmcJQdpJ~i7{||0kwT#xZ4*t1uCx}<*2!&+=4zNy?MBvWtxHkabQ`*fVlZ!&vTOKRBuBA za{~YX41I{63;@8PTO6RTi@w5(1N;F%XB(aD?}dg40w63_Q4#YI3l#A~TZ)(+>BOEK zur7ru;*+Hpy;``;b^-NyI#I-DO4u|xkJOUQY~#?;tT>%0<@w6fC@tLWBEGLAlO#*` zZH8zqd~y?ayCjn)&7h$E=5%@smm)^9JgPi{+ziphnN$gvBIS`}9GV=WNVqg9n&MC; znRFSCf)eBqS;C=7AgY{4l|W=U7u!oUx)h>FIb<0ZOQDLCLzQtUG9FFNMV%BWmn?-a zMardOa2^EOK?_ku3Xx@~8KTHAGgUg1MLAeXQ-YRbG%Q37pLNu!@nedXpmkzZ zSkoB-3e=2&g&Oe_4eNysthH%5+Nm^fO;*!dW77~m!7(hF`V80TGZSJ*n6aVo&&R|# zC_&qC=A_yaVPj~nLYw{XJLV+Lq5<5`VBog%%J)KI33+tv*+mP&o!7g z-_Xc-!9o*Lvqg)SEL~=?{EHR%m6lek2&-*u*Vx&wUAKPYrp->yuHZH|&u_MqD0GIO zKXYfmuHAdS{cdkia7gHnKSe|xjE*@R8+ZJ~Nmjz?Gw04HCM93Il*&%afOwa)1Xr%+ z{E~OA;CkVWqT-TUrDf%}EACcS-Me4?;Nc_TliH`x>gpSQ7d43`Qh9T0Tlv zcK7u5z3LwrR1Ccy9vK~f^XJ67zdlU#Mgi;VOaV)@T?{JjDcN3c)cvb}h9`~LRfmi%r=*MtM`1y^OUSu`+}H)JcngYj@v9E4A+Fa1U3!6ovMlI7RNn&TpM+0 zKQ1)cxEHOB%qM<#_bK1t<)Q0bD@95!RT1@KpaJMOLwDxH# zw}$kS#&26$5Qa9Cn%5f+2m|<#bA+{b@UB?4JXN=PI1qN({VvU;yJAD^MS=^Xok2om zcLYS}=9ms^OrBeU1I*(49IY>htZ<9bwHOw!(yw~vcppETLz9lEEg@G+M z5s_}yo&2DSo8#LFc5TifI8lD+13v@dp~cM62vY#o^Q{_Ik>cyi7ZrrVQEzf2NR(b` zBoH4D0H^ZyCmc9(DR_N&r<;FF<<1o2J6jK2T05~E?JvX`_MQ?=m3M5xhVk*DdX~5c Go&EdoL${L`~rf*Bch_? z6OxisGBUGr@(YVgsvBF|+B^FuOrA1*=B&B%mMmMdZvEyhTet1lxogk<0|$?uID78W z)oa&p-nxC~?t@29o<4j2;^pi2A3lEh@$=X3KY#!I7dczYz`#7o)5S5QBJRzVMmOdJ z5r>Dpip@bGD_evXNG#ga+PZMX3f4tRJVIB`)c%x9`hWClx!l9UFPCgHubTJwNRaNn zxcu|x)~dJXx~+a!_KLAY|JlWL?=NRD?DgD|8^E3LR88vp?s(3GzpAso?+j&6_^K>a z^?Lfx`?X6m=W%a$^lwY{%@av@N=IZ>wV<7~%GGH10+7cy+qcoeXO zt8j~m(A3rp&oAfR>A(MQ|MR=KljlD8Rondf(}sT^8a@?1i(hMF+H&gBuc+K0`-qBf z`@a|3t#^DiQ*f5B)|D5Mi$W_Bc4qeof1O=xd}7rnuj^`={o3jGbxN1I%{x=HG~}v@ zsH)U5%Ya8GOvJsm_!KWcvNzMpYtO7_uAP0Ec~dJ4&aM=izU*e;qYDN%dxW~%EQ7PQ zpd@v-jZbKQ|ixJfkss()h>6`i_0t zbNPQ;WP?6Gp8kKMT*U0#yO&)~DmWX~{`&9FD*N}-{}%mO%RgN{%q*OO~x!w|?{1Z98}E*?-{R(GzFSUAlVh z`psLn@7%rj;L($(&z`@0{r@FZG+6iG${T=^YzvwTj7o>yG zo&Vl?vRjR0+5=_mbyQCGMlMym!j=;_Z%1TjnBuCXW}Qi`5kk3T_x7G%{(SrXyE`PG zf9Bh_{P6y>F2Cn?ezO*STdsENz0a2WGc)!ZU#v@C^!FSA3F*7*_Z+w;Zu&+!c&Wdr z^@)I*Pb_GYlIiN&q`6_?QO72uU4Qis{cq&6+3#Jk z?E72Sx{b9pRyUVaYB@CKfeI~pfCK+|;np1Rl{=6x&bsRybA(&#xz7yq7CX6DGE5I# z_|ISJK-`oUn%oamvq~nh7D$-Bk}GCN3tW28o$Wxi{i!XVugN8t_BiF<-O3gr@3OLL z^D&0W8e!(SmhAh^EsA?wY245rI3?%*tJ0r)AO8Oxb0_|dTU5QSOZaWGrP?AO`#oL# KT-G@yGywqY%HBx; diff --git a/src/icons/skin/build-icons/icons/stalledUP.svg b/src/icons/skin/stalledUP.svg similarity index 100% rename from src/icons/skin/build-icons/icons/stalledUP.svg rename to src/icons/skin/stalledUP.svg diff --git a/src/icons/skin/uploading.png b/src/icons/skin/uploading.png deleted file mode 100644 index 2a449494728a4f2ac69a649f97ff44f7fc2dd474..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1470 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911MRQ8&P5FjTnz$e5N$Yo&o-_YQ6HqD(NP-LjGJtBp1_IRs&3^zSLE;%e z^uQ?ttQTbLL!dZF5NK5914oboh{{J!ATxpD4?$ML^@7+BK^il2bA=vvTqai%Y5-TiV(?`zB1DGJWQ(x$~ARTeEKc=B?Xy?%K2e zz`>&@&Yrt;_1g8Dw{G9Ld+))cCr_U}fBE|ThmT)={QUL%&)&zzjA$FCIf>5L)*$(7I%vM7#>E+mh2Pw+x;Tm<-gJ|@r(OA z{<(h9UsNwh2cbLvz4c_b8p*T=%Gm3uobHWWs&<7fCve`5$j&guRZGn}lUgH$a?9@R zJ-z(-_WgHvNIw6}w{Q93{byZ%&+YtXE&R4z?bdsrE%#?;>^Htxm%ixlIRX;Wch~PZ za82CwjdJi(e^Kib0X55e&I`3YS*Q7=kZ)zISEhpD&4p7A3M~rlvUD$TG2C0p5+1U- z{Xt{aIf0Uu&)5!XU)`gyWAQA#Cbg?~lq{Cb@@6qzW$6;IWEN9Xr+QYVVxfa>s7g_; z)=MA7tv}opUrU6&3qGc~=?a_3#W`-vvigOj?#+*=e7664;l`f%PyLVmVflG8USmye z-jpnU_+mxj?zTl64=A2k&?Y6*)wM};!@{GEO-8%^ z>K*#u$Y-?B U+h$9(ML_m@y85}Sb4q9e0KlZ0q5uE@ diff --git a/src/icons/skin/build-icons/icons/uploading.svg b/src/icons/skin/uploading.svg similarity index 100% rename from src/icons/skin/build-icons/icons/uploading.svg rename to src/icons/skin/uploading.svg diff --git a/src/update_qrc_files.py b/src/update_qrc_files.py index 8fda40e4e4..ebc2504159 100755 --- a/src/update_qrc_files.py +++ b/src/update_qrc_files.py @@ -75,7 +75,7 @@ if 'skin_unused' in dirs: dirs.remove('skin_unused') for file in files: - if splitext(file)[-1] in ('.png', '.jpg', '.gif'): + if splitext(file)[-1] in ('.svg', '.png', '.jpg', '.gif'): icons_list.append(join(root, file)) output = ''' From 91775b3966988985c52d116e81e4c5a4a29e56cd Mon Sep 17 00:00:00 2001 From: Eugene Shalygin Date: Sat, 7 Oct 2017 21:43:22 +0200 Subject: [PATCH 6/6] Use "speedometer" icon for rate limit --- src/gui/guiiconprovider.cpp | 47 +++++++++++++++++++++++++++++++----- src/gui/guiiconprovider.h | 5 +++- src/gui/optionsdlg.cpp | 2 ++ src/gui/optionsdlg.ui | 38 ++++++++++++++--------------- src/gui/statusbar.cpp | 4 +-- src/icons.qrc | 2 -- src/icons/slow.png | Bin 1375 -> 0 bytes src/icons/slow_off.png | Bin 1414 -> 0 bytes 8 files changed, 68 insertions(+), 30 deletions(-) delete mode 100644 src/icons/slow.png delete mode 100644 src/icons/slow_off.png diff --git a/src/gui/guiiconprovider.cpp b/src/gui/guiiconprovider.cpp index 0ba413017f..047fb73d2d 100644 --- a/src/gui/guiiconprovider.cpp +++ b/src/gui/guiiconprovider.cpp @@ -39,8 +39,11 @@ #include #include #include +#include #include +#include #include +#include #include "base/preferences.h" #include "base/settingvalue.h" @@ -54,6 +57,12 @@ #include #endif +namespace +{ + const QLatin1String speedometerIconName {"speedometer"}; + const QLatin1String speedometerFlippedIconName {"speedometer-flipped"}; +} + class GuiIconProvider::SVGManipulator { public: @@ -109,14 +118,13 @@ void GuiIconProvider::SVGManipulator::replaceSVGFillColor(const QString& svgFile } GuiIconProvider::GuiIconProvider(QObject *parent) - : IconProvider(parent) - , m_coloredIconsDir(colorizedIconsDir()) + : IconProvider {parent} + , m_iconsTemporaryDir {temporaryDirForIcons()} + , m_coloredIconsDir(m_iconsTemporaryDir.path() + QDir::separator() + QLatin1String("colorized")) , m_svgManipulator(new SVGManipulator()) { if (!m_coloredIconsDir.isValid()) - qCWarning(theme, "Could not create temporary directory '%s' for colorized icons", qPrintable(m_coloredIconsDir.path())); - else - m_coloredIconsDir.setAutoRemove(true); + qCWarning(theme, "Could not create temporary directory '%s' for colorized icons", qUtf8Printable(m_coloredIconsDir.path())); connect(&Theme::ThemeProvider::instance(), &Theme::ThemeProvider::colorThemeChanged, this, &GuiIconProvider::colorThemeChanged); @@ -143,6 +151,10 @@ QIcon GuiIconProvider::getIcon(const QString &iconId) QIcon GuiIconProvider::getIcon(const QString &iconId, const QString &fallback) { + const auto it = m_generatedIcons.find(iconId); + if (it != m_generatedIcons.end()) { + return it.value(); + } #if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC)) if (iconSet() == IconSet::SystemTheme) { QIcon icon = QIcon::fromTheme(iconId); @@ -234,6 +246,8 @@ void GuiIconProvider::update() setIconDir(IconProvider::defaultIconDir()); } + m_generatedIcons[speedometerFlippedIconName] = flipIcon(getIcon(speedometerIconName), true, false); + using BitTorrent::TorrentState; const auto trySetColorizedIcon = [this](BitTorrent::TorrentState state, const char *stateName, const char *iconName) { @@ -298,7 +312,7 @@ void GuiIconProvider::decolorizeIcons() } } -QString GuiIconProvider::colorizedIconsDir() +QString GuiIconProvider::temporaryDirForIcons() { // TODO Application should create QTemporaryDir for /run/user/// // and we then will be able to create directory "icons" inside @@ -322,3 +336,24 @@ CachedSettingValue &GuiIconProvider::stateIconsAreColorizedSetting() static CachedSettingValue setting("Appearance/StateIconColorization", true); return setting; } + +QIcon GuiIconProvider::flipIcon(const QIcon& icon, bool horizontal, bool vertical) +{ + QIcon res; + const QList sizes = !icon.availableSizes().isEmpty() + ? icon.availableSizes() + : QList{{16, 16}, {32, 32}, {64, 64}, {128, 128}, {256, 256}}; + for (const auto &size : sizes) { + QPixmap px {size}; + px.fill({0, 0, 0, 0}); + QPainter painter {&px}; + QRect bounds {0, 0, size.width(), size.height()}; + QTransform tr; + tr.scale(horizontal ? -1. : 1., vertical ? -1. : 1.); + tr.translate(horizontal ? -size.width() : 0, vertical ? -size.height() : 0); + painter.setTransform(tr); + painter.drawPixmap(0, 0, icon.pixmap(size)); + res.addPixmap(px); + } + return res; +} diff --git a/src/gui/guiiconprovider.h b/src/gui/guiiconprovider.h index 700aad228a..522032268f 100644 --- a/src/gui/guiiconprovider.h +++ b/src/gui/guiiconprovider.h @@ -89,13 +89,16 @@ private slots: void update(); void reset(); void decolorizeIcons(); + static QIcon flipIcon(const QIcon &icon, bool horizontal, bool vertical); - static QString colorizedIconsDir(); + static QString temporaryDirForIcons(); static CachedSettingValue &iconSetSetting(); static CachedSettingValue &stateIconsAreColorizedSetting(); QMap m_torrentStateIcons; // these icons are needed frequently + QTemporaryDir m_iconsTemporaryDir; QTemporaryDir m_coloredIconsDir; + QMap m_generatedIcons; QScopedPointer m_svgManipulator; }; diff --git a/src/gui/optionsdlg.cpp b/src/gui/optionsdlg.cpp index edabb7da8a..f7ec1abce6 100644 --- a/src/gui/optionsdlg.cpp +++ b/src/gui/optionsdlg.cpp @@ -210,6 +210,8 @@ OptionsDialog::OptionsDialog(QWidget *parent) // uniform size for all icons m_ui->tabSelection->item(i)->setSizeHint(QSize(std::numeric_limits::max(), 62)); } + m_ui->labelRateLimitIcon->setPixmap(GuiIconProvider::instance()->getIcon(QLatin1String("speedometer")).pixmap(32, 32)); + m_ui->labelAltRateLimitIcon->setPixmap(GuiIconProvider::instance()->getIcon(QLatin1String("speedometer-flipped")).pixmap(32, 32)); m_ui->IpFilterRefreshBtn->setIcon(GuiIconProvider::instance()->getIcon("view-refresh")); diff --git a/src/gui/optionsdlg.ui b/src/gui/optionsdlg.ui index 0d35bc3323..4b6cc65012 100644 --- a/src/gui/optionsdlg.ui +++ b/src/gui/optionsdlg.ui @@ -95,7 +95,7 @@ - 0 + 4 @@ -127,8 +127,8 @@ 0 0 - 501 - 893 + 549 + 540 @@ -917,8 +917,8 @@ 0 0 - 591 - 1138 + 623 + 1213 @@ -1491,8 +1491,8 @@ 0 0 - 501 - 745 + 535 + 816 @@ -1994,8 +1994,8 @@ 0 0 - 516 - 525 + 549 + 540 @@ -2059,9 +2059,9 @@ - + - :/icons/slow_off.png + :/icons/qbt-theme/speedometer.svg @@ -2206,9 +2206,9 @@ - + - :/icons/slow.png + :/icons/qbt-theme/speedometer.svg @@ -2361,8 +2361,8 @@ 0 0 - 513 - 679 + 552 + 680 @@ -2836,8 +2836,8 @@ 0 0 - 516 - 525 + 430 + 259 @@ -2986,8 +2986,8 @@ 0 0 - 501 - 636 + 470 + 616 diff --git a/src/gui/statusbar.cpp b/src/gui/statusbar.cpp index 3fcb105023..19afd82f81 100644 --- a/src/gui/statusbar.cpp +++ b/src/gui/statusbar.cpp @@ -231,12 +231,12 @@ void StatusBar::refresh() void StatusBar::updateAltSpeedsBtn(bool alternative) { if (alternative) { - m_altSpeedsBtn->setIcon(QIcon(":/icons/slow.png")); + m_altSpeedsBtn->setIcon(GuiIconProvider::instance()->getIcon(QLatin1String("speedometer-flipped"))); m_altSpeedsBtn->setToolTip(tr("Click to switch to regular speed limits")); m_altSpeedsBtn->setDown(true); } else { - m_altSpeedsBtn->setIcon(QIcon(":/icons/slow_off.png")); + m_altSpeedsBtn->setIcon(GuiIconProvider::instance()->getIcon(QLatin1String("speedometer"))); m_altSpeedsBtn->setToolTip(tr("Click to switch to alternative speed limits")); m_altSpeedsBtn->setDown(false); } diff --git a/src/icons.qrc b/src/icons.qrc index 3113624e20..0696432143 100644 --- a/src/icons.qrc +++ b/src/icons.qrc @@ -372,8 +372,6 @@ icons/skin/tabs.gif icons/skin/toolbox-divider.gif icons/skin/toolbox-divider2.gif - icons/slow.png - icons/slow_off.png icons/sphere.png icons/sphere2.png icons/url.png diff --git a/src/icons/slow.png b/src/icons/slow.png deleted file mode 100644 index 0d978fc708bb5b2877e5f7b2acba6722636f0299..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1375 zcmV-l1)%zgP)ZbLql}^`t@NV z`eEn10sn>Zi=Se)?V1Y4ovtpqiAmRbdwYrD2?m403qqQko1@2%AJgFAAdQcY)AI7N zBoBwfB;aSXwY3pjB@ty~2Ye3y!ow?H#|Yoi(V;zi_Kdtq@;u{U%pHNZns;IhK2lm4>6+G*Vkj8BYN80SZHtlj=F)E z+ueQ6)wOl!+Ulw}NMBvNNLf}Z)z#HeOG^tiH8oK~Lj#>TbB1baYUuRo(^OSeMd|73 zl$w@CeSLkjxw%Oj8yi9iKi6E6K1b*$vJ9Pl-+KR(qcr|~J(W^qC@O$9*o$B78b(+s^)YKfewqe%RSMgT+6AX3SL3DB^-pNhC$MzPa z*#7{GQCM`kz_mpTXJg{5EEWr*qN1cXnM^WMm9w^5t*EZ40Yj*uo0^*PaHh7LoSdL) z-M8-=5kcUK^IzhFcPsFF#u2o2^Z+g&UVI@D?`gO3QQvu_O?HFKaWL}bCW9VEqY)7i z5#mzm4F&^@Y(ylL;QEP21euwcW|lRT6|t%d3k#VdDyODlZgvJ4>FIF%HI449BWQiH z#H3qLB9oA4aHA%20H50$vDYzyfMNitI)DI0k(H5N&xAaeh~Qvu-n=QZPDn^l78e$j zSq?&F-Hp5hYYqo??cNOz0A8OT*~&49;`@TLyr1=1`5d=~l*bqiNvS)D~N z6hMGw=1vqu(i4%)nja7GEiJ&NQ`MhTkJk%kCi~N;Qli<}S+b6E|=>Sjv#`g3$lNM2Nz3AOL7F3S5|nB z3-NvzYX7_%_M3F-H}QvQWzRk(F+Nrj#Kgo%V=~dPQc^}guj#p=d_1RPJcp;iGos*m z2nnoQ+dL-AXX1SRyUAaipMPy&QA-`^>7<{3yc+HsxKDQ5^a*bFLu~o;^Yi&!f4QH7 h&tnO#_y_oR>^W6Xd002ovPDHLkV1iH&itYda diff --git a/src/icons/slow_off.png b/src/icons/slow_off.png deleted file mode 100644 index 930663e7899f121adf9f308acecb5f88c21234e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1414 zcmV;11$p|3P)+z*h;IKSgp}$(nQmT)`T`OeX;btB=)7RHfc;- zlP3CNjJC#jYp5!rZLk6YK??{7!Y;52?EN}BbNZjL8k;ojNhWh~+1b+F-TidmzI{&;i3Bec3d}GJNRk9aQQ&g9u&}Uj%>vxSFUinKB33W&-bNuFEAJY{4w|tiRhBLt7W_1(a{mBt*v#Jl$3By(^xv4 zMtgfZdV70ex7$(b^MR3^#0=4B)ROk-(W7W>ZACJfgs@^{WQ5Jl&0+WM-5yd$^7(wx ze*z8+DR0zoD%`krC$_b|&IEXg+wI1wQ>XC#nKL+i=n%*sYeVwK0wOYCj6oDcMS?iu z+}X2eY;3gN&CJZ`@pxQqZf^F_ckvg1J%5g|*K5}E-+KGQt12s(*=ec6<>CkSzALR; zzaBex>_m7W43bZT2_&EJ2dPvFQE3c``Sdw12aG{^5SE{roH-E;f z8){(8PVi7~7qbuiI_;>cEtW4|zT8k*S=mk-s0*Qa?fR`d#-RiI^V4%7gS_CppzDmA zs*q90S|ETT3XiI)P!$DCdd5!YK%O%&(?H{@6}W%(BHl`kqBK0gGRY*@%2pNCeD>9H zWn*>qxkUV#r(d2ti9PSM$icaglu9Oa$uu-FjpZl=LROua%0fP3ClgR!l982E*o+u< z6&u*1g|K1A7OX%H_SNgKl*%JhQH!{J1&_%^a)rs_70?Ay^%$GUtF~vM7z*zmKVzfUG1F3C&CGX)zo|nct7#>@4DxJPDko!5|pr^93#eENv^s z$0HZDR|-+)Mxn^1X8@-LXg(AoK}cB-9w$Bc{N@Zg$Aa+K2k^nCZB~jcbtLIWB}rya z1_GQ?$Am946pBnbWqG8KH-@S~QWYkvHtb4GVoQFSnIf?&XQqqMJrC$}h~#|uDe6P} za2l>$5+d;n;gDrThK`8H1F2Q3)NR^yd~AIDG$kxY-Gg7haRbpvM5C%C0qS%*A<0%a z_{Dfa|L{#&GbuQnk&kYUsi+sN-5CsJP0U4l;3%?#dA(S(X0=&axjo-~@16)1Tf26x zjqb-80K{Uk(^Sc8RDq3RO}W&!QA37kPvT&UIY|$bLbCVKS!0JbF9!&-W7$EbdrFa} zV3ZPwi?Tp%%sP+apM=Kmln;g4U5*;SLu!}D+3f5r^ZWh$