diff --git a/app/bin/mytetra.qrc b/app/bin/mytetra.qrc
index 60c0e471c..b2c5e1303 100644
--- a/app/bin/mytetra.qrc
+++ b/app/bin/mytetra.qrc
@@ -85,6 +85,13 @@
resource/standartconfig/any/conf.ini
resource/standartconfig/any/editorconf.ini
resource/standartconfig/any/stylesheet.css
+ resource/standartconfig/any/styles/dark/pic/branch-closed.png
+ resource/standartconfig/any/styles/dark/pic/branch-end.png
+ resource/standartconfig/any/styles/dark/pic/branch-more.png
+ resource/standartconfig/any/styles/dark/pic/branch-open.png
+ resource/standartconfig/any/styles/dark/pic/vline.png
+ resource/standartconfig/any/styles/dark/stylesheet.css
+ resource/standartconfig/any/styles/light/stylesheet.css
resource/standartconfig/meego/conf.ini
resource/standartconfig/meego/editorconf.ini
resource/standartconfig/meego/stylesheet.css
diff --git a/app/bin/resource/standartconfig/any/styles/dark/pic/branch-closed.png b/app/bin/resource/standartconfig/any/styles/dark/pic/branch-closed.png
new file mode 100644
index 000000000..d9eb4af45
Binary files /dev/null and b/app/bin/resource/standartconfig/any/styles/dark/pic/branch-closed.png differ
diff --git a/app/bin/resource/standartconfig/any/styles/dark/pic/branch-end.png b/app/bin/resource/standartconfig/any/styles/dark/pic/branch-end.png
new file mode 100644
index 000000000..169983640
Binary files /dev/null and b/app/bin/resource/standartconfig/any/styles/dark/pic/branch-end.png differ
diff --git a/app/bin/resource/standartconfig/any/styles/dark/pic/branch-more.png b/app/bin/resource/standartconfig/any/styles/dark/pic/branch-more.png
new file mode 100644
index 000000000..357010887
Binary files /dev/null and b/app/bin/resource/standartconfig/any/styles/dark/pic/branch-more.png differ
diff --git a/app/bin/resource/standartconfig/any/styles/dark/pic/branch-open.png b/app/bin/resource/standartconfig/any/styles/dark/pic/branch-open.png
new file mode 100644
index 000000000..a22b9f4f7
Binary files /dev/null and b/app/bin/resource/standartconfig/any/styles/dark/pic/branch-open.png differ
diff --git a/app/bin/resource/standartconfig/any/styles/dark/pic/vline.png b/app/bin/resource/standartconfig/any/styles/dark/pic/vline.png
new file mode 100644
index 000000000..b9f0a1540
Binary files /dev/null and b/app/bin/resource/standartconfig/any/styles/dark/pic/vline.png differ
diff --git a/app/bin/resource/standartconfig/any/styles/dark/stylesheet.css b/app/bin/resource/standartconfig/any/styles/dark/stylesheet.css
new file mode 100644
index 000000000..9e6ca5ddc
--- /dev/null
+++ b/app/bin/resource/standartconfig/any/styles/dark/stylesheet.css
@@ -0,0 +1,169 @@
+QWidget {
+font: 10pt 'DejaVu Sans';
+ outline: 0;
+ color: white;
+ background-color: #373e4d; }
+QWidget::item:hover {
+ color: white;
+ background: #383C4A; }
+QWidget::item:selected {
+ color: white;
+ background: #383C4A; }
+QWidget::item:selected:active {
+ color: white;
+ background: #2d2f36; }
+QTreeView::item:open {
+ color: white; }
+QComboBox::drop-down:hover{
+ border-left-color: #ff80ff; }
+QComboBox:hover{
+ border: 1px solid #ff80ff; }
+QToolTip {
+ border: 1px solid #80ff80;
+ padding: 2px;
+ border-radius: 5px;
+ color: white;
+ background: #373e4d; }
+QTextEdit:focus,
+QTreeView:focus,
+QTableView:focus {
+ border: 1px solid #3e7c3e; }
+QTextEdit {
+ border: 1px solid #2f343f;
+ color: white;
+ background: #404759;
+ selection-color: #ff80ff;
+ selection-background-color: #2d2f36;
+ }
+QProgressBar {
+ border: solid;
+ color: grey;
+ background: #404759;
+ selection-background-color: #80ff80; }
+QCheckBox {
+ color: grey;
+ font-weight: bold;
+ border: 0px solid grey; }
+QCheckBox::indicator {
+ width: 0px;
+ background-color: transparent; }
+QCheckBox:unchecked {
+ color: gray;
+ background: #373e4d; }
+QCheckBox:checked {
+ color: #80ffff; }
+QToolBar,
+QLabel,
+QMenuBar,
+QDialog,
+QComboBox{
+ border-style: solid;
+ color: #80ff80;
+ background: #373e4d; }
+QComboBox:editable {
+ background: #404759; }
+QComboBox {
+ border: 1px solid gray;
+ border-radius: 3px;
+ padding: 1px 18px 1px 3px;
+ min-width: 6em; }
+QComboBox:!editable,
+QComboBox::drop-down:editable {
+ background: #373e4d; }
+QComboBox::drop-down {
+ width: 15px;
+ border-left-width: 1px;
+ border-left-color: darkgray;
+ border-left-style: solid;
+ border-top-right-radius: 3px;
+ border-bottom-right-radius: 3px; }
+QLineEdit {
+ border: 1px solid grey;
+ background: #404759; }
+QLineEdit:hover,
+QLineEdit:focus {
+ border: 1px solid #80ff80; }
+QPushButton:disabled{
+ color: grey;
+ background-color: #373e4d; }
+QPushButton {
+ background-color: #373e4d;
+ color: #80ff80;
+ font-weight: bold;
+ border-style: solid;
+ padding: 5px; }
+QToolButton {
+ background-color: #373e4d;
+ font-weight: bold;
+ border-style: solid;
+ padding: 5px; }
+QToolButton::hover,
+QToolButton:checked {
+ background-color: #404759; }
+QToolButton::pressed {
+ background-color: #2d2f36; }
+QToolBar {
+ icon-size: 14px;
+ padding: 1; }
+QTreeView::item,
+QTableView {
+ border: 1px solid #2f343f;
+ color: white;
+ background: #404759;
+}
+QTableView QTableCornerButton::section,
+QHeaderView::section:horizontal {
+ color: #5bf235;
+ border-style: solid;
+ height: 18px;
+ padding: 0px 3px 0px 6px;
+ background: #2f343f; }
+QHeaderView::section:vertical {
+ color: #5bf235;
+ border-style: solid;
+ width: 18px;
+ padding: 0px 3px 0px 6px;
+ background: #373e4d; }
+QTreeView::item {
+ border: 0px solid #2f343f; }
+QTreeView {
+ border: 1px solid #2f343f;
+ color: #5bf235;
+ background: #404759;
+ selection-background-color: transparent; }
+QTreeView::branch:has-siblings:!adjoins-item {
+ border-image: url(style/pic/vline.png) 0; }
+QTreeView::branch:has-siblings:adjoins-item {
+ border-image: url(style/pic/branch-more.png) 0; }
+QTreeView::branch:!has-children:!has-siblings:adjoins-item {
+ border-image: url(style/pic/branch-end.png) 0; }
+QTreeView::branch:closed:has-children:has-siblings,
+QTreeView::branch:has-children:!has-siblings:closed {
+ border-image: none;
+ image: url(style/pic/branch-closed.png); }
+QTreeView::branch:open:has-children:!has-siblings,
+QTreeView::branch:open:has-children:has-siblings{
+ border-image: none;
+ image: url(style/pic/branch-open.png); }
+QScrollBar:horizontal,
+QScrollBar:vertical {
+ background-color: transparent;
+ height: 8px;
+ width: 8px;
+ margin: 0px;
+ padding: 0px; }
+QScrollBar::handle:horizontal,
+QScrollBar::handle:vertical {
+ border: none;
+ min-width: 100px;
+ background-color: #2b2f36; }
+QScrollBar::add-line:horizontal,
+QScrollBar::sub-line:horizontal,
+QScrollBar::add-page:horizontal,
+QScrollBar::sub-page:horizontal,
+QScrollBar::add-line:vertical,
+QScrollBar::sub-line:vertical,
+QScrollBar::add-page:vertical,
+QScrollBar::sub-page:vertical {
+ width: 0px;
+ background-color: transparent; }
diff --git a/app/bin/resource/standartconfig/any/styles/light/stylesheet.css b/app/bin/resource/standartconfig/any/styles/light/stylesheet.css
new file mode 100644
index 000000000..cc34ad08f
--- /dev/null
+++ b/app/bin/resource/standartconfig/any/styles/light/stylesheet.css
@@ -0,0 +1,13 @@
+/* CSS style for any desktop OS */
+/* Set your Qt CSS style in this file */
+
+QToolBar, QToolButton, QPushButton
+{
+ icon-size: 16px; /* maximum icon size */
+}
+
+/*
+QToolButton {
+ padding: 0;
+}
+*/
diff --git a/app/bin/resource/translations/mytetra_ru.ts b/app/bin/resource/translations/mytetra_ru.ts
index 2fb37aed5..ecf451176 100644
--- a/app/bin/resource/translations/mytetra_ru.ts
+++ b/app/bin/resource/translations/mytetra_ru.ts
@@ -274,7 +274,42 @@ Please enable action logging in Tools -> Preferences -> Misc
Misc
- Разное
+
+ AppConfigPage_Appearance
+
+
+ Interface theme
+ Тема
+
+
+
+ Light
+ Светлая
+
+
+
+ Dark
+ Темная
+
+
+
+ Run MyTetra in a minimized window
+ Запускать MyTetra в свернутом окне
+
+
+
+ Hide detached windows if close main window
+ Сворачивать открепляемые окна при закрытии главного окна
+
+
+
+ Interface
+ Интерфейс
+
+
+
+ Windows behavior
+ Поведение
diff --git a/app/src/libraries/GlobalParameters.cpp b/app/src/libraries/GlobalParameters.cpp
index 94c5bf3fe..6cc6f2ccd 100644
--- a/app/src/libraries/GlobalParameters.cpp
+++ b/app/src/libraries/GlobalParameters.cpp
@@ -21,6 +21,7 @@
#include "libraries/WindowSwitcher.h"
#include "libraries/FixedParameters.h"
#include "libraries/helpers/DebugHelper.h"
+#include "libraries/helpers/DiskHelper.h"
#ifdef Q_OS_WIN32
#include "windows.h"
@@ -268,11 +269,23 @@ void GlobalParameters::createFirstProgramFiles(QString dirName)
}
-void GlobalParameters::createStyleSheetFile(QString dirName)
+void GlobalParameters::createStyleSheetFile(QString dirName, QString themeName)
{
QString targetOs=getTargetOs();
- QFile::copy(":/resource/standartconfig/"+targetOs+"/stylesheet.css", dirName+"/stylesheet.css");
- QFile::setPermissions(dirName+"/stylesheet.css", QFile::ReadUser | QFile::WriteUser);
+ if (targetOs == "any" && !themeName.isNull() && !themeName.isEmpty())
+ {
+ QString fromDir=":/resource/standartconfig/any/styles/"+themeName;
+ QString toDir=dirName+"/style";
+ DiskHelper::removeDirectory(toDir);
+ DiskHelper::copyDirectoryRecursively(fromDir, toDir, QFile::ReadUser | QFile::WriteUser);
+ }
+ else
+ {
+ QDir styleDir(dirName);
+ styleDir.mkdir("style");
+ QFile::copy(":/resource/standartconfig/"+targetOs+"/stylesheet.css", dirName+"/style/stylesheet.css");
+ QFile::setPermissions(dirName+"/style/stylesheet.css", QFile::ReadUser | QFile::WriteUser);
+ }
}
diff --git a/app/src/libraries/GlobalParameters.h b/app/src/libraries/GlobalParameters.h
index dc27d39d1..42a151e27 100644
--- a/app/src/libraries/GlobalParameters.h
+++ b/app/src/libraries/GlobalParameters.h
@@ -64,7 +64,7 @@ class GlobalParameters : public QObject
// Файл стилей может создаваться и после развертывания начальных файлов MyTetra
// Так как в более старых версиях MyTetra его еще не было
- void createStyleSheetFile(QString dirName);
+ void createStyleSheetFile(QString dirName, QString themeName=NULL);
public:
// Указание на обрабатываемую панель инструментов редактора текста
diff --git a/app/src/libraries/helpers/CssHelper.cpp b/app/src/libraries/helpers/CssHelper.cpp
index 5312338f8..a28f75d10 100644
--- a/app/src/libraries/helpers/CssHelper.cpp
+++ b/app/src/libraries/helpers/CssHelper.cpp
@@ -7,9 +7,11 @@
#include "CssHelper.h"
#include "libraries/GlobalParameters.h"
+#include "models/appConfig/AppConfig.h"
extern GlobalParameters globalParameters;
+extern AppConfig mytetraConfig;
CssHelper::CssHelper()
@@ -54,7 +56,18 @@ QString CssHelper::replaceCssMetaIconSize(QString styleText)
void CssHelper::setCssStyle()
{
- QString csspath = globalParameters.getWorkDirectory()+"/stylesheet.css";
+ QString dirName=globalParameters.getWorkDirectory();
+
+ // Если файл стилей есть по старому пути, переносим его в каталог style
+ QFile file(dirName+"/stylesheet.css");
+ if (file.exists())
+ {
+ QDir styleDir(dirName);
+ styleDir.mkdir("style");
+ file.rename(dirName+"/style/stylesheet.css");
+ }
+
+ QString csspath = dirName+"/style/stylesheet.css";
QFile css(csspath);
@@ -64,7 +77,14 @@ void CssHelper::setCssStyle()
if(!openResult)
{
qDebug() << "Stylesheet not found in " << csspath << ". Create new css file.";
- globalParameters.createStyleSheetFile( globalParameters.getWorkDirectory() );
+
+ QString themeName;
+ switch (mytetraConfig.getInterfaceTheme())
+ {
+ case AppConfig::Light: themeName="light"; break;
+ case AppConfig::Dark: themeName="dark"; break;
+ }
+ globalParameters.createStyleSheetFile( globalParameters.getWorkDirectory(), themeName);
}
css.close();
diff --git a/app/src/libraries/helpers/DiskHelper.cpp b/app/src/libraries/helpers/DiskHelper.cpp
index 4ec526ec6..526b60d22 100644
--- a/app/src/libraries/helpers/DiskHelper.cpp
+++ b/app/src/libraries/helpers/DiskHelper.cpp
@@ -187,6 +187,32 @@ bool DiskHelper::copyDirectory(const QString &fromName, const QString &toName)
}
+// Копирование содержимого директории
+// Рекурсивно вместе с подкаталогами
+bool DiskHelper::copyDirectoryRecursively(const QString &fromName, const QString &toName, QFile::Permissions permissionSpec)
+{
+ QDir fromDir(fromName);
+ if (!fromDir.exists())
+ return false;
+ QDir toDir(toName);
+ if (!toDir.exists())
+ toDir.mkpath(".");
+
+ foreach (QString dirName, fromDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
+ QString destPath = toName + QDir::separator() + dirName;
+ fromDir.mkpath(destPath);
+ copyDirectoryRecursively(fromName+ QDir::separator() + dirName, destPath, permissionSpec);
+ }
+
+ foreach (QString fileName, fromDir.entryList(QDir::Files)) {
+ QString destPath = toName + QDir::separator() + fileName;
+ QFile::copy(fromName + QDir::separator() + fileName, destPath);
+ QFile::setPermissions(destPath, permissionSpec);
+ }
+ return true;
+}
+
+
// Получение списка файлов с их содержимым в указанной директории
QMap DiskHelper::getFilesFromDirectory(QString dirName, QString fileMask)
{
diff --git a/app/src/libraries/helpers/DiskHelper.h b/app/src/libraries/helpers/DiskHelper.h
index 6e12f6b35..5eddaca00 100644
--- a/app/src/libraries/helpers/DiskHelper.h
+++ b/app/src/libraries/helpers/DiskHelper.h
@@ -1,6 +1,7 @@
#ifndef DISKHELPER_H
#define DISKHELPER_H
+#include
#include
#include
#include
@@ -19,6 +20,7 @@ class DiskHelper
static QString createTempDirectory(void);
static bool removeDirectory(const QString &dirName);
static bool copyDirectory(const QString &fromName, const QString &toName);
+ static bool copyDirectoryRecursively(const QString &fromName, const QString &toName, QFile::Permissions permissionSpec);
static QMap getFilesFromDirectory(QString dirName, QString fileMask);
static bool saveFilesToDirectory(QString dirName, QMap fileList);
diff --git a/app/src/models/appConfig/AppConfig.cpp b/app/src/models/appConfig/AppConfig.cpp
index 5cc27d700..7762c11c1 100644
--- a/app/src/models/appConfig/AppConfig.cpp
+++ b/app/src/models/appConfig/AppConfig.cpp
@@ -963,6 +963,30 @@ void AppConfig::setDockableWindowsBehavior(QString mode)
}
+// Тема оформления
+AppConfig::InterfaceTheme AppConfig::getInterfaceTheme()
+{
+ QString themeName = get_parameter("theme");
+
+ InterfaceTheme theme;
+ if (themeName == "dark") theme=InterfaceTheme::Dark;
+ else theme=InterfaceTheme::Light;
+
+ return theme;
+}
+
+void AppConfig::setInterfaceTheme(InterfaceTheme theme)
+{
+ QString themeName;
+ switch (theme)
+ {
+ case InterfaceTheme::Light: themeName="light"; break;
+ case InterfaceTheme::Dark: themeName="dark"; break;
+ }
+ conf->setValue("theme", themeName);
+}
+
+
// --------------------
// Номер версии конфига
// --------------------
@@ -1127,6 +1151,7 @@ void AppConfig::update_version_process(void)
parameterFunctions << &AppConfig::get_parameter_table_36;
parameterFunctions << &AppConfig::get_parameter_table_37;
parameterFunctions << &AppConfig::get_parameter_table_38;
+ parameterFunctions << &AppConfig::get_parameter_table_39;
for(int i=1; i
#include
#include
#include "AppConfigPage_Appearance.h"
+
#include "models/appConfig/AppConfig.h"
#include "libraries/GlobalParameters.h"
+#include "libraries/helpers/DiskHelper.h"
#include "libraries/wyedit/EditorShowTextDispatcher.h"
@@ -29,6 +32,16 @@ void AppConfigPage_Appearance::setupUi()
{
qDebug() << "Create appearance config page";
+ // Выбор темы интерфейса
+ themeLabel=new QLabel(this);
+ themeLabel->setText(tr("Interface theme"));
+
+ theme=new MtComboBox(this);
+ theme->setMinimumContentsLength(2);
+ theme->addItem(tr("Light"));
+ theme->addItem(tr("Dark"));
+ theme->setCurrentIndex((int)mytetraConfig.getInterfaceTheme());
+
// Настройка запуска MyTetra в свернутом окне
runInMinimizedWindow=new QCheckBox(this);
runInMinimizedWindow->setText(tr("Run MyTetra in a minimized window"));
@@ -50,6 +63,21 @@ void AppConfigPage_Appearance::setupSignals()
void AppConfigPage_Appearance::assembly()
{
+ // Группировщик настроек интерфейса
+ interfaceBox=new QGroupBox(this);
+ interfaceBox->setTitle(tr("Interface"));
+
+ // Выбор темы
+ QHBoxLayout *themeLayout=new QHBoxLayout();
+ themeLayout->addWidget(theme);
+
+ // Виджеты вставляются в группировщик настроек курсора при навигации по истории
+ QGridLayout *interfaceLayout = new QGridLayout;
+ interfaceLayout->addWidget(themeLabel,0,0);
+ interfaceLayout->addLayout(themeLayout,0,1);
+ interfaceLayout->setColumnStretch(1,100);
+ interfaceBox->setLayout(interfaceLayout);
+
// Группировщик виджетов настройки поведения окна
behaviorBox=new QGroupBox(this);
behaviorBox->setTitle(tr("Windows behavior"));
@@ -62,6 +90,7 @@ void AppConfigPage_Appearance::assembly()
// Собирается основной слой
QVBoxLayout *centralLayout=new QVBoxLayout();
+ centralLayout->addWidget(interfaceBox);
centralLayout->addWidget(behaviorBox);
centralLayout->addStretch();
@@ -79,6 +108,18 @@ int AppConfigPage_Appearance::applyChanges()
int result=0;
+ // Если был изменена тема
+ if(mytetraConfig.getInterfaceTheme()!=theme->currentIndex())
+ {
+ mytetraConfig.setInterfaceTheme((AppConfig::InterfaceTheme)theme->currentIndex());
+
+ // Удаляем существующий стиль, чтобы при следующем запуске установить новый
+ QString dirName=globalParameters.getWorkDirectory();
+ DiskHelper::removeDirectory(dirName+"/style");
+
+ result=1;
+ }
+
// Сохраняется настройка режима запуска MyTetra - обычный или свернутый
if(mytetraConfig.get_runinminimizedwindow()!=runInMinimizedWindow->isChecked())
{
diff --git a/app/src/views/appConfigWindow/AppConfigPage_Appearance.h b/app/src/views/appConfigWindow/AppConfigPage_Appearance.h
index b17d2db4e..fa523ef10 100644
--- a/app/src/views/appConfigWindow/AppConfigPage_Appearance.h
+++ b/app/src/views/appConfigWindow/AppConfigPage_Appearance.h
@@ -4,12 +4,16 @@
#include
#include
#include
+#include
#include "ConfigPage.h"
+#include "libraries/MtComboBox.h"
class AppConfigPage_Appearance : public ConfigPage
{
+ Q_OBJECT
+
public:
AppConfigPage_Appearance(QWidget *parent = nullptr);
virtual ~AppConfigPage_Appearance();
@@ -24,6 +28,10 @@ class AppConfigPage_Appearance : public ConfigPage
// Объединяющая рамка
QGroupBox *behaviorBox;
+ QGroupBox *interfaceBox;
+
+ QLabel *themeLabel;
+ MtComboBox *theme;
QCheckBox *runInMinimizedWindow; // Разрешен ли запуск в свернутом окне
QCheckBox *dockableWindowsBehavior; // Поведение открепляемых окон