diff options
Diffstat (limited to 'src-qt5/core/lumina-theme-engine')
31 files changed, 1641 insertions, 139 deletions
diff --git a/src-qt5/core/lumina-theme-engine/desktop_qss/DarkGlass.qss b/src-qt5/core/lumina-theme-engine/desktop_qss/DarkGlass.qss new file mode 100644 index 00000000..2de9fefa --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/desktop_qss/DarkGlass.qss @@ -0,0 +1,91 @@ +QWidget#LuminaBootSplash{ + background: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 palette(dark), stop:1 palette(mid) ); + border-radius: 5px; +} + +LDPlugin#applauncher{ + background-color: transparent; + border: none; +} +LDPlugin#applauncher QToolButton, LDPlugin, LDPlugin#desktopview QListWidget::item{ + background-color: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(5, 5, 5, 30), stop:1 rgba(2, 2, 2, 70)); + border-width: 3px; + border-style: solid; + border-radius: 5px; + border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(0, 0, 0, 30), stop:0.724868 rgba(0, 0, 0, 60), stop:1 rgba(0, 0, 0, 10)); + border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + color: white; +} + +LDPlugin#applauncher QToolButton:hover, LDPlugin#desktopview QListWidget::item:hover{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(highlight), stop: 1 transparent); + color: palette(highlighted-text); + border-width: 3px; + border-style: solid; + border-radius: 5px; + border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); +} +QWidget#LuminaPanelColor{ + background: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(2, 2, 2, 60), stop:1 rgba(0, 0, 0, 110)); + border-radius: 3px; +} + +/*Special taskmanager window buttons: based on window state*/ +LTBWidget, LPanel QToolButton, QDialog#LeaveDialog QToolButton{ + border: 1px solid transparent; + border-radius: 3px; + background: transparent; +} +LTBWidget::menu-indicator{ image: none; } /*disable the menu arrow*/ +LTBWidget#WindowVisible{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(mid), stop: 1 transparent); +} +LTBWidget#WindowInvisible{ + background: transparent; +} +LTBWidget#WindowActive{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(midlight), stop: 1 transparent); +} +LTBWidget#WindowAttention{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(highlight), stop: 1 transparent); +} +LTBWidget:hover, LTBWidget#WindowVisible:hover, LTBWidget#WindowInvisible:hover, LTBWidget#WindowActive:hover, LTBWidget#WindowAttention:hover, QToolButton:hover, QDialog#LeaveDialog QToolButton:hover{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(highlight), stop: 1 transparent); + color: palette(highlighted-text); + border-width: 1px; + border-style: solid; + border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); + border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(0,0,0, 30), stop:0.724868 rgba(0,0,0, 60), stop:1 rgba(0,0,0, 10)); +} + +/* CALENDER WIDGET */ + /* (This is a special hack since there is no official support for stylesheets for this widget) */ + QCalendarWidget QWidget#qt_calendar_navigationbar{ + background-color: palette(base); + } +QCalendarWidget QWidget{ + background-color: palette(base); + alternate-background-color: palette(alternate-base); + color: palette(text); +} +QCalendarWidget QAbstractButton{ + background-color: transparent; +} +QCalendarWidget QAbstractButton::menu-indicator{ + image: none; +} +QCalendarWidget QAbstractItemView{ + selection-background-color: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(3, 4, 4, 20), stop:1 rgba(0, 0, 0, 100)); + selection-color: palette(highlighted-text); +} +QCalendarWidget QWidget#qt_calendar_calendarview{ + background-color: palette(dark); + border: none; +} diff --git a/src-qt5/core/lumina-theme-engine/desktop_qss/Glass.qss b/src-qt5/core/lumina-theme-engine/desktop_qss/Glass.qss new file mode 100644 index 00000000..502c0a44 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/desktop_qss/Glass.qss @@ -0,0 +1,91 @@ +QWidget#LuminaBootSplash{ + background: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 palette(base), stop:1 palette(light) ); + border-radius: 5px; +} + +LDPlugin#applauncher{ + background-color: transparent; + border: none; +} +LDPlugin#applauncher QToolButton, LDPlugin, LDPlugin#desktopview QListWidget::item{ + background-color: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(250, 250, 250, 30), stop:1 rgba(252, 252, 252, 70)); + border-width: 3px; + border-style: solid; + border-radius: 5px; + border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + color: white; +} + +LDPlugin#applauncher QToolButton:hover, LDPlugin#desktopview QListWidget::item:hover{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(highlight), stop: 1 transparent); + color: palette(highlighted-text); + border-width: 3px; + border-style: solid; + border-radius: 5px; + border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); +} +QWidget#LuminaPanelColor{ + background: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(252, 252, 252, 60), stop:1 rgba(255,255,255, 110)); + border-radius: 3px; +} + +/*Special taskmanager window buttons: based on window state*/ +LTBWidget, LPanel QToolButton, QDialog#LeaveDialog QToolButton{ + border: 1px solid transparent; + border-radius: 3px; + background: transparent; +} +LTBWidget::menu-indicator{ image: none; } /*disable the menu arrow*/ +LTBWidget#WindowVisible{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(mid), stop: 1 transparent); +} +LTBWidget#WindowInvisible{ + background: transparent; +} +LTBWidget#WindowActive{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(dark), stop: 1 transparent); +} +LTBWidget#WindowAttention{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(highlight), stop: 1 transparent); +} +LTBWidget:hover, LTBWidget#WindowVisible:hover, LTBWidget#WindowInvisible:hover, LTBWidget#WindowActive:hover, LTBWidget#WindowAttention:hover, QToolButton:hover, QDialog#LeaveDialog QToolButton:hover{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1.1, stop: 0.1 palette(highlight), stop: 1 transparent); + color: palette(highlighted-text); + border-width: 1px; + border-style: solid; + border-top-color: qradialgradient(spread:pad, cx:0.5, cy:1, radius:0.5, fx:0.5, fy:1, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-bottom-color: qradialgradient(spread:pad, cx:0.5, cy:0, radius:0.5, fx:0.5, fy:0, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-left-color: qradialgradient(spread:pad, cx:1, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); + border-right-color: qradialgradient(spread:pad, cx:0, cy:0.5, radius:0.5, fx:1, fy:0.5, stop:0 rgba(255,255,255, 30), stop:0.724868 rgba(255,255,255, 60), stop:1 rgba(255,255,255, 10)); +} + +/* CALENDER WIDGET */ + /* (This is a special hack since there is no official support for stylesheets for this widget) */ + QCalendarWidget QWidget#qt_calendar_navigationbar{ + background-color: palette(base); + } +QCalendarWidget QWidget{ + background-color: palette(base); + alternate-background-color: palette(alternate-base); + color: palette(text); +} +QCalendarWidget QAbstractButton{ + background-color: transparent; +} +QCalendarWidget QAbstractButton::menu-indicator{ + image: none; +} +QCalendarWidget QAbstractItemView{ + selection-background-color: qradialgradient(spread:reflect, cx:0.113757, cy:0.875, radius:0.7, fx:0.045, fy:0.954545, stop:0 rgba(253, 254, 254, 20), stop:1 rgba(255,255,255, 100)); + selection-color: palette(highlighted-text); +} +QCalendarWidget QWidget#qt_calendar_calendarview{ + background-color: palette(light); + border: none; +} diff --git a/src-qt5/core/lumina-theme-engine/lthemeengine.pri b/src-qt5/core/lumina-theme-engine/lthemeengine.pri index 40202045..781527c1 100644 --- a/src-qt5/core/lumina-theme-engine/lthemeengine.pri +++ b/src-qt5/core/lumina-theme-engine/lthemeengine.pri @@ -3,7 +3,7 @@ QT *= core gui widgets x11extras network error("Use Qt 5.4.0 or higher.") } include(../../OS-detect.pri) - +include(../libLumina/LDesktopUtils.pri) CONFIG *= c++11 #Install paths diff --git a/src-qt5/core/lumina-theme-engine/lumina-theme-engine.pro b/src-qt5/core/lumina-theme-engine/lumina-theme-engine.pro index d91091d3..1e8b2ca4 100644 --- a/src-qt5/core/lumina-theme-engine/lumina-theme-engine.pro +++ b/src-qt5/core/lumina-theme-engine/lumina-theme-engine.pro @@ -3,9 +3,16 @@ include(../../OS-detect.pri) TEMPLATE = subdirs SUBDIRS += src/lthemeengine-qtplugin \ src/lthemeengine-style \ - src/lthemeengine + src/lthemeengine \ + src/lthemeengine-sstest colors.files = colors/*.conf colors.path = $${L_SHAREDIR}/lthemeengine/colors -INSTALLS += colors +qss.files = qss/*.qss +qss.path = $${L_SHAREDIR}/lthemeengine/qss + +dqss.files = desktop_qss/*.qss +dqss.path = $${L_SHAREDIR}/lthemeengine/desktop_qss + +INSTALLS += colors qss dqss diff --git a/src-qt5/core/lumina-theme-engine/qss/scrollbar-simple.qss b/src-qt5/core/lumina-theme-engine/qss/scrollbar-simple.qss new file mode 100644 index 00000000..d0c9b448 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/qss/scrollbar-simple.qss @@ -0,0 +1,30 @@ +/* SCROLLBARS (NOTE: Changing 1 subcontrol means you have to change all of them)*/ +QScrollBar{ + background: palette(alternate-base); +} +QScrollBar:horizontal{ + margin: 0px 0px 0px 0px; +} +QScrollBar:vertical{ + margin: 0px 0px 0px 0px; +} +QScrollBar::handle{ + background: palette(base); + border: 1px solid transparent; + border-radius: 1px; +} +QScrollBar::handle:hover, QScrollBar::add-line:hover, QScrollBar::sub-line:hover{ + background: palette(highlight); +} +QScrollBar::add-line{ +subcontrol-origin: none; +} +QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical{ +height: 0px; +} +QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal{ +width: 0px; +} +QScrollBar::sub-line{ +subcontrol-origin: none; +} diff --git a/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss b/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss new file mode 100644 index 00000000..a9b165a6 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/qss/sliders-simple.qss @@ -0,0 +1,70 @@ +/* SLIDERS */ +QSlider::groove:horizontal { +border: 1px solid palette(mid); +background: palette(alternate-window); +height: 10px; +border-radius: 3px; +} +QSlider::groove:vertical { +border: 1px solid palette(mid); +background: palette(alternate-window); +width: 10px; +border-radius: 3px; +} +QSlider::sub-page:horizontal { +background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, + stop: 0 transparent, stop: 1 palette(highlight) ); +border: 1px solid transparent; +height: 10px; +border-radius: 3px; +} +QSlider::add-page:vertical { +background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, + stop: 0 transparent, stop: 1 palette(highlight) ); +border: 1px solid transparent; +width: 10px; +border-radius: 3px; +} +QSlider::add-page:horizontal{ +background: palette(alternate-window); +border: 1px solid transparent; +height: 10px; +border-radius: 3px; +} +QSlider::sub-page:vertical{ +background: palette(alternate-window); +border: 1px solid transparent; +width: 10px; +border-radius: 3px; +} +QSlider::handle:horizontal{ +background: palette(mid); +border: 1px solid palette(mid); +width: 1ex; +border-radius: 1px; +} +QSlider::handle:vertical{ +background: palette(mid); +border: 1px solid palette(mid); +height: 1ex; +border-radius: 1px; +} +QSlider::handle:horizontal:hover, QSlider::handle:vertical:hover{ +border: 1px solid palette(highlight); +background: palette(highlight); +} + +QSlider::sub-page:horizontal:disabled { +background: palette(highlight); +border-color: palette(highlight); +} + +QSlider::add-page:horizontal:disabled { +background: palette(highlight); +border-color: palette(highlight); +} + +QSlider::handle:horizontal:disabled { +background: palette(alternate-window); +border: 1px solid palette(highlight); +} diff --git a/src-qt5/core/lumina-theme-engine/qss/tooltip-simple.qss b/src-qt5/core/lumina-theme-engine/qss/tooltip-simple.qss new file mode 100644 index 00000000..9bee3e08 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/qss/tooltip-simple.qss @@ -0,0 +1,7 @@ +QToolTip{ + background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 palette(window), stop: 1 palette(alternate-window)); + border-radius: 3px; + border: 1px solid palette(highlight); + padding: 1px; + color: palette(text); +} diff --git a/src-qt5/core/lumina-theme-engine/qss/traynotification-simple.qss b/src-qt5/core/lumina-theme-engine/qss/traynotification-simple.qss new file mode 100644 index 00000000..43aff087 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/qss/traynotification-simple.qss @@ -0,0 +1,4 @@ +QBalloonTip{ +background-color: palette(base); +color: palette(text); +} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp index 453bde1d..670e1c9c 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.cpp @@ -16,6 +16,8 @@ #include <QFile> #include <QFileSystemWatcher> +#include <stdlib.h> + #include <lthemeengine/lthemeengine.h> #include "lthemeengineplatformtheme.h" #if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)) && !defined(QT_NO_DBUS) @@ -130,20 +132,38 @@ void lthemeenginePlatformTheme::applySettings(){ if(m_customPalette){ qApp->setPalette(*m_customPalette); } else{ qApp->setPalette(qApp->style()->standardPalette()); } } - //do not override application style - if(m_prevStyleSheet == qApp->styleSheet()){ qApp->setStyleSheet(m_userStyleSheet); } - else{ qCDebug(llthemeengine) << "custom style sheet is disabled";} - m_prevStyleSheet = m_userStyleSheet; + //do not override application style if one is already set by the app itself + QString orig = qApp->styleSheet(); + if(orig.startsWith(m_oldStyleSheet)){ orig = orig.remove(m_oldStyleSheet); } + qApp->setStyleSheet(m_userStyleSheet+orig); //make sure the app style has higher priority than ours + m_oldStyleSheet = m_userStyleSheet; + } #endif QGuiApplication::setFont(m_generalFont); //apply font + bool ithemechange = m_iconTheme != QIcon::themeName(); QIcon::setThemeName(m_iconTheme); //apply icons + //See if we need to reload the application icon from the new theme + if(ithemechange){ + QString appIcon = qApp->windowIcon().name(); + if(!appIcon.isEmpty() && QIcon::hasThemeIcon(appIcon)){ qApp->setWindowIcon(QIcon::fromTheme(appIcon)); } + QWindowList wins = qApp->topLevelWindows(); + for(int i=0; i<wins.length(); i++){ + QString winIcon = wins[i]->icon().name(); + if(!winIcon.isEmpty() && QIcon::hasThemeIcon(winIcon)){ wins[i]->setIcon(QIcon::fromTheme(winIcon)); } + } + } + bool cthemechange = m_cursorTheme != QString(getenv("X_CURSOR_THEME")); + setenv("X_CURSOR_THEME", m_cursorTheme.toLocal8Bit().data(), 1); + //qDebug() << "Icon Theme Change:" << m_iconTheme << QIcon::themeSearchPaths(); if(m_customPalette && m_usePalette){ QGuiApplication::setPalette(*m_customPalette); } //apply palette #ifdef QT_WIDGETS_LIB if(hasWidgets()){ + QEvent et(QEvent::ThemeChange); + QEvent ec(QEvent::CursorChange); foreach (QWidget *w, qApp->allWidgets()){ - QEvent e(QEvent::ThemeChange); - QApplication::sendEvent(w, &e); + if(ithemechange){ QApplication::sendEvent(w, &et); } + if(cthemechange){ QApplication::sendEvent(w, &ec); } } } #endif @@ -156,13 +176,13 @@ void lthemeenginePlatformTheme::createFSWatcher(){ watcher->addPath(lthemeengine::configPath()); QTimer *timer = new QTimer(this); timer->setSingleShot(true); - timer->setInterval(3000); + timer->setInterval(500); connect(watcher, SIGNAL(directoryChanged(QString)), timer, SLOT(start())); connect(timer, SIGNAL(timeout()), SLOT(updateSettings())); } void lthemeenginePlatformTheme::updateSettings(){ - qCDebug(llthemeengine) << "updating settings.."; + //qCDebug(llthemeengine) << "updating settings.."; readSettings(); applySettings(); } @@ -180,6 +200,7 @@ void lthemeenginePlatformTheme::readSettings(){ QString schemePath = settings.value("color_scheme_path","airy").toString(); m_customPalette = new QPalette(loadColorScheme(schemePath)); } + m_cursorTheme = settings.value("cursor_theme","").toString(); m_iconTheme = settings.value("icon_theme", "material-design-light").toString(); settings.endGroup(); settings.beginGroup("Fonts"); @@ -211,7 +232,10 @@ void lthemeenginePlatformTheme::readSettings(){ } //load style sheets #ifdef QT_WIDGETS_LIB - QStringList qssPaths = settings.value("stylesheets").toStringList(); + QStringList qssPaths; + if(qApp->applicationFilePath().section("/",-1).startsWith("lumina-desktop") ){ qssPaths << settings.value("desktop_stylesheets").toStringList(); } + qssPaths << settings.value("stylesheets").toStringList(); + //qDebug() << "Loaded Stylesheets:" << qApp->applicationName() << qssPaths; m_userStyleSheet = loadStyleSheets(qssPaths); #endif settings.endGroup(); @@ -224,6 +248,7 @@ bool lthemeenginePlatformTheme::hasWidgets(){ #endif QString lthemeenginePlatformTheme::loadStyleSheets(const QStringList &paths){ + //qDebug() << "Loading Stylesheets:" << paths; QString content; foreach (QString path, paths){ if(!QFile::exists(path)){ continue; } diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.h index 17323328..f521d457 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.h +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-qtplugin/lthemeengineplatformtheme.h @@ -66,7 +66,7 @@ private: #endif QString loadStyleSheets(const QStringList &paths); QPalette loadColorScheme(QString filePath); - QString m_style, m_iconTheme, m_userStyleSheet, m_prevStyleSheet; + QString m_style, m_iconTheme, m_userStyleSheet, m_oldStyleSheet, m_cursorTheme; QPalette *m_customPalette = nullptr; QFont m_generalFont, m_fixedFont; int m_doubleClickInterval; diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/lthemeengine-sstest.pro b/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/lthemeengine-sstest.pro new file mode 100644 index 00000000..fadc6fcb --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/lthemeengine-sstest.pro @@ -0,0 +1,11 @@ +include(../../lthemeengine.pri) +TEMPLATE = app +QT *= widgets + +SOURCES += \ + main.cpp + +TARGET = lthemeengine-sstest +target.path = $${L_BINDIR} + +INSTALLS += target diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/main.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/main.cpp new file mode 100644 index 00000000..bdab0a30 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine-sstest/main.cpp @@ -0,0 +1,18 @@ +#include <QApplication> +//#include <QDebug> +#include <QWidget> + +#include <LUtils.h> + +int main(int argc, char **argv){ + if(argc<2){ return 1; } //error + unsetenv("QT_QPA_PLATFORMTHEME"); //Make sure we are not testing anything related to the current theme engine + QString stylesheet = LUtils::readFile(argv[1]).join("\n"); + //qDebug() << "Found Stylesheet:" << stylesheet; + QApplication app(argc, argv); + app.setStyleSheet(stylesheet); + //qDebug() << " Using Stylesheet:" << app.styleSheet(); + QWidget tmp(0,Qt::SplashScreen | Qt::BypassWindowManagerHint); + tmp.show(); //needed to actually run the parser on the stylesheet (unused/unchecked otherwise) + return 0; +} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.cpp index 04ca6a0b..98f9c865 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.cpp @@ -6,6 +6,8 @@ #include <QMessageBox> #include <QMenu> #include <QIcon> +#include <QTimer> + #include "lthemeengine.h" #include "appearancepage.h" #include "paletteeditdialog.h" @@ -81,6 +83,8 @@ void AppearancePage::createColorScheme(){ QString schemePath = lthemeengine::userColorSchemePath() + "/" + name; createColorScheme(schemePath, palette()); m_ui->colorSchemeComboBox->addItem(name.section('.',0,0), schemePath); + m_ui->colorSchemeComboBox->setCurrentIndex( m_ui->colorSchemeComboBox->count()-1); + QTimer::singleShot(10, this, SLOT(changeColorScheme()) ); } void AppearancePage::changeColorScheme(){ @@ -125,6 +129,8 @@ void AppearancePage::copyColorScheme(){ QString newPath = lthemeengine::userColorSchemePath() + "/" + name; QFile::copy(m_ui->colorSchemeComboBox->currentData().toString(), newPath); m_ui->colorSchemeComboBox->addItem(name.section('.',0,0), newPath); + m_ui->colorSchemeComboBox->setCurrentIndex( m_ui->colorSchemeComboBox->count()-1); + QTimer::singleShot(10, this, SLOT(changeColorScheme()) ); } void AppearancePage::renameColorScheme(){ @@ -189,6 +195,10 @@ void AppearancePage::readSettings(){ m_ui->styleComboBox->setCurrentText(style); m_ui->customPaletteButton->setChecked(settings.value("custom_palette", false).toBool()); QString colorSchemePath = settings.value("color_scheme_path").toString(); + if(colorSchemePath.contains("..") || colorSchemePath.contains("//") ){ + //Make this an absolute path for comparison later + colorSchemePath = QFileInfo(colorSchemePath).absoluteFilePath(); + } QDir("/").mkpath(lthemeengine::userColorSchemePath()); findColorSchemes( QStringList() << lthemeengine::userColorSchemePath() << lthemeengine::sharedColorSchemePath()); if(m_ui->colorSchemeComboBox->count() == 0){ diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.ui index cd442930..91b65245 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.ui +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/appearancepage.ui @@ -161,9 +161,15 @@ <property name="text"> <string>...</string> </property> + <property name="icon"> + <iconset theme="view-more-vertical"/> + </property> <property name="popupMode"> <enum>QToolButton::InstantPopup</enum> </property> + <property name="autoRaise"> + <bool>true</bool> + </property> <property name="arrowType"> <enum>Qt::NoArrow</enum> </property> diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.cpp new file mode 100644 index 00000000..1d84164f --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.cpp @@ -0,0 +1,139 @@ +#include <QSettings> +#include <QFileInfo> +#include <QFileInfoList> +#include <QDir> +#include <QTreeWidgetItem> +#include <QImageReader> +#include <QLocale> +#include "lthemeengine.h" +#include "cursorthemepage.h" +#include "ui_cursorthemepage.h" + +CursorThemePage::CursorThemePage(QWidget *parent) : TabPage(parent), m_ui(new Ui::CursorThemePage){ + m_ui->setupUi(this); + loadThemes(); + readSettings(); +} + +CursorThemePage::~CursorThemePage(){ + delete m_ui; +} + +void CursorThemePage::writeSettings(){ + QSettings settings(lthemeengine::configFile(), QSettings::IniFormat); + QTreeWidgetItem *item = m_ui->treeWidget->currentItem(); + if(item){ + settings.setValue("Appearance/cursor_theme", item->data(3, Qt::UserRole)); + lthemeengine::setCursorTheme(item->data(3, Qt::UserRole).toString() ); + } +} + +void CursorThemePage::readSettings(){ + QSettings settings(lthemeengine::configFile(), QSettings::IniFormat); + QString name = settings.value("Appearance/cursor_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 CursorThemePage::loadThemes(){ + /*QFileInfoList themeFileList; + foreach(QString path, lthemeengine::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()); + }*/ + QStringList themes = lthemeengine::availableSystemCursors(); + for(int i=0; i<themes.length(); i++){ loadTheme(themes[i]); } +} + +void CursorThemePage::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; + name = comment = path.section("/",-1); + /*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, 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 CursorThemePage::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/cursorthemepage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.h new file mode 100644 index 00000000..e221520b --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.h @@ -0,0 +1,29 @@ +#ifndef CURSORTHEMEPAGE_H +#define CURSORTHEMEPAGE_H + +#include <QIcon> +#include "tabpage.h" + +namespace Ui { +class CursorThemePage; +} + +class CursorThemePage : public TabPage +{ + Q_OBJECT + +public: + explicit CursorThemePage(QWidget *parent = 0); + ~CursorThemePage(); + + void writeSettings(); + +private: + void readSettings(); + void loadThemes(); + void loadTheme(const QString &path); + QIcon findIcon(const QString &themePath, int size, const QString &name); + Ui::CursorThemePage *m_ui; +}; + +#endif // ICONTHEMEPAGE_H diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.ui new file mode 100644 index 00000000..3e0a5da1 --- /dev/null +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.ui @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>CursorThemePage</class> + <widget class="QWidget" name="CursorThemePage"> + <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/iconthemepage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.cpp index 1a09ac0d..7ed54f02 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.cpp @@ -72,7 +72,7 @@ void IconThemePage::loadTheme(const QString &path){ config.endGroup(); QIcon icon1 = findIcon(path, 24, "document-save"); QIcon icon2 = findIcon(path, 24, "document-print"); - QIcon icon3 = findIcon(path, 24, "media-playback-stop"); + QIcon icon3 = findIcon(path, 24, "document-edit"); QTreeWidgetItem *item = new QTreeWidgetItem(); item->setIcon(0, icon1); item->setIcon(1, icon2); @@ -97,7 +97,7 @@ QIcon IconThemePage::findIcon(const QString &themePath, int size, const QString config.endGroup(); foreach (QString dir, dirs){ config.beginGroup(dir); - if(config.value("Size").toInt() == size){ + if(config.value("Size").toInt() == size || config.value("Type").toString().toLower()=="scalable"){ QDir iconDir = QFileInfo(themePath).path() + "/" + dir; iconDir.setFilter(QDir::Files); iconDir.setNameFilters(QStringList () << name + ".*"); diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp index fdeb8966..cb491aa6 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp @@ -8,6 +8,19 @@ #include <QDebug> +QStringList lthemeengine::readFile(QString filepath){ + QStringList out; + QFile file(filepath); + if(file.open(QIODevice::Text | QIODevice::ReadOnly)){ + QTextStream in(&file); + while(!in.atEnd()){ + out << in.readLine(); + } + file.close(); + } + return out; +} + QString lthemeengine::configPath(){ return QDir::homePath() + "/.config/lthemeengine/"; } @@ -53,6 +66,20 @@ QStringList lthemeengine::sharedStyleSheetPath(){ return dirs; } +QString lthemeengine::userDesktopStyleSheetPath(){ + return configPath() + "desktop_qss/"; +} + +QStringList lthemeengine::sharedDesktopStyleSheetPath(){ + QStringList dirs; + dirs << QString(getenv("XDG_CONFIG_HOME")); + dirs << QString(getenv("XDG_CONFIG_DIRS")).split(":"); + dirs << QString(getenv("XDG_DATA_DIRS")).split(":"); + for(int i=0; i<dirs.length(); i++){ dirs[i].append("/lthemeengine/desktop_qss/"); } + if(dirs.isEmpty()){ dirs << LTHEMEENGINE_DATADIR"/lthemeengine/desktop_qss/"; } //no XDG settings - use the hardcoded path + return dirs; + } + QString lthemeengine::userColorSchemePath(){ return configPath() + "colors/"; } @@ -77,3 +104,96 @@ QString lthemeengine::systemLanguageID(){ #endif return QLocale::system().name(); } + +QStringList lthemeengine::availableSystemCursors(){ //returns: [name] for each item + //Find all the directories which could contain themes + QStringList paths; + paths << QDir::homePath()+"/.icons"; + QStringList xdd = QString(getenv("XDG_DATA_HOME")).split(":"); + xdd << QString(getenv("XDG_DATA_DIRS")).split(":"); + for(int i=0; i<xdd.length(); i++){ + if(QFile::exists(xdd[i]+"/icons")){ + paths << xdd[i]+"/icons"; + } + } + //Now get all the icon themes in these directories + QStringList themes, tmpthemes; + QDir dir; + for(int i=0; i<paths.length(); i++){ + if(dir.cd(paths[i])){ + tmpthemes = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); + for(int j=0; j<tmpthemes.length(); j++){ + if(tmpthemes[j].startsWith("default")){ continue; } + if( QFile::exists(dir.absoluteFilePath(tmpthemes[j]+"/cursors")) ){ themes << tmpthemes[j]; } + } + } + } + //Clean up the list and return + themes.removeDuplicates(); + themes.sort(); + return themes; +} + +//Return the currently-selected Cursor theme +QString lthemeengine::currentCursor(){ + //qDebug() << "Reading Current Cursor Theme:"; + QStringList info = readFile(QDir::homePath()+"/.icons/default/index.theme"); + if(info.isEmpty()){ return ""; } + QString cursor; + bool insection = false; + for(int i=0; i<info.length(); i++){ + if(info[i]=="[Icon Theme]"){ insection = true; continue;} + else if(insection && info[i].startsWith("Inherits=")){ + cursor = info[i].section("=",1,1).simplified(); + break; + } + } + //qDebug() << " - found theme:" << cursor; + return cursor; +} + +//Change the current Cursor Theme +bool lthemeengine::setCursorTheme(QString cursorname){ +//qDebug() << "Set Cursor Theme:" << cursorname; + if(cursorname=="default"){ + //special case - this will cause a recursive inheritance loop - just remove the file instead + if(QFile::exists(QDir::homePath()+"/.icons/default/index.theme")){ + return QFile::remove(QDir::homePath()+"/.icons/default/index.theme"); + } + return true; //already does not exist + } + QStringList info = readFile(QDir::homePath()+"/.icons/default/index.theme"); + bool insection = false; + bool changed = false; + QString newval = "Inherits="+cursorname; + for(int i=0; i<info.length() && !changed; i++){ + if(info[i]=="[Icon Theme]"){ + insection = true; + }else if( info[i].startsWith("[") && insection){ + //Section does not have the setting - add it + info.insert(i, newval); + changed =true; + }else if( info[i].startsWith("[") ){ + insection = false; + }else if(insection && info[i].startsWith("Inherits=")){ + info[i] = newval; //replace the current setting + changed = true; + } + } //end loop over file contents + if(!changed){ //Could not change the file contents for some reason + if(insection){ info << newval; } //end of file while in the section + else{ info << "[Icon Theme]" << newval; } //entire section missing from file + } + //Now save the file + QFile file(QDir::homePath()+"/.icons/default/index.theme"); + bool ok = false; + if( file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){ + QTextStream out(&file); + out << info.join("\n"); + if(!info.last().isEmpty()){ out << "\n"; } //always end with a new line + file.close(); + ok = true; + } + //qDebug() << "Done saving the cursor:" << info; + return ok; +} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.desktop b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.desktop index 7eb91bee..9d36fffa 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.desktop +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.desktop @@ -1,6 +1,6 @@ [Desktop Entry] X-Desktop-File-Install-Version=0.11 -Name=Lumine Theme Engine +Name=Lumina Theme Engine Comment=Lumina Theme Engine Exec=lthemeengine Icon=preferences-desktop-theme diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.h index 8a466ed9..c1b6eac6 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.h +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.h @@ -16,14 +16,22 @@ class lthemeengine { public: + static QStringList readFile(QString path); static QString configPath(); static QString configFile(); static QStringList iconPaths(); static QString userStyleSheetPath(); static QStringList sharedStyleSheetPath(); + static QString userDesktopStyleSheetPath(); + static QStringList sharedDesktopStyleSheetPath(); static QString userColorSchemePath(); static QStringList sharedColorSchemePath(); static QString systemLanguageID(); + //Cursor Theme Management + static QStringList availableSystemCursors(); + static QString currentCursor(); + static bool setCursorTheme(QString); + private: lthemeengine() {} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.pro b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.pro index 721b8888..cc949ff9 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.pro +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.pro @@ -16,7 +16,8 @@ SOURCES += \ interfacepage.cpp \ fontconfigdialog.cpp \ qsspage.cpp \ - qsseditordialog.cpp + qsseditordialog.cpp \ + cursorthemepage.cpp FORMS += \ mainwindow.ui \ @@ -28,7 +29,8 @@ FORMS += \ fontconfigdialog.ui \ previewform.ui \ qsspage.ui \ - qsseditordialog.ui + qsseditordialog.ui \ + cursorthemepage.ui HEADERS += \ mainwindow.h \ @@ -41,7 +43,8 @@ HEADERS += \ interfacepage.h \ fontconfigdialog.h \ qsspage.h \ - qsseditordialog.h + qsseditordialog.h \ + cursorthemepage.h DEFINES += USE_WIDGETS diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp index 719a0f49..a82f8cc6 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp @@ -1,27 +1,47 @@ #include <QApplication> #include <QSettings> +#include <QDebug> +#include <QTimer> + #include "lthemeengine.h" #include "mainwindow.h" #include "appearancepage.h" #include "fontspage.h" #include "iconthemepage.h" +#include "cursorthemepage.h" #include "interfacepage.h" #include "qsspage.h" #include "ui_mainwindow.h" +#include <LDesktopUtils.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 + bgroup = new QButtonGroup(this); + bgroup->setExclusive(true); + //Clear out any pages in the stacked widget + while(m_ui->stackedWidget->count()>0){ + m_ui->stackedWidget->removeWidget(m_ui->stackedWidget->widget(0)); + } + //Now add all the pages into the widget + bgroup->addButton(m_ui->tool_page_general, m_ui->stackedWidget->addWidget(new AppearancePage(this)) ); + bgroup->addButton(m_ui->tool_page_effects, m_ui->stackedWidget->addWidget(new InterfacePage(this))); + bgroup->addButton(m_ui->tool_page_fonts, m_ui->stackedWidget->addWidget(new FontsPage(this))); + bgroup->addButton(m_ui->tool_page_icons, m_ui->stackedWidget->addWidget(new IconThemePage(this))); + bgroup->addButton(m_ui->tool_page_styles, m_ui->stackedWidget->addWidget(new QSSPage(this, false))); + bgroup->addButton(m_ui->tool_page_deskstyles, m_ui->stackedWidget->addWidget(new QSSPage(this, true))); + bgroup->addButton(m_ui->tool_page_cursors, m_ui->stackedWidget->addWidget(new CursorThemePage(this)) ); + connect(bgroup, SIGNAL(buttonClicked(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int)) ); + connect(m_ui->push_close, SIGNAL(clicked()), this, SLOT(closeWindow()) ); + connect(m_ui->push_apply, SIGNAL(clicked()), this, SLOT(applyWindow()) ); + + QTimer::singleShot(10, m_ui->tool_page_general, SLOT(toggle())); QSettings settings(lthemeengine::configFile(), QSettings::IniFormat); restoreGeometry(settings.value("SettingsWindow/geometry").toByteArray()); setWindowIcon(QIcon::fromTheme("preferences-desktop-theme")); - m_ui->versionLabel->setText(tr("Version: %1").arg(LTHEMEENGINE_VERSION_STR)); + this->setWindowTitle(tr("Theme Settings")); + m_ui->versionLabel->setText(tr("Version: %1").arg(LDesktopUtils::LuminaDesktopVersion())); + //m_ui->buttonBox->set } MainWindow::~MainWindow(){ @@ -33,16 +53,14 @@ void MainWindow::closeEvent(QCloseEvent *){ 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(); - } +void MainWindow::closeWindow(){ + close(); + QApplication::quit(); +} + +void MainWindow::applyWindow(){ + for(int i = 0; i < m_ui->stackedWidget->count(); ++i){ + TabPage *p = qobject_cast<TabPage*>(m_ui->stackedWidget->widget(i)); + if(p) { p->writeSettings(); } + } } diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.h index 749949a6..333bc1fd 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.h +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.h @@ -2,8 +2,9 @@ #define MAINWINDOW_H #include <QWidget> - -class QAbstractButton; +#include <QAbstractButton> +#include <QButtonGroup> +//class QAbstractButton; namespace Ui { class MainWindow; @@ -18,12 +19,14 @@ public: ~MainWindow(); private slots: - void on_buttonBox_clicked(QAbstractButton *button); + void closeWindow(); + void applyWindow(); private: void closeEvent(QCloseEvent *); Ui::MainWindow *m_ui; + QButtonGroup *bgroup; }; #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 index 5bdab6d7..c60eb870 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui @@ -6,14 +6,14 @@ <rect> <x>0</x> <y>0</y> - <width>438</width> - <height>374</height> + <width>672</width> + <height>747</height> </rect> </property> <property name="windowTitle"> <string>Qt5 Configuration Tool</string> </property> - <layout class="QGridLayout" name="gridLayout"> + <layout class="QVBoxLayout" name="verticalLayout_2"> <property name="leftMargin"> <number>6</number> </property> @@ -23,22 +23,318 @@ <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> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <property name="spacing"> + <number>4</number> </property> - </widget> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QToolButton" name="tool_page_general"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>General</string> + </property> + <property name="icon"> + <iconset theme="preferences-desktop-theme"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextUnderIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_page_effects"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Effects</string> + </property> + <property name="icon"> + <iconset theme="preferences-desktop-display"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextUnderIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_page_fonts"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Fonts</string> + </property> + <property name="icon"> + <iconset theme="preferences-desktop-font"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextUnderIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_page_icons"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Icons</string> + </property> + <property name="icon"> + <iconset theme="preferences-desktop-icons"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextUnderIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_page_cursors"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Cursors</string> + </property> + <property name="icon"> + <iconset theme="preferences-desktop-mouse"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextUnderIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_page_styles"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>General +Styles</string> + </property> + <property name="icon"> + <iconset theme="preferences-system-windows"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextUnderIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_page_deskstyles"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Desktop +Styles</string> + </property> + <property name="icon"> + <iconset theme="preferences-desktop"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="iconSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextUnderIcon</enum> + </property> + <property name="autoRaise"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QStackedWidget" name="stackedWidget"> + <property name="frameShape"> + <enum>QFrame::Box</enum> + </property> + <widget class="QWidget" name="page"/> + </widget> + </item> + </layout> </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 class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="versionLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string notr="true">...</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="push_close"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Close</string> + </property> + <property name="icon"> + <iconset theme="dialog-cancel"/> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="push_apply"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Apply</string> + </property> + <property name="icon"> + <iconset theme="dialog-ok-apply"/> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + </widget> + </item> + </layout> </item> </layout> </widget> diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp index ac891a80..56289931 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.cpp @@ -4,6 +4,12 @@ #include "qsseditordialog.h" #include "ui_qsseditordialog.h" +#include <QTemporaryFile> +#include <QTextStream> + +#include <LuminaXDG.h> +#include <LUtils.h> + QSSEditorDialog::QSSEditorDialog(const QString &filePath, QWidget *parent) : QDialog(parent), m_ui(new Ui::QSSEditorDialog){ m_ui->setupUi(this); m_filePath = filePath; @@ -37,6 +43,11 @@ QSSEditorDialog::QSSEditorDialog(const QString &filePath, QWidget *parent) : QDi for(int i=0; i<colors.length(); i++){ colorMenu->addAction( colors[i].section("::::",0,0) )->setWhatsThis(colors[i].section("::::",1,1) ); } m_ui->tool_color->setMenu(colorMenu); connect(colorMenu, SIGNAL(triggered(QAction*)), this, SLOT(colorPicked(QAction*)) ); + validateTimer = new QTimer(this); + validateTimer->setInterval(500); //1/2 second after finish typing + validateTimer->setSingleShot(true); + connect(validateTimer, SIGNAL(timeout()), this, SLOT(validateStyleSheet()) ); + connect(m_ui->textEdit, SIGNAL(textChanged()), validateTimer, SLOT(start()) ); } QSSEditorDialog::~QSSEditorDialog(){ @@ -69,3 +80,31 @@ void QSSEditorDialog::colorPicked(QAction* act){ if(id.isEmpty()){ return; } m_ui->textEdit->insertPlainText( QString("palette(%1)").arg(id) ); } + +bool QSSEditorDialog::isStyleSheetValid(const QString &styleSheet){ + QTemporaryFile tempfile; + if(tempfile.open()){ + QTextStream out(&tempfile); + out << styleSheet; + out.flush(); + tempfile.close(); + } + QStringList log = LUtils::getCmdOutput("lthemeengine-sstest", QStringList() << tempfile.fileName()); + qDebug() << "Got Validation Log:" << log; + return log.join("").simplified().isEmpty(); +} + +void QSSEditorDialog::validateStyleSheet(){ + qDebug() << "Validating StyleSheet:"; + bool ok = isStyleSheetValid(m_ui->textEdit->toPlainText()); + + //Now update the button/label as needed + int sz = this->fontMetrics().height(); + if(ok){ + m_ui->label_status_icon->setPixmap(LXDG::findIcon("dialog-ok","").pixmap(sz,sz) ); + m_ui->label_status_icon->setToolTip(tr("Valid StyleSheet")); + }else{ + m_ui->label_status_icon->setPixmap(LXDG::findIcon("dialog-cancel","").pixmap(sz,sz) ); + m_ui->label_status_icon->setToolTip(tr("Invalid StyleSheet")); + } +} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h index 114611fe..f51434e9 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.h @@ -5,6 +5,7 @@ #include <QString> #include <QMenu> #include <QAction> +#include <QTimer> namespace Ui { class QSSEditorDialog; @@ -23,6 +24,8 @@ public: private slots: void on_buttonBox_clicked(QAbstractButton *button); void colorPicked(QAction*); + bool isStyleSheetValid(const QString&); + void validateStyleSheet(); private: void save(); @@ -30,6 +33,7 @@ private: Ui::QSSEditorDialog *m_ui; QString m_filePath; QMenu *colorMenu; + QTimer *validateTimer; }; diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui index f75a21c6..68a14fb1 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsseditordialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>643</width> - <height>499</height> + <width>808</width> + <height>512</height> </rect> </property> <property name="windowTitle"> @@ -53,6 +53,38 @@ </widget> </item> <item> + <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> + <widget class="QLabel" name="label_status_icon"> + <property name="minimumSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + <property name="text"> + <string notr="true"/> + </property> + <property name="scaledContents"> + <bool>false</bool> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="orientation"> <enum>Qt::Horizontal</enum> diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp index 2cf0f221..3140c553 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.cpp @@ -4,6 +4,9 @@ #include <QMessageBox> #include <QFile> #include <QMenu> +#include <QDebug> +#include <QTimer> + #include "lthemeengine.h" #include "qsseditordialog.h" #include "qsspage.h" @@ -12,8 +15,9 @@ #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){ +QSSPage::QSSPage(QWidget *parent, bool desktop) : TabPage(parent), m_ui(new Ui::QSSPage){ m_ui->setupUi(this); + desktop_qss = desktop; QDir("/").mkpath(lthemeengine::userStyleSheetPath()); m_menu = new QMenu(this); m_menu->addAction(QIcon::fromTheme("accessories-text-editor"), tr("Edit"), this, SLOT(on_editButton_clicked())); @@ -25,6 +29,9 @@ QSSPage::QSSPage(QWidget *parent) : TabPage(parent), m_ui(new Ui::QSSPage){ 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")); + m_ui->tool_enable->setEnabled(false); + m_ui->tool_disable->setEnabled(false); + m_ui->copyButton->setEnabled(false); } QSSPage::~QSSPage(){ @@ -34,14 +41,44 @@ QSSPage::~QSSPage(){ void QSSPage::writeSettings(){ QStringList styleSheets; QSettings settings(lthemeengine::configFile(), QSettings::IniFormat); - for(int i = 0; i < m_ui->qssListWidget->count(); ++i){ + for(int i = m_ui->qssListWidget->count()-1; i>=0; 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); + styleSheets << item->data(QSS_FULL_PATH_ROLE).toString(); } + if(desktop_qss){ settings.setValue("Interface/desktop_stylesheets", styleSheets); } + else{ settings.setValue("Interface/stylesheets", styleSheets); } } void QSSPage::on_qssListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *){ + if(current!=0){ + m_ui->list_disabled->clearSelection(); //clear any current selection on the other widget + m_ui->list_disabled->setCurrentRow(-1); + m_ui->tool_enable->setEnabled(false); + } + //qDebug() << "Got Current Item Changed"; + m_ui->tool_disable->setEnabled(current!=0); + m_ui->copyButton->setEnabled(current!=0); + 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_list_disabled_currentItemChanged(QListWidgetItem *current, QListWidgetItem *){ + if(current!=0){ + m_ui->qssListWidget->clearSelection(); //clear any current selection on the other widget + m_ui->qssListWidget->setCurrentRow(-1); + m_ui->tool_disable->setEnabled(false); + } + //qDebug() << "Got Current Item Changed"; + m_ui->tool_enable->setEnabled(current!=0); + m_ui->copyButton->setEnabled(current!=0); if(current){ m_ui->editButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool()); m_ui->removeButton->setEnabled(current->data(QSS_WRITABLE_ROLE).toBool()); @@ -58,54 +95,149 @@ 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 = lthemeengine::userStyleSheetPath() + name; + QString filePath; + if(desktop_qss){ filePath = lthemeengine::userDesktopStyleSheetPath() + name; } + else{ filePath = lthemeengine::userStyleSheetPath() + name; } if(QFile::exists(filePath)){ QMessageBox::warning(this, tr("Error"), tr("The file \"%1\" already exists").arg(filePath)); return; } + // Make sure the directory exists + QString dir = filePath.section("/",0,-2); + if(!QFile::exists(dir)){ + QDir D(dir); + D.mkpath(dir); + } //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); + QListWidgetItem *item = new QListWidgetItem(info.fileName(), m_ui->list_disabled); item->setToolTip(info.filePath()); item->setData(QSS_FULL_PATH_ROLE, info.filePath()); item->setData(QSS_WRITABLE_ROLE, info.isWritable()); - item->setCheckState(Qt::Unchecked); + m_ui->list_disabled->setCurrentRow(m_ui->list_disabled->count()-1); + QTimer::singleShot(10, this, SLOT(on_editButton_clicked()) ); } void QSSPage::on_editButton_clicked(){ - QListWidgetItem *item = m_ui->qssListWidget->currentItem(); + QListWidgetItem *item = currentSelection(); if(item){ QSSEditorDialog dialog(item->data(QSS_FULL_PATH_ROLE).toString(), this); dialog.exec(); } } +void QSSPage::on_copyButton_clicked(){ + QListWidgetItem *sel = currentSelection(); + if(sel==0){ return; } + QString name = QInputDialog::getText(this, tr("Enter Style Sheet Name"), tr("File name:"), QLineEdit::Normal, sel->text().section(".qss",0,0)+"_copy"); + if(name.isEmpty()){ return; } + if(!name.endsWith(".qss", Qt::CaseInsensitive)){ name.append(".qss"); } + QString filePath; + if(desktop_qss){ filePath = lthemeengine::userDesktopStyleSheetPath() + name; } + else{ filePath = lthemeengine::userStyleSheetPath() + name; } + if(QFile::exists(filePath)){ + QMessageBox::warning(this, tr("Error"), tr("The file \"%1\" already exists").arg(filePath)); + return; + } + // Make sure the directory exists + QString dir = filePath.section("/",0,-2); + if(!QFile::exists(dir)){ + QDir D(dir); + D.mkpath(dir); + } + //Copy the file over + QFile::copy(sel->data(QSS_FULL_PATH_ROLE).toString(), filePath); + //creating item + QFileInfo info(filePath); + QListWidgetItem *item = new QListWidgetItem(info.fileName(), m_ui->list_disabled); + item->setToolTip(info.filePath()); + item->setData(QSS_FULL_PATH_ROLE, info.filePath()); + item->setData(QSS_WRITABLE_ROLE, info.isWritable()); + m_ui->list_disabled->setCurrentRow(m_ui->list_disabled->count()-1); +} + void QSSPage::on_removeButton_clicked(){ - QListWidgetItem *item = m_ui->qssListWidget->currentItem(); + QListWidgetItem *item = currentSelection(); 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::on_tool_enable_clicked(){ + QList<QListWidgetItem*> sel = m_ui->list_disabled->selectedItems(); + //qDebug() << "Got Selection:" << sel.count(); + for(int i=0; i<sel.length(); i++){ + m_ui->qssListWidget->addItem(sel[i]->clone()); + delete sel[i]; + //QCoreApplication::processEvents(); + m_ui->qssListWidget->setCurrentRow(m_ui->qssListWidget->count()-1); + } + +} + +void QSSPage::on_tool_disable_clicked(){ + QList<QListWidgetItem*> sel = m_ui->qssListWidget->selectedItems(); + //qDebug() << "Got Selection:" << sel.count(); + for(int i=0; i<sel.length(); i++){ + m_ui->list_disabled->addItem(sel[i]->clone()); + delete sel[i]; + //QCoreApplication::processEvents(); + m_ui->list_disabled->setCurrentRow(m_ui->list_disabled->count()-1); + } +} + +void QSSPage::on_tool_priority_up_clicked(){ + QList<QListWidgetItem*> sel = m_ui->qssListWidget->selectedItems(); + for(int i=0; i<sel.length(); i++){ + int index = m_ui->qssListWidget->row(sel[i]); + //qDebug() << "Move Item Up:" << index; + if(index>0){ + m_ui->qssListWidget->insertItem(index-1, m_ui->qssListWidget->takeItem(index)); + m_ui->qssListWidget->setCurrentRow(index-1); + } + } +} + +void QSSPage::on_tool_priority_down_clicked(){ + QList<QListWidgetItem*> sel = m_ui->qssListWidget->selectedItems(); + for(int i=0; i<sel.length(); i++){ + int index = m_ui->qssListWidget->row(sel[i]); + //qDebug() << "Move Item Down:" << index; + if(index<(m_ui->qssListWidget->count()-1) ){ + m_ui->qssListWidget->insertItem(index+1, m_ui->qssListWidget->takeItem(index)); + m_ui->qssListWidget->setCurrentRow(index+1); + } + } +} + void QSSPage::readSettings(){ //load stylesheets m_ui->qssListWidget->clear(); - findStyleSheets(QStringList() << lthemeengine::userStyleSheetPath() << lthemeengine::sharedStyleSheetPath()); + m_ui->list_disabled->clear(); + //Read the currently-enabled settings QSettings settings(lthemeengine::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); } + QStringList styleSheets; + if(desktop_qss){ styleSheets = settings.value("Interface/desktop_stylesheets").toStringList(); } + else{ styleSheets = settings.value("Interface/stylesheets").toStringList(); } + for(int i=0; i<styleSheets.length(); i++){ + if(styleSheets[i].contains("..") || styleSheets[i].contains("//") ){ + //Get the absolute path for matching later + styleSheets[i] = QFileInfo(styleSheets[i]).absoluteFilePath(); } + } + //Now load the items into list widgets + //qDebug() << "Found Stylesheets" << styleSheets; + if(desktop_qss){ findStyleSheets(QStringList() << lthemeengine::userDesktopStyleSheetPath() << lthemeengine::sharedDesktopStyleSheetPath(), styleSheets); } + else{findStyleSheets(QStringList() << lthemeengine::userStyleSheetPath() << lthemeengine::sharedStyleSheetPath(), styleSheets); } + } -void QSSPage::findStyleSheets(QStringList paths){ +void QSSPage::findStyleSheets(QStringList paths, QStringList enabled){ paths.removeDuplicates(); for(int i=0; i<paths.length(); i++){ if(!QFile::exists(paths[i])){ continue; } @@ -113,20 +245,30 @@ void QSSPage::findStyleSheets(QStringList paths){ dir.setFilter(QDir::Files); dir.setNameFilters(QStringList() << "*.qss"); foreach (QFileInfo info, dir.entryInfoList()){ - QListWidgetItem *item = new QListWidgetItem(info.fileName(), m_ui->qssListWidget); + QListWidgetItem *item = new QListWidgetItem(info.fileName()); item->setToolTip(info.filePath()); item->setData(QSS_FULL_PATH_ROLE, info.filePath()); item->setData(QSS_WRITABLE_ROLE, info.isWritable()); + if( enabled.contains(info.filePath()) ){ m_ui->qssListWidget->addItem(item); } + else{ m_ui->list_disabled->addItem(item); } } } + //Now ensure the priority of the items in the active list is correct + for(int i = 0; i < m_ui->qssListWidget->count(); ++i){ + QListWidgetItem *item = m_ui->qssListWidget->item(i); + int index = enabled.indexOf( item->data(QSS_FULL_PATH_ROLE).toString() ); + if(index>=0){ m_ui->qssListWidget->insertItem(index, item); }// item->move(m_ui->qssListWidget->count() - 1 - index); } + } + m_ui->list_disabled->sortItems(Qt::AscendingOrder); + } void QSSPage::on_renameButton_clicked(){ - QListWidgetItem *item = m_ui->qssListWidget->currentItem(); + QListWidgetItem *item = currentSelection(); 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()){ + if(!m_ui->qssListWidget->findItems(name, Qt::MatchExactly).isEmpty() || !m_ui->list_disabled->findItems(name, Qt::MatchExactly).isEmpty()){ QMessageBox::warning(this, tr("Error"), tr("The style sheet \"%1\" already exists").arg(name)); return; } @@ -145,3 +287,9 @@ 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)); } } + +QListWidgetItem* QSSPage::currentSelection(){ + QListWidgetItem *item = m_ui->qssListWidget->currentItem(); + if(item==0){ item = m_ui->list_disabled->currentItem(); } + return item; +} diff --git a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h index 5e924ad9..07df4ac2 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.h @@ -15,24 +15,34 @@ class QSSPage : public TabPage Q_OBJECT public: - explicit QSSPage(QWidget *parent = 0); + explicit QSSPage(QWidget *parent = 0, bool desktop = false); ~QSSPage(); void writeSettings(); private slots: void on_qssListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *); + void on_list_disabled_currentItemChanged(QListWidgetItem *current, QListWidgetItem *); void on_createButton_clicked(); + void on_copyButton_clicked(); void on_editButton_clicked(); void on_removeButton_clicked(); void on_renameButton_clicked(); void on_qssListWidget_customContextMenuRequested(const QPoint &pos); + void on_tool_enable_clicked(); + void on_tool_disable_clicked(); + void on_tool_priority_up_clicked(); + void on_tool_priority_down_clicked(); + private: void readSettings(); - void findStyleSheets(QStringList paths); + void findStyleSheets(QStringList paths, QStringList enabled); Ui::QSSPage *m_ui; QMenu *m_menu; + bool desktop_qss; + + QListWidgetItem* currentSelection(); }; #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 index 124b4dc6..def99dd0 100644 --- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui +++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/qsspage.ui @@ -13,69 +13,301 @@ <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> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QToolButton" name="tool_priority_up"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Increase Priority</string> + </property> + <property name="text"> + <string notr="true"/> + </property> + <property name="icon"> + <iconset theme="arrow-up"> + <normaloff>.</normaloff>.</iconset> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="tool_priority_down"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Decrease priority of style</string> + </property> + <property name="text"> + <string notr="true"/> + </property> + <property name="icon"> + <iconset theme="arrow-down"> + <normaloff>.</normaloff>.</iconset> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <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> + <widget class="QToolButton" name="tool_disable"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Disable Style</string> + </property> + <property name="text"> + <string>Disable</string> + </property> + <property name="icon"> + <iconset theme="arrow-right"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="font"> + <font> + <italic>true</italic> + </font> + </property> + <property name="text"> + <string>Enabled</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="qssListWidget"> + <property name="contextMenuPolicy"> + <enum>Qt::CustomContextMenu</enum> + </property> + <property name="alternatingRowColors"> + <bool>false</bool> + </property> + <property name="resizeMode"> + <enum>QListView::Fixed</enum> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + </widget> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QToolButton" name="tool_enable"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Enable</string> + </property> + <property name="icon"> + <iconset theme="arrow-left"> + <normaloff>.</normaloff>.</iconset> + </property> + <property name="toolButtonStyle"> + <enum>Qt::ToolButtonTextBesideIcon</enum> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <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> + <item> + <widget class="QLabel" name="label_2"> + <property name="font"> + <font> + <italic>true</italic> + </font> + </property> + <property name="text"> + <string>Available</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="list_disabled"/> + </item> + </layout> + </item> + </layout> </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"> + <item> + <widget class="Line" name="line_2"> <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 class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="createButton"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Create</string> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="copyButton"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Copy</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="editButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Edit</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="renameButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Rename</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="removeButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <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> + </layout> </item> </layout> </widget> |