aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Moore <ken@ixsystems.com>2017-09-15 12:25:54 -0400
committerKen Moore <ken@ixsystems.com>2017-09-15 12:25:54 -0400
commit5b1831a22408a22d9c3bc03a82942a4bf092f311 (patch)
treeab34171d8d1c905ea589b915e8209cfee0b5844e
parentMake sure the "leave" dialog is themeable, and theme it within the DarkGlass ... (diff)
downloadlumina-5b1831a22408a22d9c3bc03a82942a4bf092f311.tar.gz
lumina-5b1831a22408a22d9c3bc03a82942a4bf092f311.tar.bz2
lumina-5b1831a22408a22d9c3bc03a82942a4bf092f311.zip
Add mouse cursor theme management to lthemeengine.
Also fix up a number of other little bugs in various pages.
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.cpp139
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.h29
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/cursorthemepage.ui51
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/iconthemepage.cpp4
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.cpp106
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.h6
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.pro9
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp2
-rw-r--r--src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui36
9 files changed, 375 insertions, 7 deletions
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 701745c4..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/";
}
@@ -91,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.h b/src-qt5/core/lumina-theme-engine/src/lthemeengine/lthemeengine.h
index 06dd3e09..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,6 +16,7 @@
class lthemeengine
{
public:
+ static QStringList readFile(QString path);
static QString configPath();
static QString configFile();
static QStringList iconPaths();
@@ -26,6 +27,11 @@ public:
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 d0f1560f..d4544c7b 100644
--- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.cpp
@@ -8,6 +8,7 @@
#include "appearancepage.h"
#include "fontspage.h"
#include "iconthemepage.h"
+#include "cursorthemepage.h"
#include "interfacepage.h"
#include "qsspage.h"
#include "ui_mainwindow.h"
@@ -27,6 +28,7 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent), m_ui(new Ui::MainWind
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)) );
QTimer::singleShot(10, m_ui->tool_page_general, SLOT(toggle()));
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 bfaf3eaf..dd676c37 100644
--- a/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui
+++ b/src-qt5/core/lumina-theme-engine/src/lthemeengine/mainwindow.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>657</width>
- <height>500</height>
+ <width>672</width>
+ <height>723</height>
</rect>
</property>
<property name="windowTitle">
@@ -159,6 +159,38 @@
</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">
bgstack15