aboutsummaryrefslogtreecommitdiff
path: root/src-qt5/core/lumina-theme-engine/src/lthemeengine
diff options
context:
space:
mode:
Diffstat (limited to 'src-qt5/core/lumina-theme-engine/src/lthemeengine')
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.cpp418
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.h79
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.ui243
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.cpp138
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.h56
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.ui160
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.cpp126
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.h62
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.ui134
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.cpp214
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.h57
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.ui51
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.cpp140
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.h54
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.ui327
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/main.cpp84
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp90
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.h57
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui47
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.cpp146
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.h68
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.ui120
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/previewform.ui76
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp85
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h59
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui47
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp232
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h66
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui84
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.cpp115
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.desktop60
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.h60
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.pro57
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/tabpage.cpp33
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/tabpage.h43
35 files changed, 3888 insertions, 0 deletions
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.cpp
new file mode 100644
index 00000000..4183dec1
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.cpp
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QStyleFactory>
+#include <QMdiSubWindow>
+#include <QSettings>
+#include <QDir>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QMenu>
+#include <QIcon>
+#include "qt5ct.h"
+#include "appearancepage.h"
+#include "paletteeditdialog.h"
+#include "ui_appearancepage.h"
+#include "ui_previewform.h"
+
+AppearancePage::AppearancePage(QWidget *parent) :
+ TabPage(parent),
+ m_ui(new Ui::AppearancePage)
+{
+ m_ui->setupUi(this);
+ QStringList keys = QStyleFactory::keys();
+ keys.removeAll("qt5ct-style"); //hide qt5ct proxy style
+ m_ui->styleComboBox->addItems(keys);
+
+ connect(m_ui->paletteComboBox, SIGNAL(activated(int)), SLOT(updatePalette()));
+ connect(m_ui->customPaletteButton, SIGNAL(clicked()), SLOT(updatePalette()));
+ connect(m_ui->defaultPaletteButton, SIGNAL(clicked()), SLOT(updatePalette()));
+
+ m_previewWidget = new QWidget(this);
+ m_previewUi = new Ui::PreviewForm();
+ m_previewUi->setupUi(m_previewWidget);
+ QMdiSubWindow *w = m_ui->mdiArea->addSubWindow(m_previewWidget, Qt::CustomizeWindowHint
+ | Qt::WindowMinMaxButtonsHint
+ | Qt::WindowTitleHint);
+ w->move(10, 10);
+
+ QMenu *menu = new QMenu(this);
+ menu->addAction(QIcon::fromTheme("list-add"), tr("Create"), this, SLOT(createColorScheme()));
+ m_changeColorSchemeAction = menu->addAction(tr("Edit"), this, SLOT(changeColorScheme()));
+ menu->addAction(tr("Create a Copy"), this, SLOT(copyColorScheme()));
+ m_renameColorSchemeAction = menu->addAction(tr("Rename"), this, SLOT(renameColorScheme()));
+ menu->addSeparator();
+ m_removeColorSchemeAction = menu->addAction(tr("Remove"), this, SLOT(removeColorScheme()));
+ m_ui->colorSchemeButton->setMenu(menu);
+
+ m_changeColorSchemeAction->setIcon(QIcon::fromTheme("accessories-text-editor"));
+ m_removeColorSchemeAction->setIcon(QIcon::fromTheme("list-remove"));
+ connect(menu, SIGNAL(aboutToShow()), SLOT(updateActions()));
+
+ readSettings();
+}
+
+AppearancePage::~AppearancePage()
+{
+ if(m_selectedStyle)
+ delete m_selectedStyle;
+ delete m_ui;
+ delete m_previewUi;
+}
+
+void AppearancePage::writeSettings()
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.beginGroup("Appearance");
+ settings.setValue("style", m_ui->styleComboBox->currentText());
+ settings.setValue("custom_palette", m_ui->customPaletteButton->isChecked());
+ settings.setValue("color_scheme_path", m_ui->colorSchemeComboBox->currentData().toString());
+ settings.endGroup();
+}
+
+void AppearancePage::on_styleComboBox_activated(const QString &text)
+{
+ QStyle *style = QStyleFactory::create(text);
+ if(!style)
+ return;
+ setStyle(m_previewWidget, style);
+
+ if(m_selectedStyle)
+ delete m_selectedStyle;
+ m_selectedStyle = style;
+
+ updatePalette();
+}
+
+void AppearancePage::on_colorSchemeComboBox_activated(int)
+{
+ m_customPalette = loadColorScheme(m_ui->colorSchemeComboBox->currentData().toString());
+ updatePalette();
+}
+
+void AppearancePage::createColorScheme()
+{
+ QString name = QInputDialog::getText(this, tr("Enter Color Scheme Name"), tr("File name:"));
+ if(name.isEmpty())
+ return;
+
+ if(!name.endsWith(".conf", Qt::CaseInsensitive))
+ name.append(".conf");
+
+ if(m_ui->colorSchemeComboBox->findText(name.section('.',0,0)) != -1)
+ {
+ QMessageBox::warning(this, tr("Error"), tr("The color scheme \"%1\" already exists")
+ .arg(name.section('.',0,0)));
+ return;
+ }
+
+ QString schemePath = Qt5CT::userColorSchemePath() + "/" + name;
+
+ createColorScheme(schemePath, palette());
+ m_ui->colorSchemeComboBox->addItem(name.section('.',0,0), schemePath);
+}
+
+void AppearancePage::changeColorScheme()
+{
+ if(m_ui->colorSchemeComboBox->currentIndex() < 0)
+ return;
+
+ if(!QFileInfo(m_ui->colorSchemeComboBox->currentData().toString()).isWritable())
+ {
+ QMessageBox::information(this, tr("Warning"), tr("The color scheme \"%1\" is read only")
+ .arg(m_ui->colorSchemeComboBox->currentText()));
+ return;
+ }
+
+ PaletteEditDialog d(m_customPalette, m_selectedStyle, this);
+ connect(&d, SIGNAL(paletteChanged(QPalette)), SLOT(setPreviewPalette(QPalette)));
+ if(d.exec() == QDialog::Accepted)
+ {
+ m_customPalette = d.selectedPalette();
+ createColorScheme(m_ui->colorSchemeComboBox->currentData().toString(), m_customPalette);
+ }
+ updatePalette();
+}
+
+void AppearancePage::removeColorScheme()
+{
+ int index = m_ui->colorSchemeComboBox->currentIndex();
+ if(index < 0 || m_ui->colorSchemeComboBox->count() <= 1)
+ return;
+
+ if(!QFileInfo(m_ui->colorSchemeComboBox->currentData().toString()).isWritable())
+ {
+ QMessageBox::information(this, tr("Warning"), tr("The color scheme \"%1\" is read only")
+ .arg(m_ui->colorSchemeComboBox->currentText()));
+ return;
+ }
+
+ int button = QMessageBox::question(this, tr("Confirm Remove"),
+ tr("Are you sure you want to remove color scheme \"%1\"?")
+ .arg(m_ui->colorSchemeComboBox->currentText()),
+ QMessageBox::Yes | QMessageBox::No);
+ if(button != QMessageBox::Yes)
+ return;
+
+ if(QFile::remove(m_ui->colorSchemeComboBox->currentData().toString()))
+ {
+ m_ui->colorSchemeComboBox->removeItem(index);
+ on_colorSchemeComboBox_activated(0);
+ }
+}
+
+void AppearancePage::copyColorScheme()
+{
+ if(m_ui->colorSchemeComboBox->currentIndex() < 0)
+ return;
+
+ QString name = QInputDialog::getText(this, tr("Enter Color Scheme Name"), tr("File name:"),
+ QLineEdit::Normal,
+ tr("%1 (copy)").arg(m_ui->colorSchemeComboBox->currentText()));
+ if(name.isEmpty() || name == m_ui->colorSchemeComboBox->currentText())
+ return;
+
+ if(!name.endsWith(".conf", Qt::CaseInsensitive))
+ name.append(".conf");
+
+ if(m_ui->colorSchemeComboBox->findText(name.section('.',0,0)) != -1)
+ {
+ QMessageBox::warning(this, tr("Error"), tr("The color scheme \"%1\" already exists")
+ .arg(name.section('.',0,0)));
+ return;
+ }
+
+ QString newPath = Qt5CT::userColorSchemePath() + "/" + name;
+ QFile::copy(m_ui->colorSchemeComboBox->currentData().toString(), newPath);
+ m_ui->colorSchemeComboBox->addItem(name.section('.',0,0), newPath);
+}
+
+void AppearancePage::renameColorScheme()
+{
+ int index = m_ui->colorSchemeComboBox->currentIndex();
+
+ if(index < 0)
+ return;
+
+ if(!QFileInfo(m_ui->colorSchemeComboBox->currentData().toString()).isWritable())
+ {
+ QMessageBox::information(this, tr("Warning"), tr("The color scheme \"%1\" is read only")
+ .arg(m_ui->colorSchemeComboBox->currentText()));
+ return;
+ }
+
+ QString name = QInputDialog::getText(this, tr("Enter Color Scheme Name"), tr("File name:"),
+ QLineEdit::Normal, m_ui->colorSchemeComboBox->currentText());
+ if(name.isEmpty() || name == m_ui->colorSchemeComboBox->currentText())
+ return;
+
+ if(!name.endsWith(".conf", Qt::CaseInsensitive))
+ name.append(".conf");
+
+ if(m_ui->colorSchemeComboBox->findText(name.section('.',0,0)) != -1)
+ {
+ QMessageBox::warning(this, tr("Error"), tr("The color scheme \"%1\" already exists")
+ .arg(name.section('.',0,0)));
+ return;
+ }
+
+ QString newPath = Qt5CT::userColorSchemePath() + "/" + name;
+ QFile::rename(m_ui->colorSchemeComboBox->currentData().toString(), newPath);
+ m_ui->colorSchemeComboBox->setItemText(index, name.section('.',0,0));
+ m_ui->colorSchemeComboBox->setItemData(index, newPath);
+}
+
+void AppearancePage::updatePalette()
+{
+ if(!m_selectedStyle)
+ return;
+
+ setPreviewPalette(m_ui->customPaletteButton->isChecked() ?
+ m_customPalette : m_selectedStyle->standardPalette());
+}
+
+void AppearancePage::setPreviewPalette(const QPalette &p)
+{
+ QPalette previewPalette = palette();
+
+ QPalette::ColorGroup colorGroup = QPalette::Disabled;
+
+ if(m_ui->paletteComboBox->currentIndex() == 0)
+ {
+ colorGroup = QPalette::Active;
+ }
+ else if(m_ui->paletteComboBox->currentIndex() == 1)
+ {
+ colorGroup = QPalette::Inactive;
+ }
+
+ for (int i = 0; i < QPalette::NColorRoles; i++)
+ {
+ QPalette::ColorRole role = QPalette::ColorRole(i);
+ previewPalette.setColor(QPalette::Active, role, p.color(colorGroup, role));
+ previewPalette.setColor(QPalette::Inactive, role, p.color(colorGroup, role));
+ }
+
+ setPalette(m_ui->mdiArea, previewPalette);
+}
+
+void AppearancePage::updateActions()
+{
+ if(m_ui->colorSchemeComboBox->count() == 0 ||
+ !QFileInfo(m_ui->colorSchemeComboBox->currentData().toString()).isWritable())
+ {
+ m_changeColorSchemeAction->setVisible(false);
+ m_renameColorSchemeAction->setVisible(false);
+ m_removeColorSchemeAction->setVisible(false);
+ }
+ else
+ {
+ m_changeColorSchemeAction->setVisible(true);
+ m_renameColorSchemeAction->setVisible(true);
+ m_removeColorSchemeAction->setVisible(m_ui->colorSchemeComboBox->count() > 1);
+ }
+}
+
+void AppearancePage::readSettings()
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.beginGroup("Appearance");
+ QString style = settings.value("style", "Fusion").toString();
+ m_ui->styleComboBox->setCurrentText(style);
+
+ m_ui->customPaletteButton->setChecked(settings.value("custom_palette", false).toBool());
+ QString colorSchemePath = settings.value("color_scheme_path").toString();
+
+ QDir("/").mkpath(Qt5CT::userColorSchemePath());
+ findColorSchemes(Qt5CT::userColorSchemePath());
+ findColorSchemes(Qt5CT::sharedColorSchemePath());
+
+ if(m_ui->colorSchemeComboBox->count() == 0)
+ {
+ m_customPalette = palette(); //load fallback palette
+ }
+ else
+ {
+ int index = m_ui->colorSchemeComboBox->findData(colorSchemePath);
+ if(index >= 0)
+ m_ui->colorSchemeComboBox->setCurrentIndex(index);
+ m_customPalette = loadColorScheme(m_ui->colorSchemeComboBox->currentData().toString());
+ }
+
+ on_styleComboBox_activated(m_ui->styleComboBox->currentText());
+
+ settings.endGroup();
+}
+
+void AppearancePage::setStyle(QWidget *w, QStyle *s)
+{
+ foreach (QObject *o, w->children())
+ {
+ if(o->isWidgetType())
+ {
+ setStyle(qobject_cast<QWidget *>(o), s);
+ }
+ }
+ w->setStyle(s);
+}
+
+void AppearancePage::setPalette(QWidget *w, QPalette p)
+{
+ foreach (QObject *o, w->children())
+ {
+ if(o->isWidgetType())
+ {
+ setPalette(qobject_cast<QWidget *>(o), p);
+ }
+ }
+ w->setPalette(p);
+}
+
+void AppearancePage::findColorSchemes(const QString &path)
+{
+ QDir dir(path);
+ dir.setFilter(QDir::Files);
+ dir.setNameFilters(QStringList() << "*.conf");
+
+ foreach (QFileInfo info, dir.entryInfoList())
+ {
+ m_ui->colorSchemeComboBox->addItem(info.baseName(), info.filePath());
+ }
+}
+
+QPalette AppearancePage::loadColorScheme(const QString &filePath)
+{
+ QPalette customPalette;
+ QSettings settings(filePath, QSettings::IniFormat);
+ settings.beginGroup("ColorScheme");
+ QStringList activeColors = settings.value("active_colors").toStringList();
+ QStringList inactiveColors = settings.value("inactive_colors").toStringList();
+ QStringList disabledColors = settings.value("disabled_colors").toStringList();
+ settings.endGroup();
+
+ if(activeColors.count() == QPalette::NColorRoles &&
+ inactiveColors.count() == QPalette::NColorRoles &&
+ disabledColors.count() == QPalette::NColorRoles)
+ {
+ for (int i = 0; i < QPalette::NColorRoles; i++)
+ {
+ QPalette::ColorRole role = QPalette::ColorRole(i);
+ customPalette.setColor(QPalette::Active, role, QColor(activeColors.at(i)));
+ customPalette.setColor(QPalette::Inactive, role, QColor(inactiveColors.at(i)));
+ customPalette.setColor(QPalette::Disabled, role, QColor(disabledColors.at(i)));
+ }
+ }
+ else
+ {
+ customPalette = palette(); //load fallback palette
+ }
+
+ return customPalette;
+}
+
+void AppearancePage::createColorScheme(const QString &name, const QPalette &palette)
+{
+ QSettings settings(name, QSettings::IniFormat);
+ settings.beginGroup("ColorScheme");
+
+ QStringList activeColors, inactiveColors, disabledColors;
+ for (int i = 0; i < QPalette::NColorRoles; i++)
+ {
+ QPalette::ColorRole role = QPalette::ColorRole(i);
+ activeColors << palette.color(QPalette::Active, role).name();
+ inactiveColors << palette.color(QPalette::Inactive, role).name();
+ disabledColors << palette.color(QPalette::Disabled, role).name();
+ }
+
+ settings.setValue("active_colors",activeColors);
+ settings.setValue("inactive_colors",inactiveColors);
+ settings.setValue("disabled_colors",disabledColors);
+
+ settings.endGroup();
+
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.h
new file mode 100644
index 00000000..3a7752c7
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef APPEARANCEPAGE_H
+#define APPEARANCEPAGE_H
+
+#include "tabpage.h"
+
+namespace Ui {
+class AppearancePage;
+class PreviewForm;
+}
+
+class QStyle;
+class QAction;
+
+class AppearancePage : public TabPage
+{
+ Q_OBJECT
+
+public:
+ explicit AppearancePage(QWidget *parent = 0);
+ ~AppearancePage();
+
+ void writeSettings();
+
+private slots:
+ void on_styleComboBox_activated(const QString &text);
+ void on_colorSchemeComboBox_activated(int);
+ void createColorScheme();
+ void changeColorScheme();
+ void removeColorScheme();
+ void copyColorScheme();
+ void renameColorScheme();
+ void updatePalette();
+ void setPreviewPalette(const QPalette &p);
+ void updateActions();
+
+private:
+ void readSettings();
+ void setStyle(QWidget *w, QStyle *s);
+ void setPalette(QWidget *w, QPalette p);
+ void findColorSchemes(const QString &path);
+ QPalette loadColorScheme(const QString &filePath);
+ void createColorScheme(const QString &name, const QPalette &palette);
+ Ui::AppearancePage *m_ui;
+ QStyle *m_selectedStyle = nullptr;
+ QPalette m_customPalette;
+ QWidget *m_previewWidget;
+ QAction *m_changeColorSchemeAction, *m_renameColorSchemeAction, *m_removeColorSchemeAction;
+ Ui::PreviewForm *m_previewUi;
+};
+
+#endif // APPEARANCEPAGE_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.ui
new file mode 100644
index 00000000..cd442930
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.ui
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AppearancePage</class>
+ <widget class="QWidget" name="AppearancePage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>596</width>
+ <height>470</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string notr="true">Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Style:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="3">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Preview</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QComboBox" name="paletteComboBox">
+ <item>
+ <property name="text">
+ <string>Active palette</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Inactive palette</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Disabled palette</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>82</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QMdiArea" name="mdiArea">
+ <property name="tabsMovable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="styleComboBox"/>
+ </item>
+ <item row="0" column="2">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0" colspan="3">
+ <widget class="QGroupBox" name="paletteGroupBox">
+ <property name="title">
+ <string>Palette</string>
+ </property>
+ <layout class="QVBoxLayout" name="_2">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="defaultPaletteButton">
+ <property name="text">
+ <string>Default</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="customPaletteButton">
+ <property name="text">
+ <string>Custom</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>230</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="colorScheeLabel">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Color scheme:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="colorSchemeComboBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="colorSchemeButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::InstantPopup</enum>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::NoArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>customPaletteButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>colorScheeLabel</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>160</x>
+ <y>79</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>77</x>
+ <y>104</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>customPaletteButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>colorSchemeComboBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>144</x>
+ <y>75</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>146</x>
+ <y>100</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>customPaletteButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>colorSchemeButton</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>177</x>
+ <y>78</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>288</x>
+ <y>116</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.cpp
new file mode 100644
index 00000000..398a2436
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QXmlStreamWriter>
+#include <QFile>
+#include <QDir>
+#include <QMessageBox>
+#include "fontconfigdialog.h"
+#include "ui_fontconfigdialog.h"
+
+FontConfigDialog::FontConfigDialog(QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::FontConfigDialog)
+{
+ m_ui->setupUi(this);
+
+ m_ui->hintingStyleComboBox->addItem(tr("None"), "hintnone");
+ m_ui->hintingStyleComboBox->addItem(tr("Slight"), "hintslight");
+ m_ui->hintingStyleComboBox->addItem(tr("Medium"), "hintmedium");
+ m_ui->hintingStyleComboBox->addItem(tr("Full"), "hintfull");
+
+ m_ui->rgbaComboBox->addItem(tr("None"), "none");
+ m_ui->rgbaComboBox->addItem("rgb", "rgb");
+ m_ui->rgbaComboBox->addItem("bgr", "bgr");
+ m_ui->rgbaComboBox->addItem("vrgb", "vrgb");
+ m_ui->rgbaComboBox->addItem("vbgr", "vbgr");
+
+ m_ui->lcdFilterComboBox->addItem("lcdnone");
+ m_ui->lcdFilterComboBox->addItem("lcddefault");
+ m_ui->lcdFilterComboBox->addItem("lcdlight");
+ m_ui->lcdFilterComboBox->addItem("lcdlegacy");
+}
+
+FontConfigDialog::~FontConfigDialog()
+{
+ delete m_ui;
+}
+
+void FontConfigDialog::accept()
+{
+ QDir::home().mkpath(".config/fontconfig/");
+ QString path = QDir::homePath() + "/.config/fontconfig/fonts.conf";
+ qDebug("FontConfigDialog: fontconfig path: %s", qPrintable(path));
+
+
+ if(QFile::exists(path))
+ {
+ if(QMessageBox::question(this, tr("Font Configuration"),
+ tr("<i>%1</i> already exists. Do you want to replace it?").arg(path),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ {
+ QDialog::reject();
+ return;
+ }
+
+ QFile::remove(path + ".back");
+ QFile::copy(path, path + ".back");
+ }
+
+ QFile file(path);
+ if(!file.open(QIODevice::WriteOnly))
+ {
+ qWarning("FontConfigDialog: unable to open file: %s", qPrintable(file.errorString()));
+ return;
+ }
+
+ QXmlStreamWriter stream(&file);
+ stream.setAutoFormatting(true);
+
+ stream.writeStartDocument();
+ stream.writeDTD("<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">");
+ stream.writeStartElement("fontconfig");
+
+ stream.writeStartElement("match");
+ stream.writeAttribute("target", "font");
+ writeOption(&stream, "antialias", "bool", m_ui->antialisingCheckBox->isChecked() ? "true" : "false");
+ writeOption(&stream, "hinting", "bool", m_ui->hintingCheckBox->isChecked() ? "true" : "false");
+ writeOption(&stream, "hintstyle", "const", m_ui->hintingStyleComboBox->currentData().toString());
+ writeOption(&stream, "rgba", "const", m_ui->rgbaComboBox->currentData().toString());
+ writeOption(&stream, "autohint", "bool", m_ui->autohinterCheckBox->isChecked() ? "true" : "false");
+ writeOption(&stream, "lcdfilter", "const", m_ui->lcdFilterComboBox->currentText());
+ writeOption(&stream, "dpi", "double", QString::number(m_ui->dpiSpinBox->value()));
+ stream.writeEndElement();
+
+ if(m_ui->disableBoldAutohintCheckBox->isChecked())
+ {
+ stream.writeStartElement("match");
+ stream.writeAttribute("target", "font");
+
+ stream.writeStartElement("test");
+ stream.writeAttribute("name", "weight");
+ stream.writeAttribute("compare", "more");
+ stream.writeTextElement("const", "medium");
+ stream.writeEndElement();
+
+ writeOption(&stream, "autohint", "bool", m_ui->autohinterCheckBox->isChecked() ? "true" : "false");
+
+ stream.writeEndElement();
+ }
+ stream.writeEndElement();
+ stream.writeEndDocument();
+
+ QDialog::accept();
+}
+
+void FontConfigDialog::writeOption(QXmlStreamWriter *stream, const QString &name, const QString &type, const QString &value)
+{
+ stream->writeStartElement("edit");
+ stream->writeAttribute("name", name);
+ stream->writeAttribute("mode", "assign");
+ stream->writeTextElement(type, value);
+ stream->writeEndElement();
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.h
new file mode 100644
index 00000000..5b7e31a5
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FONTCONFIGDIALOG_H
+#define FONTCONFIGDIALOG_H
+
+#include <QDialog>
+
+namespace Ui {
+class FontConfigDialog;
+}
+
+class QXmlStreamWriter;
+
+class FontConfigDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit FontConfigDialog(QWidget *parent = 0);
+ ~FontConfigDialog();
+
+public slots:
+ void accept();
+ void writeOption(QXmlStreamWriter *stream, const QString &name, const QString &type, const QString &value);
+
+private:
+ Ui::FontConfigDialog *m_ui;
+};
+
+#endif // FONTCONFIGDIALOG_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.ui
new file mode 100644
index 00000000..a557695f
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontconfigdialog.ui
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FontConfigDialog</class>
+ <widget class="QDialog" name="FontConfigDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>349</width>
+ <height>286</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Font Configuration</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>6</number>
+ </property>
+ <item row="5" column="0" colspan="2">
+ <widget class="QCheckBox" name="disableBoldAutohintCheckBox">
+ <property name="text">
+ <string>Disable automatic hinting for bold fonts</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>LCD filter:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0" colspan="2">
+ <widget class="QCheckBox" name="autohinterCheckBox">
+ <property name="text">
+ <string>Automatic hinting</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QCheckBox" name="hintingCheckBox">
+ <property name="text">
+ <string>Hinting</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Font resolution:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="lcdFilterComboBox"/>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="rgbaComboBox"/>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="hintingStyleComboBox"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Subpixel geometry:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QCheckBox" name="antialisingCheckBox">
+ <property name="text">
+ <string>Antialiasing</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Hinting style:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QSpinBox" name="dpiSpinBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> dpi</string>
+ </property>
+ <property name="minimum">
+ <number>80</number>
+ </property>
+ <property name="maximum">
+ <number>180</number>
+ </property>
+ <property name="value">
+ <number>102</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>FontConfigDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>FontConfigDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.cpp
new file mode 100644
index 00000000..ac9fb164
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QSignalMapper>
+#include <QMessageBox>
+#include <QSettings>
+#include <QApplication>
+#include <QFontDialog>
+#include <QDir>
+#include <QFile>
+#include "qt5ct.h"
+#include "fontspage.h"
+#include "fontconfigdialog.h"
+#include "ui_fontspage.h"
+
+FontsPage::FontsPage(QWidget *parent) :
+ TabPage(parent),
+ m_ui(new Ui::FontsPage)
+{
+ m_ui->setupUi(this);
+
+ QSignalMapper *mapper = new QSignalMapper(this);
+ mapper->setMapping(m_ui->changeGeneralFontButton, m_ui->generalFontLabel);
+ mapper->setMapping(m_ui->changeFixedWidthFontButton, m_ui->fixedFontLabel);
+ connect(m_ui->changeGeneralFontButton, SIGNAL(clicked()), mapper, SLOT(map()));
+ connect(m_ui->changeFixedWidthFontButton, SIGNAL(clicked()), mapper, SLOT(map()));
+ connect(mapper, SIGNAL(mapped(QWidget*)), SLOT(onFontChangeRequested(QWidget*)));
+
+ readSettings();
+
+ //icons
+ m_ui->createFontsConfButton->setIcon(QIcon::fromTheme("document-new"));
+ m_ui->removeFontsConfButton->setIcon(QIcon::fromTheme("edit-delete"));
+}
+
+FontsPage::~FontsPage()
+{
+ delete m_ui;
+}
+
+void FontsPage::writeSettings()
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.beginGroup("Fonts");
+ settings.setValue("general", m_ui->generalFontLabel->font());
+ settings.setValue("fixed", m_ui->fixedFontLabel->font());
+ settings.endGroup();
+}
+
+void FontsPage::onFontChangeRequested(QWidget *widget)
+{
+ bool ok = false;
+ QFont font = QFontDialog::getFont (&ok, widget->font(), this);
+ if(ok)
+ {
+ widget->setFont(font);
+ qobject_cast<QLabel*>(widget)->setText(font.family () + " " + QString::number(font.pointSize ()));
+ }
+}
+
+void FontsPage::readSettings()
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.beginGroup("Fonts");
+ loadFont(&settings, m_ui->generalFontLabel, "general");
+ loadFont(&settings, m_ui->fixedFontLabel, "fixed");
+ settings.endGroup();
+}
+
+void FontsPage::loadFont(QSettings *settings, QLabel *label, const QString &key)
+{
+ QFont font = settings->value(key, QApplication::font()).value<QFont>();
+ label->setText(font.family () + " " + QString::number(font.pointSize ()));
+ label->setFont(font);
+}
+
+void FontsPage::on_createFontsConfButton_clicked()
+{
+ FontConfigDialog d(this);
+ d.exec();
+}
+
+void FontsPage::on_removeFontsConfButton_clicked()
+{
+ QString path = QDir::homePath() + "/.config/fontconfig/fonts.conf";
+
+
+ if(QFile::exists(path))
+ {
+ if(QMessageBox::question(this, tr("Remove Font Configuration"),
+ tr("Are you sure you want to delete <i>%1</i>?").arg(path),
+ QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
+ {
+ return;
+ }
+
+ QFile::remove(path + ".back");
+ QFile::copy(path, path + ".back");
+ QFile::remove(path);
+ }
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.h
new file mode 100644
index 00000000..a9c5f1f6
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FONTSPAGE_H
+#define FONTSPAGE_H
+
+#include "tabpage.h"
+
+namespace Ui {
+class FontsPage;
+}
+
+class QLabel;
+class QSettings;
+
+class FontsPage : public TabPage
+{
+ Q_OBJECT
+
+public:
+ explicit FontsPage(QWidget *parent = 0);
+ ~FontsPage();
+
+ void writeSettings();
+
+private slots:
+ void onFontChangeRequested(QWidget *widget);
+ void on_createFontsConfButton_clicked();
+ void on_removeFontsConfButton_clicked();
+
+private:
+ void readSettings();
+ void loadFont(QSettings *settings, QLabel *label, const QString &key);
+ Ui::FontsPage *m_ui;
+};
+
+#endif // FONTSPAGE_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.ui
new file mode 100644
index 00000000..b03b5fc0
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/fontspage.ui
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>FontsPage</class>
+ <widget class="QWidget" name="FontsPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>517</width>
+ <height>320</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string notr="true">Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="1" column="2">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>342</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0" colspan="3">
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="1">
+ <widget class="QLabel" name="generalFontLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>General:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QToolButton" name="changeGeneralFontButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="fixedFontLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QToolButton" name="changeFixedWidthFontButton">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Fixed width:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" colspan="3">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>280</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="createFontsConfButton">
+ <property name="text">
+ <string>Create fonts.conf</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="removeFontsConfButton">
+ <property name="text">
+ <string>Remove fonts.conf</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.cpp
new file mode 100644
index 00000000..ee4d638d
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QSettings>
+#include <QFileInfo>
+#include <QFileInfoList>
+#include <QDir>
+#include <QTreeWidgetItem>
+#include <QImageReader>
+#include <QLocale>
+#include "qt5ct.h"
+#include "iconthemepage.h"
+#include "ui_iconthemepage.h"
+
+IconThemePage::IconThemePage(QWidget *parent) :
+ TabPage(parent),
+ m_ui(new Ui::IconThemePage)
+{
+ m_ui->setupUi(this);
+ loadThemes();
+ readSettings();
+}
+
+IconThemePage::~IconThemePage()
+{
+ delete m_ui;
+}
+
+void IconThemePage::writeSettings()
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ QTreeWidgetItem *item = m_ui->treeWidget->currentItem();
+ if(item)
+ settings.setValue("Appearance/icon_theme", item->data(3, Qt::UserRole));
+}
+
+void IconThemePage::readSettings()
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ QString name = settings.value("Appearance/icon_theme").toString();
+
+ if(name.isEmpty())
+ return;
+
+ for(int i = 0; i < m_ui->treeWidget->topLevelItemCount(); ++i)
+ {
+ QTreeWidgetItem *item = m_ui->treeWidget->topLevelItem(i);
+ if(item->data(3, Qt::UserRole).toString() == name)
+ {
+ m_ui->treeWidget->setCurrentItem(item);
+ break;
+ }
+ }
+}
+
+void IconThemePage::loadThemes()
+{
+ QFileInfoList themeFileList;
+ foreach(QString path, Qt5CT::iconPaths())
+ {
+ QDir dir(path);
+ dir.setFilter(QDir::Dirs | QDir::NoDotDot | QDir::NoDot);
+ foreach (QFileInfo info, dir.entryInfoList())
+ {
+ QDir themeDir(info.absoluteFilePath());
+ themeDir.setFilter(QDir::Files);
+ themeFileList << themeDir.entryInfoList(QStringList() << "index.theme");
+ }
+ }
+
+ foreach(QFileInfo info, themeFileList)
+ {
+ loadTheme(info.canonicalFilePath());
+ }
+}
+
+void IconThemePage::loadTheme(const QString &path)
+{
+ QSettings config(path, QSettings::IniFormat);
+ config.setIniCodec("UTF-8");
+
+ config.beginGroup("Icon Theme");
+ QStringList dirs = config.value("Directories").toStringList();
+ if(dirs.isEmpty() || config.value("Hidden", false).toBool())
+ return;
+
+ QString name, comment;
+ QString lang = QLocale::system().name();
+
+ name = config.value(QString("Name[%1]").arg(lang)).toString();
+ comment = config.value(QString("Comment[%1]").arg(lang)).toString();
+
+ if(lang.contains("_"))
+ lang = lang.split("_").first();
+
+ if(name.isEmpty())
+ name = config.value(QString("Name[%1]").arg(lang)).toString();
+
+ if(comment.isEmpty())
+ comment = config.value(QString("Comment[%1]").arg(lang)).toString();
+
+ if(name.isEmpty())
+ name = config.value("Name").toString();
+
+ if(comment.isEmpty())
+ comment = config.value("Comment").toString();
+
+ config.endGroup();
+
+ QIcon icon1 = findIcon(path, 24, "document-save");
+ QIcon icon2 = findIcon(path, 24, "document-print");
+ QIcon icon3 = findIcon(path, 24, "media-playback-stop");
+
+ QTreeWidgetItem *item = new QTreeWidgetItem();
+ item->setIcon(0, icon1);
+ item->setIcon(1, icon2);
+ item->setIcon(2, icon3);
+ item->setText(3, name);
+ item->setData(3, Qt::UserRole, QFileInfo(path).path().section("/", -1));
+ item->setToolTip(3, comment);
+ item->setSizeHint(0, QSize(24,24));
+ m_ui->treeWidget->addTopLevelItem(item);
+
+ m_ui->treeWidget->resizeColumnToContents(0);
+ m_ui->treeWidget->resizeColumnToContents(1);
+ m_ui->treeWidget->resizeColumnToContents(2);
+ m_ui->treeWidget->resizeColumnToContents(3);
+}
+
+QIcon IconThemePage::findIcon(const QString &themePath, int size, const QString &name)
+{
+ QSettings config(themePath, QSettings::IniFormat);
+ config.beginGroup("Icon Theme");
+ QStringList dirs = config.value("Directories").toStringList();
+ QStringList parents = config.value("Inherits").toStringList();
+ bool haveInherits = config.contains("Inherits");
+ config.endGroup();
+
+ foreach (QString dir, dirs)
+ {
+ config.beginGroup(dir);
+ if(config.value("Size").toInt() == size)
+ {
+ QDir iconDir = QFileInfo(themePath).path() + "/" + dir;
+ iconDir.setFilter(QDir::Files);
+ iconDir.setNameFilters(QStringList () << name + ".*");
+ if(iconDir.entryInfoList().isEmpty())
+ continue;
+ return QIcon(iconDir.entryInfoList().first().absoluteFilePath());
+ }
+ config.endGroup();
+ }
+
+ foreach (QString dir, dirs)
+ {
+ config.beginGroup(dir);
+ if(abs(config.value("Size").toInt() - size) < 4)
+ {
+ QDir iconDir = QFileInfo(themePath).path() + "/" + dir;
+ iconDir.setFilter(QDir::Files);
+ iconDir.setNameFilters(QStringList () << name + ".*");
+ if(iconDir.entryInfoList().isEmpty())
+ continue;
+ return QIcon(iconDir.entryInfoList().first().absoluteFilePath());
+ }
+ config.endGroup();
+ }
+
+ if (!haveInherits)
+ return QIcon();
+
+ parents.append("hicolor"); //add fallback themes
+ parents.append("gnome");
+ parents.removeDuplicates();
+
+ foreach (QString parent, parents)
+ {
+ QString parentThemePath = QDir(QFileInfo(themePath).path() + "/../" + parent).canonicalPath() + "/index.theme";
+
+ if(!QFile::exists(parentThemePath) || parentThemePath == themePath)
+ continue;
+
+ QIcon icon = findIcon(parentThemePath, size, name);
+ if(!icon.isNull())
+ return icon;
+ }
+
+ return QIcon();
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.h
new file mode 100644
index 00000000..0ccd64e0
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ICONTHEMEPAGE_H
+#define ICONTHEMEPAGE_H
+
+#include <QIcon>
+#include "tabpage.h"
+
+namespace Ui {
+class IconThemePage;
+}
+
+class IconThemePage : public TabPage
+{
+ Q_OBJECT
+
+public:
+ explicit IconThemePage(QWidget *parent = 0);
+ ~IconThemePage();
+
+ void writeSettings();
+
+private:
+ void readSettings();
+ void loadThemes();
+ void loadTheme(const QString &path);
+ QIcon findIcon(const QString &themePath, int size, const QString &name);
+ Ui::IconThemePage *m_ui;
+};
+
+#endif // ICONTHEMEPAGE_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.ui
new file mode 100644
index 00000000..a6385041
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.ui
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>IconThemePage</class>
+ <widget class="QWidget" name="IconThemePage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string notr="true">Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTreeWidget" name="treeWidget">
+ <property name="columnCount">
+ <number>4</number>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ <column>
+ <property name="text">
+ <string notr="true">1</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string notr="true">2</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string notr="true">3</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string notr="true">4</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.cpp
new file mode 100644
index 00000000..fc5c0662
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QSettings>
+#include <QApplication>
+#include <QDialogButtonBox>
+#include "qt5ct.h"
+#include "interfacepage.h"
+#include "ui_interfacepage.h"
+
+InterfacePage::InterfacePage(QWidget *parent) :
+ TabPage(parent),
+ m_ui(new Ui::InterfacePage)
+{
+ m_ui->setupUi(this);
+
+ m_ui->buttonLayoutComboBox->addItem("Windows", QDialogButtonBox::WinLayout);
+ m_ui->buttonLayoutComboBox->addItem("Mac OS X", QDialogButtonBox::MacLayout);
+ m_ui->buttonLayoutComboBox->addItem("KDE", QDialogButtonBox::KdeLayout);
+ m_ui->buttonLayoutComboBox->addItem("GNOME", QDialogButtonBox::GnomeLayout);
+
+ m_ui->toolButtonStyleComboBox->addItem(tr("Only display the icon"), Qt::ToolButtonIconOnly);
+ m_ui->toolButtonStyleComboBox->addItem(tr("Only display the text"), Qt::ToolButtonTextOnly);
+ m_ui->toolButtonStyleComboBox->addItem(tr("The text appears beside the icon"), Qt::ToolButtonTextBesideIcon);
+ m_ui->toolButtonStyleComboBox->addItem(tr("The text appears under the icon"), Qt::ToolButtonTextUnderIcon);
+ m_ui->toolButtonStyleComboBox->addItem(tr("Follow the application style"), Qt::ToolButtonFollowStyle);
+
+ readSettings();
+}
+
+InterfacePage::~InterfacePage()
+{
+ delete m_ui;
+}
+
+void InterfacePage::writeSettings()
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.beginGroup("Interface");
+ settings.setValue("double_click_interval", m_ui->doubleClickIntervalSpinBox->value());
+ settings.setValue("cursor_flash_time", m_ui->cursorFlashTimeSpinBox->value());
+ settings.setValue("buttonbox_layout", m_ui->buttonLayoutComboBox->currentData());
+ settings.setValue("menus_have_icons", m_ui->menuIconsCheckBox->isChecked());
+ settings.setValue("activate_item_on_single_click", m_ui->singleClickCheckBox->checkState());
+ settings.setValue("dialog_buttons_have_icons", m_ui->dialogIconsCheckBox->checkState());
+ settings.setValue("toolbutton_style", m_ui->toolButtonStyleComboBox->currentData());
+ settings.setValue("wheel_scroll_lines", m_ui->wheelScrollLinesSpinBox->value());
+
+ QStringList effects;
+ if(m_ui->guiEffectsCheckBox->isChecked())
+ effects << "General";
+
+ if(m_ui->menuEffectComboBox->currentIndex() == 1)
+ effects << "AnimateMenu";
+ else if(m_ui->menuEffectComboBox->currentIndex() == 2)
+ effects << "FadeMenu";
+
+ if(m_ui->comboBoxEffectComboBox->currentIndex() == 1)
+ effects << "AnimateCombo";
+
+ if(m_ui->toolTipEffectComboBox->currentIndex() == 1)
+ effects << "AnimateTooltip";
+ else if(m_ui->toolTipEffectComboBox->currentIndex() == 2)
+ effects << "FadeTooltip";
+
+ if(m_ui->toolBoxEffectComboBox->currentIndex() == 1)
+ effects << "AnimateToolBox";
+
+ settings.setValue("gui_effects", effects);
+ settings.endGroup();
+}
+
+void InterfacePage::readSettings()
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.beginGroup("Interface");
+ m_ui->doubleClickIntervalSpinBox->setValue(qApp->doubleClickInterval());
+ m_ui->cursorFlashTimeSpinBox->setValue(qApp->cursorFlashTime());
+
+ m_ui->guiEffectsCheckBox->setChecked(qApp->isEffectEnabled(Qt::UI_General));
+
+ int layout = settings.value("buttonbox_layout", style()->styleHint(QStyle::SH_DialogButtonLayout)).toInt();
+ int index = m_ui->buttonLayoutComboBox->findData(layout);
+ if(index >= 0)
+ m_ui->buttonLayoutComboBox->setCurrentIndex(index);
+
+ if(qApp->isEffectEnabled(Qt::UI_AnimateMenu))
+ m_ui->menuEffectComboBox->setCurrentIndex(1);
+ else if(qApp->isEffectEnabled(Qt::UI_FadeMenu))
+ m_ui->menuEffectComboBox->setCurrentIndex(2);
+
+ if(qApp->isEffectEnabled(Qt::UI_AnimateCombo))
+ m_ui->comboBoxEffectComboBox->setCurrentIndex(1);
+
+ if(qApp->isEffectEnabled(Qt::UI_AnimateTooltip))
+ m_ui->toolTipEffectComboBox->setCurrentIndex(1);
+ else if(qApp->isEffectEnabled(Qt::UI_FadeTooltip))
+ m_ui->toolTipEffectComboBox->setCurrentIndex(2);
+
+ if(qApp->isEffectEnabled(Qt::UI_AnimateToolBox))
+ m_ui->toolBoxEffectComboBox->setCurrentIndex(1);
+
+ m_ui->singleClickCheckBox->setCheckState((Qt::CheckState)settings.value("activate_item_on_single_click", Qt::PartiallyChecked).toInt());
+ m_ui->dialogIconsCheckBox->setCheckState((Qt::CheckState)settings.value("dialog_buttons_have_icons", Qt::PartiallyChecked).toInt());
+ m_ui->menuIconsCheckBox->setChecked(!qApp->testAttribute(Qt::AA_DontShowIconsInMenus));
+
+ int toolbarStyle = settings.value("toolbutton_style", Qt::ToolButtonFollowStyle).toInt();
+ index = m_ui->toolButtonStyleComboBox->findData(toolbarStyle);
+ if(index >= 0)
+ m_ui->toolButtonStyleComboBox->setCurrentIndex(index);
+
+ m_ui->wheelScrollLinesSpinBox->setValue(settings.value("wheel_scroll_lines", 3).toInt());
+
+ settings.endGroup();
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.h
new file mode 100644
index 00000000..637b6bf1
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef INTERFACEPAGE_H
+#define INTERFACEPAGE_H
+
+#include "tabpage.h"
+
+namespace Ui {
+class InterfacePage;
+}
+
+class InterfacePage : public TabPage
+{
+ Q_OBJECT
+
+public:
+ explicit InterfacePage(QWidget *parent = 0);
+ ~InterfacePage();
+
+ void writeSettings();
+
+private:
+ void readSettings();
+
+ Ui::InterfacePage *m_ui;
+};
+
+#endif // INTERFACEPAGE_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.ui
new file mode 100644
index 00000000..ca9d0291
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/interfacepage.ui
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>InterfacePage</class>
+ <widget class="QWidget" name="InterfacePage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>498</width>
+ <height>449</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string notr="true">Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="2" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>259</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0">
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Double click interval:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Cursor flash time:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>ComboBox effect:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>ToolTip effect:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>ToolBox effect:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="doubleClickIntervalSpinBox">
+ <property name="suffix">
+ <string> ms</string>
+ </property>
+ <property name="maximum">
+ <number>2000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="cursorFlashTimeSpinBox">
+ <property name="suffix">
+ <string> ms</string>
+ </property>
+ <property name="maximum">
+ <number>4000</number>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="comboBoxEffectComboBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disable</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Animate</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="toolTipEffectComboBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disable</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Animate</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Fade</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="7" column="1">
+ <widget class="QComboBox" name="toolBoxEffectComboBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disable</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Animate</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Menu effect:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="menuEffectComboBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>Disable</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Animate</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Fade</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QCheckBox" name="guiEffectsCheckBox">
+ <property name="text">
+ <string>Enable gui effects</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Dialog buttons layout:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="1">
+ <widget class="QComboBox" name="buttonLayoutComboBox"/>
+ </item>
+ <item row="10" column="0" colspan="2">
+ <widget class="QCheckBox" name="menuIconsCheckBox">
+ <property name="text">
+ <string>Menus have icons</string>
+ </property>
+ </widget>
+ </item>
+ <item row="9" column="0" colspan="2">
+ <widget class="QCheckBox" name="dialogIconsCheckBox">
+ <property name="text">
+ <string>Dialog buttons have icons</string>
+ </property>
+ <property name="tristate">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QCheckBox" name="singleClickCheckBox">
+ <property name="text">
+ <string>Activate item on single-click</string>
+ </property>
+ <property name="tristate">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>Toolbar button style:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="1">
+ <widget class="QComboBox" name="toolButtonStyleComboBox"/>
+ </item>
+ <item row="12" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Mouse wheel scroll lines:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="1">
+ <widget class="QSpinBox" name="wheelScrollLinesSpinBox">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>20</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="1">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>238</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>guiEffectsCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>menuEffectComboBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>126</x>
+ <y>86</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>201</x>
+ <y>114</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>guiEffectsCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>comboBoxEffectComboBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>75</x>
+ <y>84</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>160</x>
+ <y>153</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>guiEffectsCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>toolTipEffectComboBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>54</x>
+ <y>84</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>155</x>
+ <y>184</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>guiEffectsCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>toolBoxEffectComboBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>36</x>
+ <y>91</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>156</x>
+ <y>216</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/main.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/main.cpp
new file mode 100644
index 00000000..d15c9c01
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/main.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QApplication>
+#include <QLibraryInfo>
+#include <QLocale>
+#include "qt5ct.h"
+#include <QTranslator>
+#include <QMessageBox>
+#include <QProcessEnvironment>
+#include <QStyleFactory>
+#include "mainwindow.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ QTranslator translator;
+ QString locale = Qt5CT::systemLanguageID();
+ translator.load(QString(":/qt5ct_") + locale);
+ app.installTranslator(&translator);
+
+ QTranslator qt_translator;
+ qt_translator.load(QLibraryInfo::location (QLibraryInfo::TranslationsPath) + "/qtbase_" + locale);
+ app.installTranslator(&qt_translator);
+
+ qDebug("Configuration path: %s", qPrintable(Qt5CT::configPath()));
+ qDebug("Shared QSS path: %s", qPrintable(Qt5CT::sharedStyleSheetPath()));
+
+ //checking environment
+ QStringList errorMessages;
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+
+ if(env.contains("QT_STYLE_OVERRIDE"))
+ {
+ errorMessages << app.translate("main", "Please remove the <b>QT_STYLE_OVERRIDE</b> environment variable");
+ }
+
+ if(env.value("QT_QPA_PLATFORMTHEME") != "qt5ct")
+ {
+ errorMessages << app.translate("main", "The <b>QT_QPA_PLATFORMTHEME</b> environment "
+ "variable is not set correctly");
+ }
+
+ if(!QStyleFactory::keys().contains("qt5ct-style"))
+ {
+ errorMessages << app.translate("main", "Unable to find <b>libqt5ct-style.so</b>");
+ }
+
+ if(!errorMessages.isEmpty())
+ {
+ QMessageBox::critical(0, app.translate("main", "Error"), errorMessages.join("<br><br>"));
+ return 0;
+ }
+
+ MainWindow w;
+ w.show();
+
+ return app.exec();
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp
new file mode 100644
index 00000000..b120436f
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QApplication>
+#include <QSettings>
+#include "qt5ct.h"
+#include "mainwindow.h"
+#include "appearancepage.h"
+#include "fontspage.h"
+#include "iconthemepage.h"
+#include "interfacepage.h"
+#include "qsspage.h"
+#include "ui_mainwindow.h"
+
+MainWindow::MainWindow(QWidget *parent) :
+ QWidget(parent),
+ m_ui(new Ui::MainWindow)
+{
+ m_ui->setupUi(this);
+ m_ui->tabWidget->addTab(new AppearancePage(this), tr("Appearance"));
+ m_ui->tabWidget->addTab(new FontsPage(this), tr("Fonts"));
+ m_ui->tabWidget->addTab(new IconThemePage(this), tr("Icon Theme"));
+ m_ui->tabWidget->addTab(new InterfacePage(this), tr("Interface"));
+#ifdef USE_WIDGETS
+ m_ui->tabWidget->addTab(new QSSPage(this), tr("Style Sheets"));
+#endif
+
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ restoreGeometry(settings.value("SettingsWindow/geometry").toByteArray());
+
+ setWindowIcon(QIcon::fromTheme("preferences-desktop-theme"));
+
+ m_ui->versionLabel->setText(tr("Version: %1").arg(QT5CT_VERSION_STR));
+}
+
+MainWindow::~MainWindow()
+{
+ delete m_ui;
+}
+
+void MainWindow::closeEvent(QCloseEvent *)
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.setValue("SettingsWindow/geometry", saveGeometry());
+}
+
+void MainWindow::on_buttonBox_clicked(QAbstractButton *button)
+{
+ int id = m_ui->buttonBox->standardButton(button);
+ if(id == QDialogButtonBox::Ok || id == QDialogButtonBox::Apply)
+ {
+ for(int i = 0; i < m_ui->tabWidget->count(); ++i)
+ {
+ TabPage *p = qobject_cast<TabPage*>(m_ui->tabWidget->widget(i));
+ if(p)
+ p->writeSettings();
+ }
+ }
+
+ if(id == QDialogButtonBox::Ok || id == QDialogButtonBox::Cancel)
+ {
+ close();
+ qApp->quit();
+ }
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.h
new file mode 100644
index 00000000..f532141c
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QWidget>
+
+class QAbstractButton;
+
+namespace Ui {
+class MainWindow;
+}
+
+class MainWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+private slots:
+ void on_buttonBox_clicked(QAbstractButton *button);
+
+private:
+ void closeEvent(QCloseEvent *);
+
+ Ui::MainWindow *m_ui;
+};
+
+#endif // MAINWINDOW_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui
new file mode 100644
index 00000000..5bdab6d7
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QWidget" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>438</width>
+ <height>374</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Qt5 Configuration Tool</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>6</number>
+ </property>
+ <item row="0" column="0" colspan="2">
+ <widget class="QTabWidget" name="tabWidget"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="versionLabel">
+ <property name="text">
+ <string notr="true">...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.cpp
new file mode 100644
index 00000000..31a3a2a9
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QPalette>
+#include <QColorDialog>
+#include <QSettings>
+#include "qt5ct.h"
+#include "paletteeditdialog.h"
+#include "ui_paletteeditdialog.h"
+
+PaletteEditDialog::PaletteEditDialog(const QPalette &palette, QStyle *currentStyle, QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::PaletteEditDialog)
+{
+ m_currentStyle = currentStyle;
+ m_ui->setupUi(this);
+ m_ui->tableWidget->setColumnCount(3);
+ m_ui->tableWidget->setRowCount(QPalette::NColorRoles);
+ m_ui->tableWidget->verticalHeader()->setDefaultSectionSize(fontMetrics().lineSpacing() + 10);
+ m_ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
+ m_ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
+
+ QStringList labels;
+ labels << tr("Active") << tr("Inactive") << tr("Disabled");
+ m_ui->tableWidget->setHorizontalHeaderLabels(labels);
+ setPalette(palette);
+
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ restoreGeometry(settings.value("PaletteEditor/geometry").toByteArray());
+}
+
+PaletteEditDialog::~PaletteEditDialog()
+{
+ delete m_ui;
+}
+
+QPalette PaletteEditDialog::selectedPalette() const
+{
+ QPalette palette;
+ for(int i = 0; i < QPalette::NColorRoles; i++)
+ {
+ palette.setBrush(QPalette::Active, QPalette::ColorRole(i), m_ui->tableWidget->item(i,0)->backgroundColor());
+ palette.setBrush(QPalette::Inactive, QPalette::ColorRole(i), m_ui->tableWidget->item(i,1)->backgroundColor());
+ palette.setBrush(QPalette::Disabled, QPalette::ColorRole(i), m_ui->tableWidget->item(i,2)->backgroundColor());
+ }
+ return palette;
+}
+
+void PaletteEditDialog::setPalette(const QPalette &palette)
+{
+ for(int i = 0; i < QPalette::NColorRoles; i++)
+ {
+ if(!m_ui->tableWidget->item(i,0))
+ m_ui->tableWidget->setItem(i, 0, new QTableWidgetItem());
+ if(!m_ui->tableWidget->item(i,1))
+ m_ui->tableWidget->setItem(i, 1, new QTableWidgetItem());
+ if(!m_ui->tableWidget->item(i,2))
+ m_ui->tableWidget->setItem(i, 2, new QTableWidgetItem());
+
+ m_ui->tableWidget->item(i,0)->setBackgroundColor(palette.color(QPalette::Active, QPalette::ColorRole(i)));
+ m_ui->tableWidget->item(i,1)->setBackgroundColor(palette.color(QPalette::Inactive, QPalette::ColorRole(i)));
+ m_ui->tableWidget->item(i,2)->setBackgroundColor(palette.color(QPalette::Disabled, QPalette::ColorRole(i)));
+ }
+
+ QStringList labels;
+ labels << tr("Window text") << tr("Button background") << tr("Bright") << tr("Less bright") << tr("Dark") << tr("Less dark")
+ << tr("Normal text") << tr("Bright text") << tr("Button text") << tr("Normal background") << tr("Window") << tr("Shadow")
+ << tr("Highlight") << tr("Highlighted text") << tr("Link") << tr("Visited link")
+ << tr("Alternate background") << tr("Default") << tr("Tooltip background") << tr("Tooltip text");
+ m_ui->tableWidget->setVerticalHeaderLabels(labels);
+}
+
+void PaletteEditDialog::hideEvent(QHideEvent *)
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.setValue("PaletteEditor/geometry", saveGeometry());
+}
+
+void PaletteEditDialog::on_tableWidget_itemClicked(QTableWidgetItem *item)
+{
+ QColor color = QColorDialog::getColor(item->backgroundColor(), this, tr("Select Color"));
+ if(color.isValid())
+ {
+ item->setBackgroundColor(color);
+ emit paletteChanged(selectedPalette());
+ }
+}
+
+void PaletteEditDialog::on_resetPaletteButton_clicked()
+{
+ setPalette(m_currentStyle->standardPalette());
+ emit paletteChanged(selectedPalette());
+}
+
+void PaletteEditDialog::on_buildInactiveButton_clicked()
+{
+ QPalette palette = selectedPalette();
+ for(int i = 0; i < QPalette::NColorRoles; i++)
+ {
+ palette.setColor(QPalette::Inactive, QPalette::ColorRole(i),
+ palette.color(QPalette::Active, QPalette::ColorRole(i)));
+ }
+ setPalette(palette);
+ emit paletteChanged(selectedPalette());
+}
+
+void PaletteEditDialog::on_buildDisabledButton_clicked()
+{
+ QPalette palette = selectedPalette();
+ for(int i = 0; i < QPalette::NColorRoles; i++)
+ {
+ palette.setColor(QPalette::Disabled, QPalette::ColorRole(i),
+ palette.color(QPalette::Active, QPalette::ColorRole(i)));
+ }
+ palette.setColor(QPalette::Disabled, QPalette::ButtonText, Qt::darkGray);
+ palette.setColor(QPalette::Disabled, QPalette::WindowText, Qt::darkGray);
+ palette.setColor(QPalette::Disabled, QPalette::Text, Qt::darkGray);
+ palette.setColor(QPalette::Disabled, QPalette::HighlightedText, Qt::darkGray);
+ setPalette(palette);
+ emit paletteChanged(selectedPalette());
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.h
new file mode 100644
index 00000000..c8691a3c
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PALETTEEDITDIALOG_H
+#define PALETTEEDITDIALOG_H
+
+#include <QDialog>
+#include <QPalette>
+
+class QTableWidgetItem;
+class QStyle;
+
+namespace Ui {
+class PaletteEditDialog;
+}
+
+class PaletteEditDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit PaletteEditDialog(const QPalette &palette, QStyle *currentStyle, QWidget *parent = 0);
+ ~PaletteEditDialog();
+
+ QPalette selectedPalette() const;
+
+signals:
+ void paletteChanged(const QPalette &p);
+
+private slots:
+ void on_tableWidget_itemClicked(QTableWidgetItem *item);
+ void on_resetPaletteButton_clicked();
+ void on_buildInactiveButton_clicked();
+ void on_buildDisabledButton_clicked();
+
+private:
+ void setPalette(const QPalette &palette);
+ void hideEvent(QHideEvent *);
+ Ui::PaletteEditDialog *m_ui;
+ QStyle *m_currentStyle;
+};
+
+#endif // PALETTEEDITDIALOG_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.ui
new file mode 100644
index 00000000..6ca6350f
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/paletteeditdialog.ui
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PaletteEditDialog</class>
+ <widget class="QDialog" name="PaletteEditDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>631</width>
+ <height>529</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Palette Editor</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>6</number>
+ </property>
+ <item row="3" column="0">
+ <widget class="QPushButton" name="buildInactiveButton">
+ <property name="text">
+ <string>Build inactive palette</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QPushButton" name="buildDisabledButton">
+ <property name="text">
+ <string>Build disabled palette</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="3">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>117</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="9" column="0" colspan="5">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="5">
+ <widget class="QTableWidget" name="tableWidget">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::NoSelection</enum>
+ </property>
+ <property name="columnCount">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QPushButton" name="resetPaletteButton">
+ <property name="text">
+ <string>Reset palette</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>PaletteEditDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>PaletteEditDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/previewform.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/previewform.ui
new file mode 100644
index 00000000..508201db
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/previewform.ui
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PreviewForm</class>
+ <widget class="QWidget" name="PreviewForm">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>281</width>
+ <height>130</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Preview Window</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab_3">
+ <attribute name="title">
+ <string>Tab 1</string>
+ </attribute>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="1" column="0">
+ <widget class="QPushButton" name="pushButton_3">
+ <property name="text">
+ <string>PushButton</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" colspan="2">
+ <widget class="QProgressBar" name="progressBar_2">
+ <property name="value">
+ <number>24</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLineEdit" name="lineEdit_2"/>
+ </item>
+ <item row="0" column="1" colspan="2">
+ <widget class="QSpinBox" name="spinBox_2"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_4">
+ <attribute name="title">
+ <string>Tab 2</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QRadioButton" name="radioButton_7">
+ <property name="text">
+ <string>RadioButton</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkBox_2">
+ <property name="text">
+ <string>CheckBox</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp
new file mode 100644
index 00000000..7c6292ac
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QFile>
+#include <QSettings>
+#include "qt5ct.h"
+#include "qsseditordialog.h"
+#include "ui_qsseditordialog.h"
+
+QSSEditorDialog::QSSEditorDialog(const QString &filePath, QWidget *parent) :
+ QDialog(parent),
+ m_ui(new Ui::QSSEditorDialog)
+{
+ m_ui->setupUi(this);
+ m_filePath = filePath;
+
+ QFile file(filePath);
+ file.open(QIODevice::ReadOnly);
+ m_ui->textEdit->setPlainText(QString::fromUtf8(file.readAll()));
+ setWindowTitle(tr("%1 - Style Sheet Editor").arg(file.fileName()));
+
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ restoreGeometry(settings.value("QSSEditor/geometry").toByteArray());
+}
+
+QSSEditorDialog::~QSSEditorDialog()
+{
+ delete m_ui;
+}
+
+void QSSEditorDialog::save()
+{
+ QFile file(m_filePath);
+ file.open(QIODevice::WriteOnly);
+ file.write(m_ui->textEdit->toPlainText().toUtf8());
+}
+
+void QSSEditorDialog::hideEvent(QHideEvent *)
+{
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ settings.setValue("QSSEditor/geometry", saveGeometry());
+}
+
+void QSSEditorDialog::on_buttonBox_clicked(QAbstractButton *button)
+{
+ QDialogButtonBox::StandardButton id = m_ui->buttonBox->standardButton(button);
+ if(id == QDialogButtonBox::Ok)
+ {
+ save();
+ accept();
+ }
+ else if(id == QDialogButtonBox::Save)
+ {
+ save();
+ }
+ else
+ {
+ reject();
+ }
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h
new file mode 100644
index 00000000..e2a6c773
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef QSSEDITORDIALOG_H
+#define QSSEDITORDIALOG_H
+
+#include <QDialog>
+#include <QString>
+
+namespace Ui {
+class QSSEditorDialog;
+}
+
+class QAbstractButton;
+
+class QSSEditorDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit QSSEditorDialog(const QString &filePath, QWidget *parent = 0);
+ ~QSSEditorDialog();
+
+private slots:
+ void on_buttonBox_clicked(QAbstractButton *button);
+
+private:
+ void save();
+ void hideEvent(QHideEvent *);
+ Ui::QSSEditorDialog *m_ui;
+ QString m_filePath;
+};
+
+#endif // QSSEDITORDIALOG_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui
new file mode 100644
index 00000000..7627b4d4
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QSSEditorDialog</class>
+ <widget class="QDialog" name="QSSEditorDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>643</width>
+ <height>499</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Style Sheet Editor</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QTextEdit" name="textEdit">
+ <property name="acceptRichText">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Save</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp
new file mode 100644
index 00000000..784ff674
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QSettings>
+#include <QDir>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QFile>
+#include <QMenu>
+#include "qt5ct.h"
+#include "qsseditordialog.h"
+#include "qsspage.h"
+#include "ui_qsspage.h"
+
+#define QSS_FULL_PATH_ROLE (Qt::ItemDataRole(Qt::UserRole))
+#define QSS_WRITABLE_ROLE (Qt::ItemDataRole(Qt::UserRole + 1))
+
+QSSPage::QSSPage(QWidget *parent) :
+ TabPage(parent),
+ m_ui(new Ui::QSSPage)
+{
+ m_ui->setupUi(this);
+ QDir("/").mkpath(Qt5CT::userStyleSheetPath());
+
+ m_menu = new QMenu(this);
+ m_menu->addAction(QIcon::fromTheme("accessories-text-editor"), tr("Edit"), this, SLOT(on_editButton_clicked()));
+ m_menu->addAction(tr("Rename"), this, SLOT(on_renameButton_clicked()));
+ m_menu->addSeparator();
+ m_menu->addAction(QIcon::fromTheme("edit-delete"), tr("Remove"), this, SLOT(on_removeButton_clicked()));
+
+ readSettings();
+
+ //icons
+ m_ui->createButton->setIcon(QIcon::fromTheme("document-new"));
+ m_ui->editButton->setIcon(QIcon::fromTheme("accessories-text-editor"));
+ m_ui->removeButton->setIcon(QIcon::fromTheme("edit-delete"));
+}
+
+QSSPage::~QSSPage()
+{
+ delete m_ui;
+}
+
+void QSSPage::writeSettings()
+{
+ QStringList styleSheets;
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+
+ for(int i = 0; i < m_ui->qssListWidget->count(); ++i)
+ {
+ QListWidgetItem *item = m_ui->qssListWidget->item(i);
+ if(item->checkState() == Qt::Checked)
+ styleSheets << item->data(QSS_FULL_PATH_ROLE).toString();
+ }
+
+ settings.setValue("Interface/stylesheets", styleSheets);
+}
+
+void QSSPage::on_qssListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *)
+{
+ if(current)
+ {
+ m_ui->editButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool());
+ m_ui->removeButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool());
+ m_ui->renameButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool());
+ }
+ else
+ {
+ m_ui->editButton->setEnabled(false);
+ m_ui->removeButton->setEnabled(false);
+ m_ui->renameButton->setEnabled(false);
+ }
+}
+
+void QSSPage::on_createButton_clicked()
+{
+ QString name = QInputDialog::getText(this, tr("Enter Style Sheet Name"), tr("File name:"));
+ if(name.isEmpty())
+ return;
+
+ if(!name.endsWith(".qss", Qt::CaseInsensitive))
+ name.append(".qss");
+
+ QString filePath = Qt5CT::userStyleSheetPath() + name;
+
+ if(QFile::exists(filePath))
+ {
+ QMessageBox::warning(this, tr("Error"), tr("The file \"%1\" already exists").arg(filePath));
+ return;
+ }
+
+ //creating empty file
+ QFile file(filePath);
+ file.open(QIODevice::WriteOnly);
+ file.close();
+
+ //creating item
+ QFileInfo info(filePath);
+ QListWidgetItem *item = new QListWidgetItem(info.fileName(), m_ui->qssListWidget);
+ item->setToolTip(info.filePath());
+ item->setData(QSS_FULL_PATH_ROLE, info.filePath());
+ item->setData(QSS_WRITABLE_ROLE, info.isWritable());
+ item->setCheckState(Qt::Unchecked);
+}
+
+void QSSPage::on_editButton_clicked()
+{
+ QListWidgetItem *item = m_ui->qssListWidget->currentItem();
+ if(item)
+ {
+ QSSEditorDialog dialog(item->data(QSS_FULL_PATH_ROLE).toString(), this);
+ dialog.exec();
+ }
+}
+
+void QSSPage::on_removeButton_clicked()
+{
+ QListWidgetItem *item = m_ui->qssListWidget->currentItem();
+ if(!item)
+ return;
+
+ int button = QMessageBox::question(this, tr("Confirm Remove"),
+ tr("Are you sure you want to remove style sheet \"%1\"?")
+ .arg(item->text()),
+ QMessageBox::Yes | QMessageBox::No);
+ if(button == QMessageBox::Yes)
+ {
+ QFile::remove(item->data(QSS_FULL_PATH_ROLE).toString());
+ delete item;
+ }
+}
+
+void QSSPage::readSettings()
+{
+ //load stylesheets
+ m_ui->qssListWidget->clear();
+ findStyleSheets(Qt5CT::userStyleSheetPath());
+ findStyleSheets(Qt5CT::sharedStyleSheetPath());
+
+ QSettings settings(Qt5CT::configFile(), QSettings::IniFormat);
+ QStringList styleSheets = settings.value("Interface/stylesheets").toStringList();
+ for(int i = 0; i < m_ui->qssListWidget->count(); ++i)
+ {
+ QListWidgetItem *item = m_ui->qssListWidget->item(i);
+ if(styleSheets.contains(item->data(QSS_FULL_PATH_ROLE).toString()))
+ item->setCheckState(Qt::Checked);
+ else
+ item->setCheckState(Qt::Unchecked);
+ }
+}
+
+void QSSPage::findStyleSheets(const QString &path)
+{
+ QDir dir(path);
+ dir.setFilter(QDir::Files);
+ dir.setNameFilters(QStringList() << "*.qss");
+
+ foreach (QFileInfo info, dir.entryInfoList())
+ {
+ QListWidgetItem *item = new QListWidgetItem(info.fileName(), m_ui->qssListWidget);
+ item->setToolTip(info.filePath());
+ item->setData(QSS_FULL_PATH_ROLE, info.filePath());
+ item->setData(QSS_WRITABLE_ROLE, info.isWritable());
+ }
+}
+
+void QSSPage::on_renameButton_clicked()
+{
+ QListWidgetItem *item = m_ui->qssListWidget->currentItem();
+ if(!item)
+ return;
+
+ QString name = QInputDialog::getText(this, tr("Rename Style Sheet"), tr("Style sheet name:"),
+ QLineEdit::Normal, item->text(), 0);
+ if(name.isEmpty())
+ return;
+
+ if(!m_ui->qssListWidget->findItems(name, Qt::MatchExactly).isEmpty())
+ {
+ QMessageBox::warning(this, tr("Error"), tr("The style sheet \"%1\" already exists").arg(name));
+ return;
+ }
+
+ if(!name.endsWith(".qss", Qt::CaseInsensitive))
+ name.append(".qss");
+
+ QString newPath = Qt5CT::userStyleSheetPath() + name;
+
+ if(!QFile::rename(item->data(QSS_FULL_PATH_ROLE).toString(), newPath))
+ {
+ QMessageBox::warning(this, tr("Error"), tr("Unable to rename file"));
+ return;
+ }
+
+ item->setText(name);
+ item->setData(QSS_FULL_PATH_ROLE, newPath);
+ item->setToolTip(newPath);
+}
+
+void QSSPage::on_qssListWidget_customContextMenuRequested(const QPoint &pos)
+{
+ QListWidgetItem *item = m_ui->qssListWidget->currentItem();
+ if(item && item->data(QSS_WRITABLE_ROLE).toBool())
+ {
+ m_menu->exec(m_ui->qssListWidget->viewport()->mapToGlobal(pos));
+ }
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h
new file mode 100644
index 00000000..665f68c0
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef QSSPAGE_H
+#define QSSPAGE_H
+
+#include "tabpage.h"
+
+namespace Ui {
+class QSSPage;
+}
+
+class QListWidgetItem;
+class QMenu;
+
+class QSSPage : public TabPage
+{
+ Q_OBJECT
+
+public:
+ explicit QSSPage(QWidget *parent = 0);
+ ~QSSPage();
+
+ void writeSettings();
+
+private slots:
+ void on_qssListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *);
+ void on_createButton_clicked();
+ void on_editButton_clicked();
+ void on_removeButton_clicked();
+ void on_renameButton_clicked();
+ void on_qssListWidget_customContextMenuRequested(const QPoint &pos);
+
+private:
+ void readSettings();
+ void findStyleSheets(const QString &path);
+ Ui::QSSPage *m_ui;
+ QMenu *m_menu;
+};
+
+#endif // QSSPAGE_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui
new file mode 100644
index 00000000..124b4dc6
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QSSPage</class>
+ <widget class="QWidget" name="QSSPage">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>483</width>
+ <height>320</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string notr="true">Style Sheet Editor</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="0">
+ <widget class="QPushButton" name="createButton">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Create</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <widget class="QPushButton" name="removeButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>189</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0" colspan="6">
+ <widget class="QListWidget" name="qssListWidget">
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="editButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Edit</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="renameButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Rename</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.cpp
new file mode 100644
index 00000000..b83f43df
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <QDir>
+#include <QLocale>
+#include "qt5ct.h"
+
+#ifndef QT5CT_DATADIR
+#define QT5CT_DATADIR "/usr/share"
+#endif
+
+
+QString Qt5CT::configPath()
+{
+ return QDir::homePath() + "/.config/qt5ct/";
+}
+
+QString Qt5CT::configFile()
+{
+ return configPath() + "qt5ct.conf";
+}
+
+QStringList Qt5CT::iconPaths()
+{
+ QString xdgDataDirs = qgetenv("XDG_DATA_DIRS");
+ QString xdgDataHome = qgetenv("XDG_DATA_HOME");
+
+ QStringList paths;
+ paths << QDir::homePath() + "/.icons/";
+
+ if(xdgDataDirs.isEmpty())
+ {
+ paths << "/usr/share/icons";
+ paths << "/usr/local/share/icons";
+ }
+ else
+ {
+ foreach (QString p, xdgDataDirs.split(":"))
+ paths << QDir(p + "/icons/").absolutePath();
+ }
+
+ if(xdgDataHome.isEmpty())
+ xdgDataHome = QDir::homePath() + "/.local/share";
+
+ paths << "/usr/share/pixmaps";
+ paths << xdgDataHome + "/icons";
+ paths.removeDuplicates();
+
+ //remove invalid
+ foreach (QString p, paths)
+ {
+ if(!QDir(p).exists())
+ paths.removeAll(p);
+ }
+ return paths;
+}
+
+QString Qt5CT::userStyleSheetPath()
+{
+ return configPath() + "qss/";
+}
+
+QString Qt5CT::sharedStyleSheetPath()
+{
+ return QT5CT_DATADIR"/qt5ct/qss/";
+}
+
+QString Qt5CT::userColorSchemePath()
+{
+ return configPath() + "colors/";
+}
+
+QString Qt5CT::sharedColorSchemePath()
+{
+ return QT5CT_DATADIR"/qt5ct/colors/";
+}
+
+QString Qt5CT::systemLanguageID()
+{
+#ifdef Q_OS_UNIX
+ QByteArray v = qgetenv ("LC_ALL");
+ if (v.isEmpty())
+ v = qgetenv ("LC_MESSAGES");
+ if (v.isEmpty())
+ v = qgetenv ("LANG");
+ if (!v.isEmpty())
+ return QLocale (v).name();
+#endif
+ return QLocale::system().name();
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.desktop b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.desktop
new file mode 100644
index 00000000..1c5f6560
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.desktop
@@ -0,0 +1,60 @@
+[Desktop Entry]
+X-Desktop-File-Install-Version=0.11
+Name=Qt5 Settings
+
+Comment=Qt5 Configuration Tool
+
+Comment[ar]= أداة اعداد Qt5
+Name[ar]=إعدادات Qt5
+
+Comment[bg]=Инструмент за настройка на Qt5
+Name[bg]=Настройки на Qt5
+
+Comment[de]=Qt5-Konfigurationswerkzeug
+Name[de]=Qt5-Einstellungen
+
+Comment[el]=Εργαλείο διαμόρφωσης της Qt5
+Name[el]=Ρυθμίσεις Qt5
+
+Comment[es_ES]=Herramienta de configuración de QT5
+Name[es_ES]=Ajustes QT5
+
+Comment[fr]=Un outil de configuration de Qt5
+Name[fr]=Paramètres de Qt5
+
+Comment[he]=כלי תצורה Qt5
+Name[he]=הגדרות Qt5
+
+Comment[ru]=Программа для настройки Qt5
+Name[ru]=Настройки Qt5
+
+Comment[cs]=Nástroj na nastavení Qt5
+Name[cs]=Nastavení Qt5
+
+Comment[it_IT]=Strumento di configurazione Qt5
+Name[it_IT]=Impostazioni Qt5
+
+Comment[nl_NL]=Qt5-instellingengereedschap
+Name[nl_NL]=Qt5-instellingen
+
+Comment[pl]=Narzędzie konfiguracji Qt5
+Name[pl]=Ustawienia Qt5
+
+Comment[sk]=Qt5 konfiguračný nástroj
+Name[sk]=Qt5 nastavenia
+
+Comment[sr]=Qt5 конфигурациони алат
+Name[sr]=Qt5 поставке
+
+Comment[zh_CN]=Qt5 配置工具
+Name[zh_CN]=Qt5 设置
+
+Comment[zh_TW]=Qt5 設定工具
+Name[zh_TW]=Qt5 設定
+
+
+Exec=qt5ct
+Icon=preferences-desktop-theme
+Terminal=false
+Type=Application
+Categories=Settings;DesktopSettings;Qt;
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.h
new file mode 100644
index 00000000..1aecd741
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef QT5CT_H
+#define QT5CT_H
+
+#define QT5CT_VERSION_MAJOR 0
+#define QT5CT_VERSION_MINOR 33
+
+#define QT5CT_TOSTRING(s) #s
+#define QT5CT_STRINGIFY(s) QT5CT_TOSTRING(s)
+
+#define QT5CT_VERSION_INT (QT5CT_VERSION_MAJOR<<8 | QT5CT_VERSION_MINOR)
+#define QT5CT_VERSION_STR QT5CT_STRINGIFY(QT5CT_VERSION_MAJOR.QT5CT_VERSION_MINOR)
+
+#include <QString>
+#include <QStringList>
+
+class Qt5CT
+{
+public:
+ static QString configPath();
+ static QString configFile();
+ static QStringList iconPaths();
+ static QString userStyleSheetPath();
+ static QString sharedStyleSheetPath();
+ static QString userColorSchemePath();
+ static QString sharedColorSchemePath();
+ static QString systemLanguageID();
+
+private:
+ Qt5CT() {}
+};
+
+#endif // QT5CT_H
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.pro b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.pro
new file mode 100644
index 00000000..0f9724f1
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qt5ct.pro
@@ -0,0 +1,57 @@
+include(../../qt5ct.pri)
+
+TEMPLATE = app
+
+QT += widgets
+
+SOURCES += \
+ main.cpp \
+ mainwindow.cpp \
+ tabpage.cpp \
+ appearancepage.cpp \
+ fontspage.cpp \
+ qt5ct.cpp \
+ paletteeditdialog.cpp \
+ iconthemepage.cpp \
+ interfacepage.cpp \
+ fontconfigdialog.cpp \
+ qsspage.cpp \
+ qsseditordialog.cpp
+
+FORMS += \
+ mainwindow.ui \
+ appearancepage.ui \
+ fontspage.ui \
+ paletteeditdialog.ui \
+ iconthemepage.ui \
+ interfacepage.ui \
+ fontconfigdialog.ui \
+ previewform.ui \
+ qsspage.ui \
+ qsseditordialog.ui
+
+HEADERS += \
+ mainwindow.h \
+ tabpage.h \
+ appearancepage.h \
+ fontspage.h \
+ qt5ct.h \
+ paletteeditdialog.h \
+ iconthemepage.h \
+ interfacepage.h \
+ fontconfigdialog.h \
+ qsspage.h \
+ qsseditordialog.h
+
+!equals (DISABLE_WIDGETS,1) {
+ DEFINES += USE_WIDGETS
+}
+
+RESOURCES = translations/translations.qrc
+
+target.path = $$BINDIR
+
+desktop.files = qt5ct.desktop
+desktop.path = $$DATADIR/applications
+
+INSTALLS += target desktop
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/tabpage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/tabpage.cpp
new file mode 100644
index 00000000..251ce024
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/tabpage.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tabpage.h"
+
+TabPage::TabPage(QWidget *parent) : QWidget(parent)
+{
+}
diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/tabpage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/tabpage.h
new file mode 100644
index 00000000..ac285054
--- /dev/null
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/tabpage.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014-2017, Ilya Kotov <forkotov02@hotmail.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TABPAGE_H
+#define TABPAGE_H
+
+#include <QWidget>
+
+class TabPage : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit TabPage(QWidget *parent = 0);
+
+ virtual void writeSettings() = 0;
+};
+
+#endif // TABPAGE_H
bgstack15