Support for QML based decoration in KCM decoration

Model is extended to support QML based Aurorae themes as well
the preview is able to handle it. For this a new qml component
is added which loads the decoration preview.
This commit is contained in:
Martin Gräßlin 2012-07-27 10:10:28 +02:00
parent 673dcd6ad3
commit 249173946a
6 changed files with 117 additions and 9 deletions

View file

@ -30,4 +30,9 @@ install(TARGETS kcm_kwindecoration DESTINATION ${PLUGIN_INSTALL_DIR} )
########### install files ############### ########### install files ###############
install( FILES kwindecoration.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) install( FILES kwindecoration.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
install( FILES qml/main.qml qml/AuroraeDecoration.qml qml/AuroraePreview.qml DESTINATION ${DATA_INSTALL_DIR}/kwin/kcm_kwindecoration) install( FILES
qml/main.qml
qml/AuroraeDecoration.qml
qml/AuroraePreview.qml
qml/DecorationPreview.qml
DESTINATION ${DATA_INSTALL_DIR}/kwin/kcm_kwindecoration)

View file

@ -34,7 +34,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KGlobalSettings> #include <KGlobalSettings>
#include <KIcon> #include <KIcon>
#include <KLocale> #include <KLocale>
#include <KServiceTypeTrader>
#include <KStandardDirs> #include <KStandardDirs>
#include <KPluginInfo>
#include "kwindecoration.h" #include "kwindecoration.h"
/* WARNING ------------------------------------------------------------------------- /* WARNING -------------------------------------------------------------------------
@ -66,6 +68,7 @@ DecorationModel::DecorationModel(KSharedConfigPtr config, QObject* parent)
roleNames[DecorationModel::PixmapRole] = "preview"; roleNames[DecorationModel::PixmapRole] = "preview";
roleNames[TypeRole] = "type"; roleNames[TypeRole] = "type";
roleNames[AuroraeNameRole] = "auroraeThemeName"; roleNames[AuroraeNameRole] = "auroraeThemeName";
roleNames[QmlMainScriptRole] = "mainScript";
setRoleNames(roleNames); setRoleNames(roleNames);
m_config = KSharedConfig::openConfig("auroraerc"); m_config = KSharedConfig::openConfig("auroraerc");
findDecorations(); findDecorations();
@ -120,6 +123,31 @@ void DecorationModel::findDecorations()
} }
} }
} }
KService::List offers = KServiceTypeTrader::self()->query("KWin/Decoration");
foreach (KService::Ptr service, offers) {
DecorationModelData data;
data.name = service->name();
data.libraryName = "kwin3_aurorae";
data.type = DecorationModelData::QmlDecoration;
data.auroraeName = service->property("X-KDE-PluginInfo-Name").toString();
QString scriptName = service->property("X-Plasma-MainScript").toString();
data.qmlPath = KStandardDirs::locate("data", "kwin/decorations/" + data.auroraeName + "/contents/" + scriptName);
if (data.qmlPath.isEmpty()) {
// not a valid QML theme
continue;
}
// TODO: read proper border sizes
data.borderSize = KDecorationDefines::BorderNormal;
data.buttonSize = KDecorationDefines::BorderNormal;
data.comment = service->comment();
KPluginInfo info(service);
data.author = info.author();
data.email= info.email();
data.version = info.version();
data.license = info.license();
data.website = info.website();
m_decorations.append(data);
}
qSort(m_decorations.begin(), m_decorations.end(), DecorationModelData::less); qSort(m_decorations.begin(), m_decorations.end(), DecorationModelData::less);
endResetModel(); endResetModel();
} }
@ -219,6 +247,8 @@ QVariant DecorationModel::data(const QModelIndex& index, int role) const
return static_cast< int >(m_decorations[ index.row()].buttonSize); return static_cast< int >(m_decorations[ index.row()].buttonSize);
else else
return QVariant(); return QVariant();
case QmlMainScriptRole:
return m_decorations[ index.row()].qmlPath;
default: default:
return QVariant(); return QVariant();
} }
@ -377,11 +407,14 @@ QModelIndex DecorationModel::indexOfName(const QString& decoName) const
return QModelIndex(); return QModelIndex();
} }
QModelIndex DecorationModel::indexOfAuroraeName(const QString& auroraeName) const QModelIndex DecorationModel::indexOfAuroraeName(const QString &auroraeName, const QString &type) const
{ {
for (int i = 0; i < m_decorations.count(); i++) { for (int i = 0; i < m_decorations.count(); i++) {
const DecorationModelData& data = m_decorations.at(i); const DecorationModelData& data = m_decorations.at(i);
if (data.type == DecorationModelData::AuroraeDecoration && if (type == "aurorae" && data.type == DecorationModelData::AuroraeDecoration &&
data.auroraeName.compare(auroraeName) == 0)
return index(i);
if (type == "qml" && data.type == DecorationModelData::QmlDecoration &&
data.auroraeName.compare(auroraeName) == 0) data.auroraeName.compare(auroraeName) == 0)
return index(i); return index(i);
} }

View file

@ -40,7 +40,8 @@ class DecorationModelData
public: public:
enum DecorationType { enum DecorationType {
NativeDecoration = 0, NativeDecoration = 0,
AuroraeDecoration = 1 AuroraeDecoration = 1,
QmlDecoration = 2
}; };
QString name; QString name;
QString libraryName; QString libraryName;
@ -53,6 +54,7 @@ public:
QString version; QString version;
QString license; QString license;
QString auroraeName; QString auroraeName;
QString qmlPath;
KDecorationDefines::BorderSize borderSize; KDecorationDefines::BorderSize borderSize;
KDecorationDefines::BorderSize buttonSize; KDecorationDefines::BorderSize buttonSize;
@ -79,7 +81,8 @@ public:
PackageLicenseRole = Qt::UserRole + 10, PackageLicenseRole = Qt::UserRole + 10,
BorderSizeRole = Qt::UserRole + 11, BorderSizeRole = Qt::UserRole + 11,
BorderSizesRole = Qt::UserRole + 12, BorderSizesRole = Qt::UserRole + 12,
ButtonSizeRole = Qt::UserRole + 13 ButtonSizeRole = Qt::UserRole + 13,
QmlMainScriptRole = Qt::UserRole + 14
}; };
DecorationModel(KSharedConfigPtr config, QObject* parent = 0); DecorationModel(KSharedConfigPtr config, QObject* parent = 0);
~DecorationModel(); ~DecorationModel();
@ -105,7 +108,7 @@ public:
QModelIndex indexOfLibrary(const QString& libraryName) const; QModelIndex indexOfLibrary(const QString& libraryName) const;
QModelIndex indexOfName(const QString& decoName) const; QModelIndex indexOfName(const QString& decoName) const;
QModelIndex indexOfAuroraeName(const QString& auroraeName) const; QModelIndex indexOfAuroraeName(const QString& auroraeName, const QString& type) const;
void regeneratePreviews(int firstIndex = 0); void regeneratePreviews(int firstIndex = 0);
void stopPreviewGeneration(); void stopPreviewGeneration();

View file

@ -102,6 +102,10 @@ KWinDecorationModule::KWinDecorationModule(QWidget* parent, const QVariantList &
m_ui->decorationList->rootContext()->setContextProperty("highlightColor", m_ui->decorationList->palette().color(QPalette::Highlight)); m_ui->decorationList->rootContext()->setContextProperty("highlightColor", m_ui->decorationList->palette().color(QPalette::Highlight));
m_ui->decorationList->rootContext()->setContextProperty("sliderWidth", m_ui->decorationList->verticalScrollBar()->width()); m_ui->decorationList->rootContext()->setContextProperty("sliderWidth", m_ui->decorationList->verticalScrollBar()->width());
m_ui->decorationList->rootContext()->setContextProperty("auroraeSource", KStandardDirs::locate("data", "kwin/aurorae/aurorae.qml")); m_ui->decorationList->rootContext()->setContextProperty("auroraeSource", KStandardDirs::locate("data", "kwin/aurorae/aurorae.qml"));
m_ui->decorationList->rootContext()->setContextProperty("decorationActiveCaptionColor", KDecoration::options()->color(ColorFont, true));
m_ui->decorationList->rootContext()->setContextProperty("decorationInactiveCaptionColor", KDecoration::options()->color(ColorFont, false));
m_ui->decorationList->rootContext()->setContextProperty("decorationActiveTitleBarColor", KDecoration::options()->color(ColorTitleBar, true));
m_ui->decorationList->rootContext()->setContextProperty("decorationInactiveTitleBarColor", KDecoration::options()->color(ColorTitleBar, false));
m_ui->decorationList->setSource(KStandardDirs::locate("data", "kwin/kcm_kwindecoration/main.qml")); m_ui->decorationList->setSource(KStandardDirs::locate("data", "kwin/kcm_kwindecoration/main.qml"));
readConfig(style); readConfig(style);
@ -174,7 +178,8 @@ void KWinDecorationModule::readConfig(const KConfigGroup & conf)
KConfig auroraeConfig("auroraerc"); KConfig auroraeConfig("auroraerc");
KConfigGroup group(&auroraeConfig, "Engine"); KConfigGroup group(&auroraeConfig, "Engine");
const QString themeName = group.readEntry("ThemeName", "example-deco"); const QString themeName = group.readEntry("ThemeName", "example-deco");
const QModelIndex index = m_proxyModel->mapFromSource(m_model->indexOfAuroraeName(themeName)); const QString type = group.readEntry("EngineType", "aurorae");
const QModelIndex index = m_proxyModel->mapFromSource(m_model->indexOfAuroraeName(themeName, type));
if (index.isValid()) { if (index.isValid()) {
m_ui->decorationList->rootObject()->setProperty("currentIndex", index.row()); m_ui->decorationList->rootObject()->setProperty("currentIndex", index.row());
} }
@ -221,10 +226,16 @@ void KWinDecorationModule::writeConfig(KConfigGroup & conf)
conf.writeEntry("BorderSize", conf.writeEntry("BorderSize",
static_cast<int>(m_model->data(index, DecorationModel::BorderSizeRole).toInt())); static_cast<int>(m_model->data(index, DecorationModel::BorderSizeRole).toInt()));
if (m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::AuroraeDecoration) { if (m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::AuroraeDecoration ||
m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration) {
KConfig auroraeConfig("auroraerc"); KConfig auroraeConfig("auroraerc");
KConfigGroup group(&auroraeConfig, "Engine"); KConfigGroup group(&auroraeConfig, "Engine");
group.writeEntry("ThemeName", m_model->data(index, DecorationModel::AuroraeNameRole).toString()); group.writeEntry("ThemeName", m_model->data(index, DecorationModel::AuroraeNameRole).toString());
if (m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration) {
group.writeEntry("EngineType", "qml");
} else {
group.deleteEntry("EngineType");
}
group.sync(); group.sync();
} }
@ -306,10 +317,15 @@ void KWinDecorationModule::slotGHNSClicked()
const QModelIndex index = m_proxyModel->mapToSource(m_proxyModel->index(m_ui->decorationList->rootObject()->property("currentIndex").toInt(), 0)); const QModelIndex index = m_proxyModel->mapToSource(m_proxyModel->index(m_ui->decorationList->rootObject()->property("currentIndex").toInt(), 0));
const QString libraryName = m_model->data(index, DecorationModel::LibraryNameRole).toString(); const QString libraryName = m_model->data(index, DecorationModel::LibraryNameRole).toString();
bool aurorae = m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::AuroraeDecoration; bool aurorae = m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::AuroraeDecoration;
bool qml = m_model->data(index, DecorationModel::TypeRole).toInt() == DecorationModelData::QmlDecoration;
const QString auroraeName = m_model->data(index, DecorationModel::AuroraeNameRole).toString(); const QString auroraeName = m_model->data(index, DecorationModel::AuroraeNameRole).toString();
m_model->reload(); m_model->reload();
if (aurorae) { if (aurorae) {
const QModelIndex proxyIndex = m_proxyModel->mapFromSource(m_model->indexOfAuroraeName(auroraeName)); const QModelIndex proxyIndex = m_proxyModel->mapFromSource(m_model->indexOfAuroraeName(auroraeName, "aurorae"));
if (proxyIndex.isValid())
m_ui->decorationList->rootObject()->setProperty("currentIndex", proxyIndex.row());
} else if (qml) {
const QModelIndex proxyIndex = m_proxyModel->mapFromSource(m_model->indexOfAuroraeName(auroraeName, "qml"));
if (proxyIndex.isValid()) if (proxyIndex.isValid())
m_ui->decorationList->rootObject()->setProperty("currentIndex", proxyIndex.row()); m_ui->decorationList->rootObject()->setProperty("currentIndex", proxyIndex.row());
} else { } else {

View file

@ -0,0 +1,47 @@
/********************************************************************
Copyright (C) 2012 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
import QtQuick 1.1
Item {
id: decorationPreview
AuroraeDecoration {
id: inactiveDecoration
active: false
anchors {
fill: parent
leftMargin: 40
rightMargin: 10
topMargin: 10
bottomMargin: 40
}
}
AuroraeDecoration {
id: activeDecoration
active: true
anchors {
fill: parent
leftMargin: 10
rightMargin: 40
topMargin: 40
bottomMargin: 10
}
}
Component.onCompleted: {
inactiveDecoration.source = mainScript;
activeDecoration.source = mainScript;
}
}

View file

@ -44,6 +44,10 @@ ListView {
source: type == 1 ? "AuroraePreview.qml" : "" source: type == 1 ? "AuroraePreview.qml" : ""
anchors.fill: parent anchors.fill: parent
} }
Loader {
source: type == 2 ? "DecorationPreview.qml" : ""
anchors.fill: parent
}
MouseArea { MouseArea {
hoverEnabled: false hoverEnabled: false
anchors.fill: parent anchors.fill: parent