diff --git a/declarativeimports/CMakeLists.txt b/declarativeimports/CMakeLists.txt index 00b54222f..5774a12b2 100644 --- a/declarativeimports/CMakeLists.txt +++ b/declarativeimports/CMakeLists.txt @@ -3,4 +3,4 @@ add_subdirectory(draganddrop) add_subdirectory(graphicslayouts) add_subdirectory(graphicswidgets) add_subdirectory(qtextracomponents) - +add_subdirectory(plasmacomponents) \ No newline at end of file diff --git a/declarativeimports/core/dataengineconsumer.cpp b/declarativeimports/core/dataengineconsumer.cpp index 0ccaff220..2120e1c41 100644 --- a/declarativeimports/core/dataengineconsumer.cpp +++ b/declarativeimports/core/dataengineconsumer.cpp @@ -42,33 +42,32 @@ ServiceMonitor::~ServiceMonitor() void ServiceMonitor::slotJobFinished(Plasma::ServiceJob *job) { - kDebug() << "engine ready!"; + //kDebug() << "engine ready!"; QString engineName = job->parameters()["EngineName"].toString(); QString location = job->destination(); QPair pair(location, engineName); - kDebug() << "pair = " << pair; + //kDebug() << "pair = " << pair; if (!m_consumer->m_remoteEngines.contains(pair)) { kDebug() << "engine does not exist yet!"; } else { KUrl engineLocation(location); engineLocation.setFileName(job->result().toString()); - kDebug() << "setting location : " - << engineLocation.prettyUrl(); + //kDebug() << "setting location : " << engineLocation.prettyUrl(); // m_consumer->m_remoteEngines[pair]->setLocation(engineLocation); } } void ServiceMonitor::slotServiceReady(Plasma::Service *plasmoidService) { - kDebug() << "service ready!"; + //kDebug() << "service ready!"; if (!m_consumer->m_engineNameForService.contains(plasmoidService)) { kDebug() << "no engine name for service!"; kDebug() << "amount of services in map: " << m_consumer->m_engineNameForService.count(); } else { - kDebug() << "value = " << m_consumer->m_engineNameForService.value(plasmoidService); + //kDebug() << "value = " << m_consumer->m_engineNameForService.value(plasmoidService); } - kDebug() << "requesting dataengine!"; + //kDebug() << "requesting dataengine!"; KConfigGroup op = plasmoidService->operationDescription("DataEngine"); op.writeEntry("EngineName", m_consumer->m_engineNameForService.value(plasmoidService)); plasmoidService->startOperationCall(op); @@ -90,6 +89,13 @@ DataEngineConsumer::~DataEngineConsumer() delete m_monitor; } +void DataEngineConsumer::finishedWithEngine(const QString &name) +{ + if (m_loadedEngines.contains(name)) { + DataEngineManager::self()->unloadEngine(name); + } +} + DataEngine *DataEngineConsumer::dataEngine(const QString &name) { if (m_loadedEngines.contains(name)) { diff --git a/declarativeimports/core/dataengineconsumer_p.h b/declarativeimports/core/dataengineconsumer_p.h index 579548033..3b2c574e0 100644 --- a/declarativeimports/core/dataengineconsumer_p.h +++ b/declarativeimports/core/dataengineconsumer_p.h @@ -57,6 +57,7 @@ public: ~DataEngineConsumer(); DataEngine *dataEngine(const QString &name); DataEngine *remoteDataEngine(const KUrl &location, const QString &name); + void finishedWithEngine(const QString &name); private: QSet m_loadedEngines; diff --git a/declarativeimports/core/datamodel.cpp b/declarativeimports/core/datamodel.cpp index d4f28c0a4..2cc7d2593 100644 --- a/declarativeimports/core/datamodel.cpp +++ b/declarativeimports/core/datamodel.cpp @@ -151,53 +151,44 @@ DataModel::~DataModel() void DataModel::dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data) { - if (!m_keyRoleFilter.isEmpty()) { - QRegExp sourceRegExp(m_sourceFilter); - //a key that matches the one we want exists and is a list of DataEngine::Data - if (data.contains(m_keyRoleFilter) && - data.value(m_keyRoleFilter).canConvert() && - //matches the source filter regexp? - (m_sourceFilter.isEmpty() || (sourceRegExp.isValid() && sourceRegExp.exactMatch(sourceName)))) { - setItems(sourceName, data.value(m_keyRoleFilter).value()); - //try to match the key we want with a regular expression if set - } else { - QRegExp regExp(m_keyRoleFilter); - if (regExp.isValid() && - //matches the source filter regexp? - (m_sourceFilter.isEmpty() || (sourceRegExp.isValid() && sourceRegExp.exactMatch(sourceName)))) { - QHash::const_iterator i; - QVariantList list; - for (i = data.constBegin(); i != data.constEnd(); ++i) { - if (regExp.exactMatch(i.key())) { - list.append(i.value()); - } - } - setItems(sourceName, list); - } - } - //an item is represented by a source: keys are roles m_roleLevel == FirstLevel - } else { + if (!m_sourceFilter.isEmpty() && m_sourceFilterRE.isValid() && !m_sourceFilterRE.exactMatch(sourceName)) { + return; + } + + if (m_keyRoleFilter.isEmpty()) { + //an item is represented by a source: keys are roles m_roleLevel == FirstLevel QVariantList list; if (!m_dataSource->data().isEmpty()) { - QVariantMap::const_iterator i = m_dataSource->data().constBegin(); - QRegExp sourceRegExp(m_sourceFilter); + QVariantHash::const_iterator i = m_dataSource->data().constBegin(); while (i != m_dataSource->data().constEnd()) { QVariant value = i.value(); - if (value.isValid() && - value.canConvert() && - //matches the source filter regexp? - (m_sourceFilter.isEmpty() || (sourceRegExp.isValid() && sourceRegExp.exactMatch(i.key())))) { + if (value.isValid() && value.canConvert()) { Plasma::DataEngine::Data data = value.value(); data["DataEngineSource"] = i.key(); - list.append(data); } ++i; } } setItems(QString(), list); + } else { + //a key that matches the one we want exists and is a list of DataEngine::Data + if (data.contains(m_keyRoleFilter) && + data.value(m_keyRoleFilter).canConvert()) { + setItems(sourceName, data.value(m_keyRoleFilter).value()); + } else if (m_keyRoleFilterRE.isValid()) { + //try to match the key we want with a regular expression if set + QVariantList list; + QHash::const_iterator i; + for (i = data.constBegin(); i != data.constEnd(); ++i) { + if (m_keyRoleFilterRE.exactMatch(i.key())) { + list.append(i.value()); + } + } + setItems(sourceName, list); + } } } @@ -212,8 +203,19 @@ void DataModel::setDataSource(QObject *object) return; } - disconnect(m_dataSource, 0, this, 0); + if (m_dataSource) { + disconnect(m_dataSource, 0, this, 0); + } + m_dataSource = source; + + const QHash data = source->data(); + QHash::const_iterator i = data.constBegin(); + while (i != data.constEnd()) { + dataUpdated(i.key(), i.value().value()); + ++i; + } + connect(m_dataSource, SIGNAL(newData(const QString &, const Plasma::DataEngine::Data &)), this, SLOT(dataUpdated(const QString &, const Plasma::DataEngine::Data &))); connect(m_dataSource, SIGNAL(sourceRemoved(const QString &)), this, SLOT(removeSource(const QString &))); @@ -227,11 +229,24 @@ QObject *DataModel::dataSource() const void DataModel::setKeyRoleFilter(const QString& key) { + // the "key role filter" can be used in one of three ways: + // + // 1) empty string -> all data is used, each source is one row in the model + // 2) matches a key in the data exactly -> only that key/value pair is used, and the value is + // treated as a collection where each item in the collection becomes a row in the model + // 3) regular expression -> matches zero or more keys in the data, and each matching key/value + // pair becomes a row in the model if (m_keyRoleFilter == key) { return; } m_keyRoleFilter = key; + m_keyRoleFilterRE = QRegExp(m_keyRoleFilter); +} + +QString DataModel::keyRoleFilter() const +{ + return m_keyRoleFilter; } void DataModel::setSourceFilter(const QString& key) @@ -241,6 +256,14 @@ void DataModel::setSourceFilter(const QString& key) } m_sourceFilter = key; + m_sourceFilterRE = QRegExp(key); + /* + FIXME: if the user changes the source filter, it won't immediately be reflected in the + available data + if (m_sourceFilterRE.isValid()) { + .. iterate through all items and weed out the ones that don't match .. + } + */ } QString DataModel::sourceFilter() const @@ -248,11 +271,6 @@ QString DataModel::sourceFilter() const return m_sourceFilter; } -QString DataModel::keyRoleFilter() const -{ - return m_keyRoleFilter; -} - void DataModel::setItems(const QString &sourceName, const QVariantList &list) { beginResetModel(); @@ -262,19 +280,31 @@ void DataModel::setItems(const QString &sourceName, const QVariantList &list) if (!list.isEmpty()) { if (list.first().canConvert()) { - foreach (const QString& roleName, list.first().value().keys()) { - if (!m_roleIds.contains(roleName)) { - ++m_maxRoleId; - m_roleNames[m_maxRoleId] = roleName.toLatin1(); - m_roleIds[roleName] = m_maxRoleId; + foreach (const QVariant &item, list) { + const QVariantHash &vh = item.value(); + QHashIterator it(vh); + while (it.hasNext()) { + it.next(); + const QString &roleName = it.key(); + if (!m_roleIds.contains(roleName)) { + ++m_maxRoleId; + m_roleNames[m_maxRoleId] = roleName.toLatin1(); + m_roleIds[roleName] = m_maxRoleId; + } } } } else { - foreach (const QString& roleName, list.first().value().keys()) { - if (!m_roleIds.contains(roleName)) { - ++m_maxRoleId; - m_roleNames[m_maxRoleId] = roleName.toLatin1(); - m_roleIds[roleName] = m_maxRoleId; + foreach (const QVariant &item, list) { + const QVariantMap &vh = item.value(); + QMapIterator it(vh); + while (it.hasNext()) { + it.next(); + const QString &roleName = it.key(); + if (!m_roleIds.contains(roleName)) { + ++m_maxRoleId; + m_roleNames[m_maxRoleId] = roleName.toLatin1(); + m_roleIds[roleName] = m_maxRoleId; + } } } } @@ -294,15 +324,8 @@ void DataModel::removeSource(const QString &sourceName) //FIXME: this could be way more efficient by not resetting the whole model //FIXME: find a way to remove only the proper things also in the case where sources are items - //source name as key of the map - if (!m_keyRoleFilter.isEmpty()) { - if (m_items.contains(sourceName)) { - beginResetModel(); - m_items.remove(sourceName); - endResetModel(); - } - //source name in the map, linear scan - } else { + if (m_keyRoleFilter.isEmpty()) { + //source name in the map, linear scan for (int i = 0; i < m_items.value(QString()).count(); ++i) { if (m_items.value(QString())[i].value().value("DataEngineSource") == sourceName) { beginResetModel(); @@ -311,6 +334,13 @@ void DataModel::removeSource(const QString &sourceName) break; } } + } else { + //source name as key of the map + if (m_items.contains(sourceName)) { + beginResetModel(); + m_items.remove(sourceName); + endResetModel(); + } } } @@ -338,10 +368,9 @@ QVariant DataModel::data(const QModelIndex &index, int role) const //is it the reserved role: DataEngineSource ? //also, if each source is an item DataEngineSource is a role between all the others, otherwise we know it from the role variable + //finally, sub items are some times QVariantHash some times QVariantMaps if (!m_keyRoleFilter.isEmpty() && m_roleNames.value(role) == "DataEngineSource") { return source; - - //sub items are some times QVariantHash some times QVariantMaps } else if (m_items.value(source).value(actualRow).canConvert()) { return m_items.value(source).value(actualRow).value().value(m_roleNames.value(role)); } else { diff --git a/declarativeimports/core/datamodel.h b/declarativeimports/core/datamodel.h index a67909c73..744ec9e93 100644 --- a/declarativeimports/core/datamodel.h +++ b/declarativeimports/core/datamodel.h @@ -105,8 +105,7 @@ public: QString keyRoleFilter() const; /** - * Include only items with a source name that matches this regexp in the model - * @since 4.7 + * Include only sources that matches this regexp in the model */ void setSourceFilter(const QString& key); QString sourceFilter() const; @@ -139,7 +138,9 @@ private Q_SLOTS: private: DataSource *m_dataSource; QString m_keyRoleFilter; + QRegExp m_keyRoleFilterRE; QString m_sourceFilter; + QRegExp m_sourceFilterRE; QMap > m_items; QHash m_roleNames; QHash m_roleIds; diff --git a/declarativeimports/core/datasource.cpp b/declarativeimports/core/datasource.cpp index 598c41c37..b33a38728 100644 --- a/declarativeimports/core/datasource.cpp +++ b/declarativeimports/core/datasource.cpp @@ -32,35 +32,39 @@ namespace Plasma { DataSource::DataSource(QObject* parent) : QObject(parent), - m_interval(1000), + m_interval(0), m_dataEngine(0) { setObjectName("DataSource"); - - connect(this, SIGNAL(engineChanged()), - this, SLOT(setupData())); - connect(this, SIGNAL(connectedSourcesChanged()), - this, SLOT(setupData()), Qt::QueuedConnection); - connect(this, SIGNAL(intervalChanged()), - this, SLOT(setupData())); } void DataSource::setConnectedSources(const QStringList &sources) { + bool sourcesChanged = false; foreach (const QString &source, sources) { if (!m_connectedSources.contains(source)) { - m_newSources.append(source); - } - } - foreach (const QString &source, m_connectedSources) { - if (!sources.contains(source)) { - m_oldSources.append(source); + sourcesChanged = true; + if (m_dataEngine) { + m_connectedSources.append(source); + m_dataEngine->connectSource(source, this, m_interval); + emit sourceConnected(source); + } } } - if (!m_newSources.isEmpty() || !m_oldSources.isEmpty()) { + foreach (const QString &source, m_connectedSources) { + if (!sources.contains(source)) { + m_data.remove(source); + sourcesChanged = true; + if (m_dataEngine) { + m_dataEngine->disconnectSource(source, this); + emit sourceDisconnected(source); + } + } + } + + if (sourcesChanged) { m_connectedSources = sources; - m_changes |= SourcesChanged; emit connectedSourcesChanged(); } } @@ -70,9 +74,9 @@ void DataSource::setEngine(const QString &e) if (e == m_engine) { return; } - m_engine = e; - m_changes |= DataEngineChanged; + m_engine = e; + setupData(); emit engineChanged(); } @@ -81,61 +85,44 @@ void DataSource::setInterval(const int interval) if (interval == m_interval) { return; } + m_interval = interval; - m_changes |= DataEngineChanged; + setupData(); emit intervalChanged(); } //TODO: event compression for this void DataSource::setupData() { + //FIXME: should all services be deleted just because we're changing the interval, etc? + qDeleteAll(m_services); + m_services.clear(); - if (m_changes & DataEngineChanged) { + Plasma::DataEngine *engine = dataEngine(m_engine); + if (!engine) { + kWarning() << "DataEngine" << m_engine << "not found"; + return; + } + + if (engine != m_dataEngine) { if (m_dataEngine) { - foreach (const QString &source, m_connectedSources) { - m_dataEngine->disconnectSource(source, this); - } + m_dataEngine->disconnect(this); + finishedWithEngine(m_dataEngine->pluginName()); } - qDeleteAll(m_services); - m_services.clear(); - - m_dataEngine = dataEngine(m_engine); - if (!m_dataEngine) { - kWarning() << "DataEngine" << m_engine << "not found"; - return; - } + m_dataEngine = engine; connect(m_dataEngine, SIGNAL(sourceAdded(const QString&)), this, SIGNAL(sourcesChanged())); connect(m_dataEngine, SIGNAL(sourceRemoved(const QString&)), this, SIGNAL(sourcesChanged())); connect(m_dataEngine, SIGNAL(sourceAdded(const QString&)), this, SIGNAL(sourceAdded(const QString&))); connect(m_dataEngine, SIGNAL(sourceRemoved(const QString&)), this, SLOT(removeSource(const QString&))); connect(m_dataEngine, SIGNAL(sourceRemoved(const QString&)), this, SIGNAL(sourceRemoved(const QString&))); - - //TODO: remove after event compression done - if (!(m_changes & SourcesChanged)) { - foreach (const QString &source, m_connectedSources) { - m_dataEngine->connectSource(source, this, m_interval); - emit sourceConnected(source); - } - } } - if (m_changes & SourcesChanged) { - if (m_dataEngine) { - foreach (const QString &source, m_oldSources) { - m_dataEngine->disconnectSource(source, this); - emit sourceDisconnected(source); - } - foreach (const QString &source, m_newSources) { - m_dataEngine->connectSource(source, this, m_interval); - emit sourceConnected(source); - } - m_oldSources.clear(); - m_newSources.clear(); - } + foreach (const QString &source, m_connectedSources) { + m_dataEngine->connectSource(source, this, m_interval); + emit sourceConnected(source); } - m_changes = NoChange; } void DataSource::dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data) @@ -157,15 +144,12 @@ void DataSource::removeSource(const QString &source) //TODO: emit those signals as last thing if (m_connectedSources.contains(source)) { + m_connectedSources.removeAll(source); emit sourceDisconnected(source); emit connectedSourcesChanged(); } if (m_dataEngine) { - m_connectedSources.removeAll(source); - m_newSources.removeAll(source); - m_oldSources.removeAll(source); - QHash::iterator it = m_services.find(source); if (it != m_services.end()) { delete it.value(); @@ -174,18 +158,14 @@ void DataSource::removeSource(const QString &source) } } -QStringList DataSource::keysForSource(const QString &source) const -{ - if (!m_data.contains(source)) { - return QStringList(); - } - return m_data.value(source).value().keys(); -} - Plasma::Service *DataSource::serviceForSource(const QString &source) { if (!m_services.contains(source)) { - m_services[source] = m_dataEngine->serviceForSource(source); + Plasma::Service *service = m_dataEngine->serviceForSource(source); + if (!service) { + return 0; + } + m_services[source] = service; } return m_services.value(source); @@ -197,20 +177,22 @@ void DataSource::connectSource(const QString &source) return; } - m_newSources.append(source); m_connectedSources.append(source); - m_changes |= SourcesChanged; - emit sourceConnected(source); - emit connectedSourcesChanged(); + if (m_dataEngine) { + m_dataEngine->connectSource(source, this, m_interval); + emit sourceConnected(source); + emit connectedSourcesChanged(); + } } void DataSource::disconnectSource(const QString &source) { - m_oldSources.append(source); - m_connectedSources.removeAll(source); - m_changes |= SourcesChanged; - emit sourceDisconnected(source); - emit connectedSourcesChanged(); + if (m_dataEngine && m_connectedSources.contains(source)) { + m_connectedSources.removeAll(source); + m_dataEngine->disconnectSource(source, this); + emit sourceDisconnected(source); + emit connectedSourcesChanged(); + } } } diff --git a/declarativeimports/core/datasource_p.h b/declarativeimports/core/datasource_p.h index 1004da049..371fd6e3a 100644 --- a/declarativeimports/core/datasource_p.h +++ b/declarativeimports/core/datasource_p.h @@ -73,10 +73,9 @@ public: Q_PROPERTY(QStringList sources READ sources NOTIFY sourcesChanged) QStringList sources() const {if (m_dataEngine) return m_dataEngine->sources(); else return QStringList();} - Q_PROPERTY(QVariantMap data READ data NOTIFY dataChanged); - QVariantMap data() const {return m_data;} + Q_PROPERTY(QVariantHash data READ data NOTIFY dataChanged); + QVariantHash data() const {return m_data;} - Q_INVOKABLE QStringList keysForSource(const QString &source) const; Q_INVOKABLE Plasma::Service *serviceForSource(const QString &source); Q_INVOKABLE void connectSource(const QString &source); @@ -103,7 +102,7 @@ private: QString m_id; int m_interval; QString m_engine; - QVariantMap m_data; + QVariantHash m_data; Plasma::DataEngine* m_dataEngine; QStringList m_connectedSources; QStringList m_oldSources; diff --git a/declarativeimports/core/dialog.cpp b/declarativeimports/core/dialog.cpp index b377a45ee..3b063f36e 100644 --- a/declarativeimports/core/dialog.cpp +++ b/declarativeimports/core/dialog.cpp @@ -28,6 +28,7 @@ #include #include +#include DialogMargins::DialogMargins(Plasma::Dialog *dialog, QObject *parent) @@ -83,7 +84,8 @@ int DialogMargins::bottom() const DialogProxy::DialogProxy(QObject *parent) : QObject(parent), m_declarativeItemContainer(0), - m_activeWindow(false) + m_activeWindow(false), + m_location(Plasma::Floating) { m_dialog = new Plasma::Dialog(); m_margins = new DialogMargins(m_dialog, this); @@ -248,6 +250,21 @@ void DialogProxy::setWindowFlags(const int flags) m_dialog->setWindowFlags((Qt::WindowFlags)flags); } +int DialogProxy::location() const +{ + return (int)m_location; +} + +void DialogProxy::setLocation(int location) +{ + if (m_location == location) { + return; + } + m_location = (Plasma::Location)location; + emit locationChanged(); +} + + QObject *DialogProxy::margins() const { return m_margins; @@ -275,8 +292,10 @@ bool DialogProxy::eventFilter(QObject *watched, QEvent *event) emit heightChanged(); } } else if (watched == m_dialog && event->type() == QEvent::Show) { + Plasma::WindowEffects::slideWindow(m_dialog, m_location); emit visibleChanged(); } else if (watched == m_dialog && event->type() == QEvent::Hide) { + Plasma::WindowEffects::slideWindow(m_dialog, m_location); emit visibleChanged(); } else if (watched == m_dialog && event->type() == QEvent::WindowActivate) { m_activeWindow = true; diff --git a/declarativeimports/core/dialog.h b/declarativeimports/core/dialog.h index 5d60d13bc..a871a80d1 100644 --- a/declarativeimports/core/dialog.h +++ b/declarativeimports/core/dialog.h @@ -23,6 +23,8 @@ #include #include +#include + class QGraphicsObject; namespace Plasma @@ -81,6 +83,7 @@ class DialogProxy : public QObject Q_PROPERTY(int windowFlags READ windowFlags WRITE setWindowFlags) Q_PROPERTY(QObject *margins READ margins CONSTANT) Q_PROPERTY(bool activeWindow READ isActiveWindow NOTIFY activeWindowChanged) + Q_PROPERTY(int location READ location WRITE setLocation NOTIFY locationChanged) public: enum WidgetAttribute { @@ -111,6 +114,9 @@ public: int windowFlags() const; void setWindowFlags(const int); + int location() const; + void setLocation(int location); + QObject *margins() const; //FIXME: alignment should be Qt::AlignmentFlag @@ -126,6 +132,7 @@ Q_SIGNALS: void widthChanged(); void heightChanged(); void activeWindowChanged(); + void locationChanged(); protected Q_SLOTS: void syncMainItem(); @@ -140,6 +147,7 @@ private: QWeakPointer m_mainItem; DialogMargins *m_margins; bool m_activeWindow; + Plasma::Location m_location; }; #endif diff --git a/declarativeimports/core/theme.cpp b/declarativeimports/core/theme.cpp index fd9e15895..eca3d6bfb 100644 --- a/declarativeimports/core/theme.cpp +++ b/declarativeimports/core/theme.cpp @@ -61,6 +61,11 @@ QString ThemeProxy::wallpaperPath() const return Plasma::Theme::defaultTheme()->wallpaperPath(); } +QString ThemeProxy::wallpaperPathForSize(int width, int height) const +{ + return Plasma::Theme::defaultTheme()->wallpaperPath(QSize(width, height)); +} + QColor ThemeProxy::textColor() const { return Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor); diff --git a/declarativeimports/core/theme_p.h b/declarativeimports/core/theme_p.h index 008264991..f1178812e 100644 --- a/declarativeimports/core/theme_p.h +++ b/declarativeimports/core/theme_p.h @@ -63,6 +63,7 @@ public: KUrl homepage() const; bool useGlobalSettings() const; QString wallpaperPath() const; + Q_INVOKABLE QString wallpaperPathForSize(int width=-1, int height=-1) const; QColor textColor() const; QColor highlightColor() const; diff --git a/declarativeimports/plasmacomponents/CMakeLists.txt b/declarativeimports/plasmacomponents/CMakeLists.txt new file mode 100644 index 000000000..bf0c4c280 --- /dev/null +++ b/declarativeimports/plasmacomponents/CMakeLists.txt @@ -0,0 +1,22 @@ +project(plasmacomponents) + +set(plasmacomponents_SRCS + plasmacomponentsplugin.cpp + qrangemodel.cpp + ) + +INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${KDE4_INCLUDES} +) + +qt4_automoc(${plasmacomponents_SRCS}) + + +add_library(plasmacomponentsplugin SHARED ${plasmacomponents_SRCS}) +target_link_libraries(plasmacomponentsplugin ${QT_QTCORE_LIBRARY} ${QT_QTDECLARATIVE_LIBRARY}) + +install(TARGETS plasmacomponentsplugin DESTINATION ${IMPORTS_INSTALL_DIR}/org/kde/plasma/components) + +install(DIRECTORY qml/ DESTINATION ${IMPORTS_INSTALL_DIR}/org/kde/plasma/components) diff --git a/declarativeimports/plasmacomponents/plasmacomponentsplugin.cpp b/declarativeimports/plasmacomponents/plasmacomponentsplugin.cpp new file mode 100644 index 000000000..b1f7bd607 --- /dev/null +++ b/declarativeimports/plasmacomponents/plasmacomponentsplugin.cpp @@ -0,0 +1,36 @@ +/* + * Copyright 2011 by Marco Martin + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "plasmacomponentsplugin.h" + +#include + +#include "qrangemodel.h" + + +void PlasmaComponentsPlugin::registerTypes(const char *uri) +{ + Q_ASSERT(uri == QLatin1String("org.kde.plasma.components")); + + qmlRegisterType(uri, 0, 1, "RangeModel"); +} + + +#include "plasmacomponentsplugin.moc" + diff --git a/declarativeimports/plasmacomponents/plasmacomponentsplugin.h b/declarativeimports/plasmacomponents/plasmacomponentsplugin.h new file mode 100644 index 000000000..65ca8bdca --- /dev/null +++ b/declarativeimports/plasmacomponents/plasmacomponentsplugin.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011 by Marco Martin + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLASMACOMPONENTSPLUGIN_H +#define PLASMACOMPONENTSPLUGIN_H + +#include + +class PlasmaComponentsPlugin : public QDeclarativeExtensionPlugin +{ + Q_OBJECT + +public: + void registerTypes(const char *uri); +}; + +Q_EXPORT_PLUGIN2(plasmacomponentsplugin, PlasmaComponentsPlugin) + +#endif diff --git a/declarativeimports/plasmacomponents/qml/BusyIndicator.qml b/declarativeimports/plasmacomponents/qml/BusyIndicator.qml new file mode 100644 index 000000000..5335d4328 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/BusyIndicator.qml @@ -0,0 +1,64 @@ +/* +* Copyright (C) 2010 by Artur Duque de Souza +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: busy + + // Common API + property bool running: false + + // Plasma API + property bool smoothAnimation: true + + implicitWidth: 52 + implicitHeight: 52 + + // Should use animation's pause to keep the + // rotation smooth when running changes but + // it has lot's of side effects on + // initialization. + onRunningChanged: { + rotationAnimation.from = rotation; + rotationAnimation.to = rotation + 360; + } + + RotationAnimation on rotation { + id: rotationAnimation + + from: 0 + to: 360 + duration: 1500 + running: busy.running + loops: Animation.Infinite + } + + PlasmaCore.SvgItem { + id: widget + + anchors.centerIn: parent + width: busy.width + height: busy.height + smooth: !running || smoothAnimation + svg: PlasmaCore.Svg { imagePath: "widgets/busywidget" } + } +} diff --git a/declarativeimports/plasmacomponents/qml/Button.qml b/declarativeimports/plasmacomponents/qml/Button.qml new file mode 100644 index 000000000..7bd29c881 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/Button.qml @@ -0,0 +1,161 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: button + + // Commmon API + property bool checked: false + property bool checkable: false + property alias pressed: mouse.pressed + property alias text: label.text + property alias iconSource: icon.source + property alias font: label.font + + signal clicked() + + PlasmaCore.Theme { + id: theme + } + + function pressButton() { + if (button.enabled) + surface.prefix = "pressed"; + } + + function releaseButton() { + if (!button.enabled) + return; + + if (button.checkable) + button.checked = !button.checked; + + // TODO: "checked" state must have special graphics? + if (button.checked) + surface.prefix = "pressed"; + else + surface.prefix = "normal"; + + button.clicked(); + button.forceActiveFocus(); + } + + width: Math.max(50, icon.width + label.paintedWidth + surface.margins.left + surface.margins.right) + height: Math.max(20, Math.max(icon.height, label.paintedHeight) + surface.margins.top + surface.margins.bottom) + // TODO: needs to define if there will be specific graphics for + // disabled buttons + opacity: enabled ? 1.0 : 0.5 + + Keys.onSpacePressed: pressButton(); + Keys.onReturnPressed: pressButton(); + Keys.onReleased: { + if (event.key == Qt.Key_Space || + event.key == Qt.Key_Return) + releaseButton(); + } + + onActiveFocusChanged: { + if (activeFocus) { + shadow.state = "focus" + } else if (checked) { + shadow.state = "hidden" + } else { + shadow.state = "shadow" + } + } + + ButtonShadow { + id: shadow + anchors.fill: parent + } + + PlasmaCore.FrameSvgItem { + id: surface + + anchors.fill: parent + imagePath: "widgets/button" + prefix: "normal" + } + + Item { + anchors { + fill: parent + leftMargin: surface.margins.left + topMargin: surface.margins.top + rightMargin: surface.margins.right + bottomMargin: surface.margins.bottom + } + + Image { + id: icon + + anchors { + fill: label.text ? undefined : parent + top: label.text ? parent.top : undefined + left: label.text ? parent.left : undefined + bottom: label.text ? parent.bottom : undefined + } + fillMode: Image.PreserveAspectFit + } + + Text { + id: label + + anchors { + top: parent.top + bottom: parent.bottom + left: icon.right + right: parent.right + } + color: theme.buttonTextColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + + MouseArea { + id: mouse + + anchors.fill: parent + hoverEnabled: true + + onPressed: { + pressButton(); + } + onReleased: { + releaseButton(); + } + onEntered: { + shadow.state = "hover" + } + onExited: { + if (button.activeFocus) { + shadow.state = "focus" + } else if (checked) { + shadow.state = "hidden" + } else { + shadow.state = "shadow" + } + } + } +} + diff --git a/declarativeimports/plasmacomponents/qml/ButtonColumn.qml b/declarativeimports/plasmacomponents/qml/ButtonColumn.qml new file mode 100644 index 000000000..752481c26 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ButtonColumn.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt 4.7 +import "ButtonGroup.js" as Behavior + +/* + Class: ButtonColumn + A ButtonColumn allows you to group Buttons in a column. It provides a selection-behavior as well. + + Note: This component don't support the enabled property. + If you need to disable it you should disable all the buttons inside it. + + + ButtonColumn { + Button { text: "Top" } + Button { text: "Bottom" } + } + +*/ +Column { + id: root + + /* + * Property: exclusive + * [bool=true] Specifies the grouping behavior. If enabled, the checked property on buttons contained + * in the group will be exclusive. + * + * Note that a button in an exclusive group will allways be checkable + */ + property bool exclusive: true + + /* + * Property: checkedButton + * [string] Contains the last checked Button. + */ + property Item checkedButton; + + Component.onCompleted: { + Behavior.create(root, {direction: Qt.Vertical}); + } + + Component.onDestruction: { + Behavior.destroy(); + } + +} diff --git a/declarativeimports/plasmacomponents/qml/ButtonGroup.js b/declarativeimports/plasmacomponents/qml/ButtonGroup.js new file mode 100644 index 000000000..ea8ca7485 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ButtonGroup.js @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +var self; +var checkHandlers = []; +var visibleButtons = []; +var nonVisibleButtons = []; +var direction; + +function create(that, options) { + self = that; + direction = options.direction || Qt.Horizontal; + self.childrenChanged.connect(rebuild); +// self.widthChanged.connect(resizeChildren); + build(); +} + +function isButton(item) { + if (item && item.hasOwnProperty("__position")) + return true; + return false; +} + +function hasChecked(item) { + return (item && item.hasOwnProperty("checked")); +} + +function destroy() { + self.childrenChanged.disconnect(rebuild); +// self.widthChanged.disconnect(resizeChildren); + cleanup(); +} + +function build() { + visibleButtons = []; + nonVisibleButtons = []; + + for (var i = 0, item; (item = self.children[i]); i++) { + if (!hasChecked(item)) + continue; + + item.visibleChanged.connect(rebuild); // Not optimal, but hardly a bottleneck in your app + if (!item.visible) { + nonVisibleButtons.push(item); + continue; + } + visibleButtons.push(item); + + if (self.exclusive && item.hasOwnProperty("checkable")) + item.checkable = true; + + if (self.exclusive) { + item.checked = false; + checkHandlers.push(checkExclusive(item)); + item.checkedChanged.connect(checkHandlers[checkHandlers.length - 1]); + } + } + + var nrButtons = visibleButtons.length; + if (nrButtons == 0) + return; + + if (self.checkedButton) + self.checkedButton.checked = true; + else if (self.exclusive) { + self.checkedButton = visibleButtons[0]; + self.checkedButton.checked = true; + } + + if (nrButtons == 1) { + finishButton(visibleButtons[0], "only"); + } else { + finishButton(visibleButtons[0], direction == Qt.Horizontal ? "leftmost" : "top"); + for (var i = 1; i < nrButtons - 1; i++) + finishButton(visibleButtons[i], direction == Qt.Horizontal ? "h_middle": "v_middle"); + finishButton(visibleButtons[nrButtons - 1], direction == Qt.Horizontal ? "rightmost" : "bottom"); + } +} + +function finishButton(button, position) { + if (isButton(button)) { + button.__position = position; + if (direction == Qt.Vertical) { + button.anchors.left = self.left //mm How to make this not cause binding loops? see QTBUG-17162 + button.anchors.right = self.right + } + } +} + +function cleanup() { + visibleButtons.forEach(function(item, i) { + if (checkHandlers[i]) + item.checkedChanged.disconnect(checkHandlers[i]); + item.visibleChanged.disconnect(rebuild); + }); + checkHandlers = []; + + nonVisibleButtons.forEach(function(item, i) { + item.visibleChanged.disconnect(rebuild); + }); +} + +function rebuild() { + if (self == undefined) + return; + + cleanup(); + build(); +} + +function resizeChildren() { + if (direction != Qt.Horizontal) + return; + + var extraPixels = self.width % visibleButtons; + var buttonSize = (self.width - extraPixels) / visibleButtons; + visibleButtons.forEach(function(item, i) { + if (!item || !item.visible) + return; + item.width = buttonSize + (extraPixels > 0 ? 1 : 0); + if (extraPixels > 0) + extraPixels--; + }); +} + +function checkExclusive(item) { + var button = item; + return function() { + for (var i = 0, ref; (ref = visibleButtons[i]); i++) { + if (ref.checked == (button === ref)) + continue; + + // Disconnect the signal to avoid recursive calls + ref.checkedChanged.disconnect(checkHandlers[i]); + ref.checked = !ref.checked; + ref.checkedChanged.connect(checkHandlers[i]); + } + self.checkedButton = button; + } +} diff --git a/declarativeimports/plasmacomponents/qml/ButtonRow.qml b/declarativeimports/plasmacomponents/qml/ButtonRow.qml new file mode 100644 index 000000000..e88b015d4 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ButtonRow.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.1 +import "ButtonGroup.js" as Behavior + +/* + Class: ButtonRow + A ButtonRow allows you to group Buttons in a row. It provides a selection-behavior as well. + + Note: This component don't support the enabled property. + If you need to disable it you should disable all the buttons inside it. + + + ButtonRow { + Button { text: "Left" } + Button { text: "Right" } + } + +*/ +Row { + id: root + + /* + * Property: exclusive + * [bool=true] Specifies the grouping behavior. If enabled, the checked property on buttons contained + * in the group will be exclusive. + * + * Note that a button in an exclusive group will allways be checkable + */ + property bool exclusive: true + + /* + * Property: checkedButton + * [string] Contains the last checked Button. + */ + property Item checkedButton; + + Component.onCompleted: { + Behavior.create(root, {direction: Qt.Horizontal}); + } + + Component.onDestruction: { + Behavior.destroy(); + } +} diff --git a/declarativeimports/plasmacomponents/qml/ButtonShadow.qml b/declarativeimports/plasmacomponents/qml/ButtonShadow.qml new file mode 100644 index 000000000..dcf8d233e --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ButtonShadow.qml @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2011 by Daker Fernandes Pinheiro + * Copyright (C) 2011 by Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: main + state: parent.state + + PlasmaCore.FrameSvgItem { + id: hover + + anchors { + fill: parent + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + opacity: 0 + imagePath: "widgets/button" + prefix: "hover" + } + + PlasmaCore.FrameSvgItem { + id: shadow + + anchors { + fill: parent + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + imagePath: "widgets/button" + prefix: "shadow" + } + + states: [ + State { + name: "shadow" + PropertyChanges { + target: shadow + opacity: 1 + } + PropertyChanges { + target: hover + opacity: 0 + prefix: "hover" + } + }, + State { + name: "hover" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 1 + prefix: "hover" + } + }, + State { + name: "focus" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 1 + prefix: "focus" + } + }, + State { + name: "hidden" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 0 + prefix: "hover" + } + } + ] + + transitions: [ + Transition { + PropertyAnimation { + properties: "opacity" + duration: 250 + easing.type: Easing.OutQuad + } + } + ] +} diff --git a/declarativeimports/plasmacomponents/qml/CheckBox.qml b/declarativeimports/plasmacomponents/qml/CheckBox.qml new file mode 100644 index 000000000..28bf4cc94 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/CheckBox.qml @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +DualStateButton { + id: checkBox + view: PlasmaCore.FrameSvgItem { + imagePath: "widgets/button" + prefix: "normal" + width: fontMetricText.height + margins.left + height: fontMetricText.height + margins.top + //FIXME: an hack to have font metrics: can we have a proper binding? + Text { + id: fontMetricText + text: "M" + visible: false + } + PlasmaCore.SvgItem { + svg: PlasmaCore.Svg { + id: checkmarkSvg + imagePath: "widgets/checkmarks" + } + elementId: "checkbox" + opacity: checked ? 1 : 0 + anchors { + fill: parent + margins: parent.margins.left/2 + } + Behavior on opacity { + NumberAnimation { + duration: 250 + easing.type: Easing.InOutQuad + } + } + } + } + + shadow: ButtonShadow {} +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/DualStateButton.qml b/declarativeimports/plasmacomponents/qml/DualStateButton.qml new file mode 100644 index 000000000..3b6d529b3 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/DualStateButton.qml @@ -0,0 +1,110 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: dualButton + + // Common API + property bool checked + property alias pressed: mouseArea.pressed + + signal clicked() + + // Plasma API + property alias text: label.text // TODO: Not yet part of the common API + property QtObject theme: PlasmaCore.Theme { } + property alias view: surfaceLoader.sourceComponent + property alias shadow: shadowLoader.sourceComponent + + width: surfaceLoader.width + label.paintedWidth + height: surfaceLoader.height + // TODO: needs to define if there will be specific graphics for + // disabled buttons + opacity: dualButton.enabled ? 1.0 : 0.5 + + function entered() { + if (dualButton.enabled) { + shadowLoader.state = "hover" + } + } + + function released() { + if (dualButton.enabled) { + dualButton.checked = !dualButton.checked; + dualButton.clicked(); + } + } + + Keys.onSpacePressed: entered(); + Keys.onReturnPressed: entered(); + Keys.onReleased: { + if(event.key == Qt.Key_Space || + event.key == Qt.Key_Return) + released(); + } + + Loader { + id: shadowLoader + anchors.fill: surfaceLoader + } + + Loader { + id: surfaceLoader + + anchors { + verticalCenter: parent.verticalCenter + left: text ? parent.left : undefined + horizontalCenter: text ? undefined : parent.horizontalCenter + } + } + + Text { + id: label + + text: dualButton.text + anchors { + top: parent.top + bottom: parent.bottom + left: surfaceLoader.right + right: parent.right + //FIXME: see how this margin will be set + leftMargin: height/4 + } + color: theme.textColor + verticalAlignment: Text.AlignVCenter + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + hoverEnabled: true + + onReleased: dualButton.released(); + onEntered: dualButton.entered(); + onPressed: dualButton.forceActiveFocus(); + onExited: { + shadowLoader.state = "shadow" + } + } +} + diff --git a/declarativeimports/plasmacomponents/qml/Highlight.qml b/declarativeimports/plasmacomponents/qml/Highlight.qml new file mode 100644 index 000000000..9670c2837 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/Highlight.qml @@ -0,0 +1,49 @@ +/* + * Copyright 2011 Daker Fernandes Pinheiro + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: highlight + + property bool hover: false + property bool pressed: false + + PlasmaCore.FrameSvgItem { + id: background + imagePath: "widgets/viewitem" + prefix: { + if (pressed) + return hover ? "selected+hover" : "selected"; + + if (hover) + return "hover"; + + return "normal"; + } + + anchors { + fill: parent + topMargin: -background.margins.top + leftMargin: -background.margins.left + bottomMargin: -background.margins.bottom + rightMargin: -background.margins.right + } + } +} diff --git a/declarativeimports/plasmacomponents/qml/ProgressBar.qml b/declarativeimports/plasmacomponents/qml/ProgressBar.qml new file mode 100644 index 000000000..efce6f20f --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ProgressBar.qml @@ -0,0 +1,99 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: progressBar + + // Common API + property alias minimumValue: range.minimumValue + property alias maximumValue: range.maximumValue + property alias value: range.value + property alias indeterminate: indeterminateAnimation.running + + // Plasma API + property int orientation: Qt.Horizontal + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + + width: 100 + height: 20 + opacity: enabled ? 1.0 : 0.5 + + RangeModel { + id: range + + // default values + minimumValue: 0.0 + maximumValue: 1.0 + value: 0 + + positionAtMinimum: 0 + positionAtMaximum: contents.width + } + + Item { + id: contents + + width: _isVertical ? progressBar.height : progressBar.width + height: _isVertical ? progressBar.width : progressBar.height + rotation: _isVertical ? 90 : 0 + anchors.centerIn: parent + + PlasmaCore.FrameSvgItem { + id: background + + anchors.fill: parent + imagePath: "widgets/bar_meter_horizontal" + prefix: "bar-inactive" + } + + PlasmaCore.FrameSvgItem { + id: bar + + width: indeterminate ? contents.width / 4 : range.position + height: contents.height + imagePath: "widgets/bar_meter_horizontal" + prefix: "bar-active" + visible: indeterminate || value > 0 + + SequentialAnimation { + id: indeterminateAnimation + + loops: Animation.Infinite + + PropertyAnimation { + target: bar; + property: "x" + duration: 800 + to: 0 + } + PropertyAnimation { + target: bar; + property: "x" + duration: 800 + to: background.width - bar.width + } + } + } + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/RadioButton.qml b/declarativeimports/plasmacomponents/qml/RadioButton.qml new file mode 100644 index 000000000..f417c25c5 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/RadioButton.qml @@ -0,0 +1,62 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + + +//FIXME: this should be round, DualStateButton shouldn't draw the shadow +DualStateButton { + id: radioButton + view: PlasmaCore.SvgItem { + svg: PlasmaCore.Svg { + id: buttonSvg + imagePath: "widgets/actionbutton" + } + elementId: "normal" + width: fontMetricText.height + 6 + height: width + //FIXME: an hack to have font metrics: can we have a proper binding? + Text { + id: fontMetricText + text: "M" + visible: false + } + PlasmaCore.SvgItem { + svg: PlasmaCore.Svg { + id: checkmarkSvg + imagePath: "widgets/checkmarks" + } + elementId: "radiobutton" + opacity: checked ? 1 : 0 + anchors { + fill: parent + margins: parent.margins.left/2 + } + Behavior on opacity { + NumberAnimation { + duration: 250 + easing.type: Easing.InOutQuad + } + } + } + } + + shadow: RoundShadow {} +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/RoundShadow.qml b/declarativeimports/plasmacomponents/qml/RoundShadow.qml new file mode 100644 index 000000000..fce6f7eb9 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/RoundShadow.qml @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2011 by Daker Fernandes Pinheiro + * Copyright (C) 2011 by Marco Martin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, 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 Library General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: main + state: parent.state + + PlasmaCore.SvgItem { + id: hover + svg: PlasmaCore.Svg { + id: hoverSvg + imagePath: "widgets/actionbutton" + } + elementId: "hover" + + anchors.fill: parent + + opacity: 0 + } + + PlasmaCore.SvgItem { + id: shadow + svg: PlasmaCore.Svg { + id: shadowSvg + imagePath: "widgets/actionbutton" + } + elementId: "shadow" + + anchors.fill: parent + } + + states: [ + State { + name: "shadow" + PropertyChanges { + target: shadow + opacity: 1 + } + PropertyChanges { + target: hover + opacity: 0 + elementId: "hover" + } + }, + State { + name: "hover" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 1 + elementId: "hover" + } + }, + State { + name: "focus" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 1 + elementId: "focus" + } + }, + State { + name: "hover" + PropertyChanges { + target: shadow + opacity: 0 + } + PropertyChanges { + target: hover + opacity: 0 + elementId: "hover" + } + } + ] + + transitions: [ + Transition { + PropertyAnimation { + properties: "opacity" + duration: 250 + easing.type: Easing.OutQuad + } + } + ] +} diff --git a/declarativeimports/plasmacomponents/qml/ScrollBar.qml b/declarativeimports/plasmacomponents/qml/ScrollBar.qml new file mode 100644 index 000000000..8adc8b615 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ScrollBar.qml @@ -0,0 +1,349 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +// TODO: add support mouse wheel and key events +Item { + id: scrollbar + + // Common API + property Flickable flickableItem: null + + // Plasma API + property int orientation: Qt.Horizontal + property bool animated: true + property bool inverted: false + property bool updateValueWhileDragging: true + property alias stepSize: range.stepSize + property alias pressed: mouseArea.pressed + property real scrollButtonInterval: 50 + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + property bool _showButtons: stepSize != 0 + property bool _inverted: _isVertical ? + !scrollbar.inverted : scrollbar.inverted + + implicitWidth: _isVertical ? 22 : 200 + implicitHeight: _isVertical ? 200 : 22 + // TODO: needs to define if there will be specific graphics for + // disabled scroll bars + opacity: enabled ? 1.0 : 0.5 + + visible: flickableItem && handle.width < contents.width + + function incrementValue(increment) { + if (!flickableItem) + return; + + if (_isVertical) { + flickableItem.contentY = Math.min(flickableItem.contentHeight, + flickableItem.contentY + increment); + } else { + flickableItem.contentX = Math.min(flickableItem.contentWidth, + flickableItem.contentX + increment); + } + } + + Keys.onUpPressed: { + if (!enabled || !_isVertical) + return; + + if (_inverted) + incrementValue(-stepSize); + else + incrementValue(stepSize); + } + + Keys.onDownPressed: { + if (!enabled || !_isVertical) + return; + + if (_inverted) + incrementValue(stepSize); + else + incrementValue(-stepSize); + } + + Keys.onLeftPressed: { + if (!enabled || _isVertical) + return; + + if (_inverted) + incrementValue(stepSize); + else + incrementValue(-stepSize); + } + + Keys.onRightPressed: { + if (!enabled || _isVertical) + return; + + if (_inverted) + incrementValue(-stepSize); + else + incrementValue(stepSize); + } + + + Item { + + width: _isVertical ? scrollbar.height : scrollbar.width + height: _isVertical ? scrollbar.width : scrollbar.height + rotation: _isVertical ? -90 : 0 + + anchors.centerIn: parent + PlasmaCore.Svg { + id: scrollbarSvg + imagePath: "widgets/scrollbar" + } + + PlasmaCore.SvgItem { + id: leftButton + + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + } + height: 18 + width: _showButtons ? 18 : 0 + svg: scrollbarSvg + elementId: { + if (leftMousArea.pressed) + return "sunken-arrow-left"; + + if (scrollbar.activeFocus || leftMousArea.containsMouse) + return "mouseover-arrow-left"; + else + return "arrow-left"; + } + + MouseArea { + id: leftMousArea + + anchors.fill: parent + enabled: scrollbar.enabled + Timer { + id: leftTimer + interval: scrollbar.scrollButtonInterval; + running: parent.pressed + repeat: true + onTriggered: { + scrollbar.forceActiveFocus(); + if (_inverted) + incrementValue(stepSize); + else + incrementValue(-stepSize); + } + } + } + } + + PlasmaCore.SvgItem { + id: rightButton + + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + height: 18 + width: _showButtons ? 18 : 0 + svg: scrollbarSvg + elementId: { + if (rightMousArea.pressed) + return "sunken-arrow-right"; + + if (scrollbar.activeFocus || rightMousArea.containsMouse) + return "mouseover-arrow-right"; + else + return "arrow-right"; + } + + MouseArea { + id: rightMousArea + + anchors.fill: parent + enabled: scrollbar.enabled + Timer { + id: rightTimer + interval: scrollbar.scrollButtonInterval; + running: parent.pressed; + repeat: true + onTriggered: { + scrollbar.forceActiveFocus(); + if (_inverted) + incrementValue(-stepSize); + else + incrementValue(stepSize); + } + } + } + } + + Item { + id: contents + + anchors { + left: leftButton.right + top: parent.top + bottom: parent.bottom + right: rightButton.left + } + + RangeModel { + id: range + + minimumValue: 0 + maximumValue: { + var diff; + if (_isVertical) + diff = flickableItem.contentHeight - flickableItem.height; + else + diff = flickableItem.contentWidth - flickableItem.width; + + return Math.max(0, diff); + } + stepSize: 0.0 + inverted: _inverted + positionAtMinimum: 0 + handle.width / 2 + positionAtMaximum: contents.width - handle.width / 2 + value: _isVertical ? flickableItem.contentY : flickableItem.contentX + onValueChanged: { + if (flickableItem.flicking) + return; + + if (_isVertical) + flickableItem.contentY = value; + else + flickableItem.contentX = value; + } + position: handle.x + onPositionChanged: { handle.x = position; } + } + + PlasmaCore.FrameSvgItem { + id: groove + + anchors.fill: parent + imagePath: "widgets/scrollbar" + prefix: "background-horizontal" + } + + PlasmaCore.FrameSvgItem { + id: handle + + transform: Translate { x: - handle.width / 2 } + x: fakeHandle.x + anchors.verticalCenter: groove.verticalCenter + width: { + var ratio; + if (_isVertical) + ratio = flickableItem.visibleArea.heightRatio; + else + ratio = flickableItem.visibleArea.widthRatio; + + return ratio * parent.width; + } + height: parent.height - margins.top // TODO: check mergin + imagePath: "widgets/scrollbar" + prefix: { + if (scrollbar.pressed) + return "sunken-slider"; + + if (scrollbar.activeFocus || mouseArea.containsMouse) + return "mouseover-slider"; + else + return "slider"; + } + + Behavior on x { + id: behavior + enabled: !mouseArea.drag.active && scrollbar.animated && + !flickableItem.flicking + + PropertyAnimation { + duration: behavior.enabled ? 150 : 0 + easing.type: Easing.OutSine + } + } + } + + Item { + id: fakeHandle + width: handle.width + height: handle.height + transform: Translate { x: - handle.width / 2 } + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + enabled: scrollbar.enabled + drag { + target: fakeHandle + axis: Drag.XAxis + minimumX: range.positionAtMinimum + maximumX: range.positionAtMaximum + } + + onPressed: { + // Clamp the value + var newX = Math.max(mouse.x, drag.minimumX); + newX = Math.min(newX, drag.maximumX); + + // Debounce the press: a press event inside the handler will not + // change its position, the user needs to drag it. + if (Math.abs(newX - fakeHandle.x) > handle.width / 2) + range.position = newX; + + scrollbar.forceActiveFocus(); + } + onReleased: { + // If we don't update while dragging, this is the only + // moment that the range is updated. + if (!scrollbar.updateValueWhileDragging) + range.position = fakeHandle.x; + } + } + } + + // Range position normally follow fakeHandle, except when + // 'updateValueWhileDragging' is false. In this case it will only follow + // if the user is not pressing the handle. + Binding { + when: updateValueWhileDragging || !mouseArea.pressed + target: range + property: "position" + value: fakeHandle.x + } + + // During the drag, we simply ignore position set from the range, this + // means that setting a value while dragging will not "interrupt" the + // dragging activity. + Binding { + when: !mouseArea.drag.active + target: fakeHandle + property: "x" + value: range.position + } + } +} diff --git a/declarativeimports/plasmacomponents/qml/ScrollDecorator.qml b/declarativeimports/plasmacomponents/qml/ScrollDecorator.qml new file mode 100644 index 000000000..61025fe87 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ScrollDecorator.qml @@ -0,0 +1,106 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: scrollDecorator + + // Common API + property Flickable flickableItem + + // Plasma API + property int orientation: Qt.Horizontal + property bool inverted: false + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + property bool _inverted: _isVertical ? + !scrollDecorator.inverted : scrollDecorator.inverted + property alias _value: range.value + + implicitWidth: _isVertical ? 16 : 200 + implicitHeight: _isVertical ? 200 : 16 + + visible: flickableItem && handle.width < contents.width + + Item { + width: _isVertical ? scrollDecorator.height : scrollDecorator.width + height: _isVertical ? scrollDecorator.width : scrollDecorator.height + rotation: _isVertical ? -90 : 0 + + anchors.centerIn: parent + + PlasmaCore.FrameSvgItem { + id: contents + imagePath: "widgets/scrollbar" + prefix: "background-horizontal" + + anchors.fill: parent + opacity: flickableItem && (flickableItem.flicking || flickableItem.moving) ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: 250 + easing.type: Easing.OutQuad + } + } + + RangeModel { + id: range + + minimumValue: 0 + maximumValue: { + var diff; + if (_isVertical) + diff = flickableItem.contentHeight - flickableItem.height; + else + diff = flickableItem.contentWidth - flickableItem.width; + + return Math.max(0, diff); + } + stepSize: 0.0 + inverted: _inverted + positionAtMinimum: 0 + handle.width / 2 + positionAtMaximum: contents.width - handle.width / 2 + value: _isVertical ? flickableItem.contentY : flickableItem.contentX + } + + PlasmaCore.FrameSvgItem { + id: handle + + x: range.position + transform: Translate { x: - handle.width / 2 } + anchors.verticalCenter: parent.verticalCenter + width: { + var ratio; + if (_isVertical) + ratio = flickableItem.visibleArea.heightRatio; + else + ratio = flickableItem.visibleArea.widthRatio; + + return ratio * parent.width; + } + height: parent.height - margins.top // TODO: check mergin + imagePath: "widgets/scrollbar" + prefix: "slider" + } + } + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/Slider.qml b/declarativeimports/plasmacomponents/qml/Slider.qml new file mode 100644 index 000000000..1458dc6ec --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/Slider.qml @@ -0,0 +1,272 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +// TODO: create a value indicator for plasma? +Item { + id: slider + + // Common API + property alias stepSize: range.stepSize + property alias minimumValue: range.minimumValue + property alias maximumValue: range.maximumValue + property alias value: range.value + property int orientation: Qt.Horizontal + property alias pressed: mouseArea.pressed + property bool valueIndicatorVisible: false + property string valueIndicatorText: value + + // Plasma API + property bool animated: false + property alias inverted: range.inverted + property bool updateValueWhileDragging: true + property real handleSize: 22 + + // Convinience API + property bool _isVertical: orientation == Qt.Vertical + + width: _isVertical ? 22 : 200 + height: _isVertical ? 200 : 22 + // TODO: needs to define if there will be specific graphics for + // disabled sliders + opacity: enabled ? 1.0 : 0.5 + + Keys.onUpPressed: { + if (!enabled || !_isVertical) + return; + + if (inverted) + value -= stepSize; + else + value += stepSize; + } + + Keys.onDownPressed: { + if (!enabled || !enabled) + return; + + if (!_isVertical) + return; + + if (inverted) + value += stepSize; + else + value -= stepSize; + } + + Keys.onLeftPressed: { + if (!enabled || _isVertical) + return; + + if (inverted) + value += stepSize; + else + value -= stepSize; + } + + Keys.onRightPressed: { + if (!enabled || _isVertical) + return; + + if (inverted) + value -= stepSize; + else + value += stepSize; + } + + Item { + id: contents + + width: _isVertical ? slider.height : slider.width + height: _isVertical ? slider.width : slider.height + rotation: _isVertical ? -90 : 0 + + anchors.centerIn: parent + + RangeModel { + id: range + + minimumValue: 0.0 + maximumValue: 1.0 + value: 0 + stepSize: 0.0 + inverted: false + positionAtMinimum: 0 + handle.width / 2 + positionAtMaximum: contents.width - handle.width / 2 + } + + PlasmaCore.Svg { + id: grooveSvg + imagePath: "widgets/slider" + } + PlasmaCore.FrameSvgItem { + id: groove + imagePath: "widgets/slider" + prefix: "groove" + //FIXME: frameSvg should have a minimumSize attribute, could be added to kdelibs 4.7(maybe just the qml binding is enough)? + height: grooveSvg.elementSize("groove-topleft").height + grooveSvg.elementSize("groove-bottomleft").height + anchors { + left: parent.left + right: parent.right + verticalCenter: parent.verticalCenter + } + } + PlasmaCore.FrameSvgItem { + id: highlight + imagePath: "widgets/slider" + prefix: "groove-highlight" + height: groove.height + width: inverted ? groove.width - handle.x : fakeHandle.x + x: inverted ? handle.x : 0 + anchors.verticalCenter: parent.verticalCenter + + visible: range.position > 0 && slider.enabled + } + + PlasmaCore.SvgItem { + id: focus + + transform: Translate { x: - handle.width / 2 } + anchors { + fill: handle + margins: -1 // Hardcoded + } + opacity: slider.activeFocus ? 1 : 0 + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-hover" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.SvgItem { + id: hover + + transform: Translate { x: - handle.width / 2 } + anchors { + fill: handle + margins: -2 // Hardcoded + } + opacity: 0 + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-hover" + + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + PlasmaCore.SvgItem { + id: handle + + transform: Translate { x: - handle.width / 2 } + x: fakeHandle.x + anchors { + verticalCenter: groove.verticalCenter + } + width: handleSize + height: handleSize + svg: PlasmaCore.Svg { imagePath: "widgets/slider" } + elementId: "horizontal-slider-handle" + + Behavior on x { + id: behavior + enabled: !mouseArea.drag.active && slider.animated + + PropertyAnimation { + duration: behavior.enabled ? 150 : 0 + easing.type: Easing.OutSine + } + } + } + + Item { + id: fakeHandle + width: handle.width + height: handle.height + transform: Translate { x: - handle.width / 2 } + } + + MouseArea { + id: mouseArea + + anchors.fill: parent + enabled: slider.enabled + drag { + target: fakeHandle + axis: Drag.XAxis + minimumX: range.positionAtMinimum + maximumX: range.positionAtMaximum + } + hoverEnabled: true + + onEntered: { + hover.opacity = 1; + } + onExited: { + if (!pressed) + hover.opacity = 0; + } + onPressed: { + // Clamp the value + var newX = Math.max(mouse.x, drag.minimumX); + newX = Math.min(newX, drag.maximumX); + + // Debounce the press: a press event inside the handler will not + // change its position, the user needs to drag it. + if (Math.abs(newX - fakeHandle.x) > handle.width / 2) + range.position = newX; + + slider.forceActiveFocus(); + } + onReleased: { + // If we don't update while dragging, this is the only + // moment that the range is updated. + if (!slider.updateValueWhileDragging) + range.position = fakeHandle.x; + + if (!containsMouse) + hover.opacity = 0; + } + } + } + + // Range position normally follow fakeHandle, except when + // 'updateValueWhileDragging' is false. In this case it will only follow + // if the user is not pressing the handle. + Binding { + when: updateValueWhileDragging || !mouseArea.pressed + target: range + property: "position" + value: fakeHandle.x + } + + // During the drag, we simply ignore position set from the range, this + // means that setting a value while dragging will not "interrupt" the + // dragging activity. + Binding { + when: !mouseArea.drag.active + target: fakeHandle + property: "x" + value: range.position + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/Switch.qml b/declarativeimports/plasmacomponents/qml/Switch.qml new file mode 100644 index 000000000..6d997f538 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/Switch.qml @@ -0,0 +1,78 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +DualStateButton { + id: switchItem + + view: PlasmaCore.FrameSvgItem { + imagePath: "widgets/slider" + prefix: "groove" + width: height * 2 + height: fontMetricText.height + margins.top + //FIXME: an hack to have font metrics: can we have a proper binding? + Text { + id: fontMetricText + text: "M" + visible: false + } + + PlasmaCore.FrameSvgItem { + id: highlight + imagePath: "widgets/slider" + prefix: "groove-highlight" + anchors.fill: parent + + opacity: checked ? 1 : 0 + Behavior on opacity { + PropertyAnimation { duration: 100 } + } + } + + PlasmaCore.FrameSvgItem { + imagePath: "widgets/button" + prefix: "shadow" + anchors { + fill: button + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + } + + PlasmaCore.FrameSvgItem { + id: button + imagePath: "widgets/button" + prefix: "normal" + anchors { + top: parent.top + bottom: parent.bottom + } + width: height + x: checked ? width : 0 + Behavior on x { + PropertyAnimation { duration: 100 } + } + } + } +} + diff --git a/declarativeimports/plasmacomponents/qml/TextArea.qml b/declarativeimports/plasmacomponents/qml/TextArea.qml new file mode 100644 index 000000000..839b75a1b --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/TextArea.qml @@ -0,0 +1,232 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: textArea + + // Common API + property alias font: textEdit.font // alias to textEdit.font + property int inputMethodHints + property bool errorHighlight + property alias cursorPosition: textEdit.cursorPosition + property alias horizontalAlignment: textEdit.cursorPosition + property alias verticalAlignment: textEdit.cursorPosition + property alias readOnly: textEdit.readOnly + property alias selectedText: textEdit.selectedText // read-only + property alias selectionEnd: textEdit.selectionEnd // read-only + property alias selectionStart: textEdit.selectionStart // read-only + property alias text: textEdit.text + property alias textFormat: textEdit.textFormat // enumeration + property alias wrapMode: textEdit.wrapMode // enumeration + property string placeholderText + + // functions + function copy() { + textEdit.copy(); + } + + function paste() { + textEdit.paste(); + } + + function cut() { + textEdit.cut(); + } + + function select(start, end) { + textEdit.select(start, end); + } + + function selectAll() { + textEdit.selectAll(); + } + + function selectWord() { + textEdit.selectWord(); + } + + function positionAt(pos) { + textEdit.positionAt(pos); + } + + function positionToRectangle(pos) { + textEdit.positionToRectangle(pos); + } + + // Plasma API + property alias interactive: flickArea.interactive + property alias contentMaxWidth: textEdit.width + property alias contentMaxHeight: textEdit.height + property real scrollWidth: 22 + + // Set active focus to it's internal textInput. + // Overriding QtQuick.Item forceActiveFocus function. + function forceActiveFocus() { + textEdit.forceActiveFocus(); + } + + // Overriding QtQuick.Item activeFocus property. + property alias activeFocus: textEdit.activeFocus + + opacity: enabled ? 1.0 : 0.5 + + PlasmaCore.FrameSvgItem { + id: hover + + anchors { + fill: base + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + imagePath: "widgets/lineedit" + prefix: { + if (textEdit.activeFocus) + return "focus"; + else + return "hover"; + } + + opacity: (mouseWatcher.containsMouse||textArea.activeFocus) ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: 250 + easing.type: Easing.InOutQuad + } + } + } + MouseArea { + id: mouseWatcher + anchors.fill: hover + hoverEnabled: true + } + + PlasmaCore.FrameSvgItem { + id: base + + // TODO: see what is the best policy for margins + anchors { + fill: flickArea + leftMargin: -2 * base.margins.left + rightMargin: -2 * base.margins.right + topMargin: -2 * base.margins.top + bottomMargin: -2 * base.margins.bottom + } + imagePath: "widgets/lineedit" + prefix: "base" + } + + Flickable { + id: flickArea + anchors { + fill: parent + rightMargin: scrollWidth + bottomMargin: scrollWidth + } + interactive: false //textArea.activeFocus + contentWidth: { + if (textEdit.wrapMode == TextEdit.NoWrap) + return textEdit.paintedWidth; + + return Math.min(textEdit.paintedWidth, textEdit.width); + } + contentHeight: Math.min(textEdit.paintedHeight, textEdit.height) + clip: true + + TextEdit { + id: textEdit + + width: flickArea.width + height: flickArea.height + clip: true + wrapMode: TextEdit.Wrap + enabled: textArea.enabled + + onCursorPositionChanged: { + if (cursorRectangle.x < flickArea.contentX) { + flickArea.contentX = cursorRectangle.x; + return; + } + + if (cursorRectangle.x > flickArea.contentX + + flickArea.width - cursorRectangle.width) { + flickArea.contentX = cursorRectangle.x - + cursorRectangle.width; + return; + } + + if (cursorRectangle.y < flickArea.contentY) { + flickArea.contentY = cursorRectangle.y; + return; + } + + if (cursorRectangle.y > flickArea.contentY + + flickArea.height - cursorRectangle.height) { + flickArea.contentY = cursorRectangle.y - + cursorRectangle.height; + return; + } + } + + // Proxying keys events is not required by the + // common API but is desired in the plasma API. + Keys.onPressed: textArea.Keys.pressed(event); + Keys.onReleased: textArea.Keys.released(event); + + Text { + anchors.fill: parent + text: textArea.placeholderText + visible: textEdit.text == "" && !textArea.activeFocus + opacity: 0.5 + } + } + } + + ScrollBar { + id: horizontalScroll + anchors { + bottom: parent.bottom + left: parent.left + right: flickArea.right + } + enabled: parent.enabled + flickableItem: flickArea + height: visible ? scrollWidth : 0 + orientation: Qt.Horizontal + stepSize: textEdit.font.pixelSize + } + + ScrollBar { + id: verticalScroll + anchors { + right: parent.right + top: parent.top + bottom: flickArea.bottom + } + enabled: parent.enabled + flickableItem: flickArea + width: visible ? scrollWidth : 0 + orientation: Qt.Vertical + stepSize: textEdit.font.pixelSize + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/TextField.qml b/declarativeimports/plasmacomponents/qml/TextField.qml new file mode 100644 index 000000000..71bd57681 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/TextField.qml @@ -0,0 +1,168 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.1 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: textField + + // Common API + property bool errorHighlight: false // TODO + property string placeholderText + property alias inputMethodHints: textInput.inputMethodHints + property alias font: textInput.font + + property alias cursorPosition: textInput.cursorPosition + property alias readOnly: textInput.readOnly + property alias echoMode: textInput.echoMode // Supports TextInput.Normal,TextInput.Password, TextInput.NoEcho, TextInput.PasswordEchoOnEdit + property alias acceptableInput: textInput.acceptableInput // read-only + property alias inputMask: textInput.inputMask + property alias validator: textInput.validator + property alias selectedText: textInput.selectedText // read-only + property alias selectionEnd: textInput.selectionEnd // read-only + property alias selectionStart: textInput.selectionStart // read-only + property alias text: textInput.text + property alias maximumLength: textInput.maximumLength + + function copy() { + textInput.copy(); + } + + function paste() { + textInput.paste(); + } + + function cut() { + textInput.cut(); + } + + function select(start, end) { + textInput.select(start, end); + } + + function selectAll() { + textInput.selectAll(); + } + + function selectWord() { + textInput.selectWord(); + } + + function positionAt(pos) { + textInput.positionAt(pos); + } + + function positionToRectangle(pos) { + textInput.positionToRectangle(pos); + } + + // Plasma API + property QtObject theme: PlasmaCore.Theme { } + + // Set active focus to it's internal textInput. + // Overriding QtQuick.Item forceActiveFocus function. + function forceActiveFocus() { + textInput.forceActiveFocus(); + } + + // Overriding QtQuick.Item activeFocus property. + property alias activeFocus: textInput.activeFocus + + // TODO: fix default size + implicitWidth: 100 + implicitHeight: 26 + // TODO: needs to define if there will be specific graphics for + // disabled text fields + opacity: enabled ? 1.0 : 0.5 + + PlasmaCore.FrameSvgItem { + id: base + + // TODO: see what is the correct policy for margins + anchors.fill: parent + imagePath: "widgets/lineedit" + prefix: "base" + } + + PlasmaCore.FrameSvgItem { + id: hover + + anchors { + fill: parent + leftMargin: -margins.left + topMargin: -margins.top + rightMargin: -margins.right + bottomMargin: -margins.bottom + } + imagePath: "widgets/lineedit" + prefix: { + if (textField.activeFocus) { + return "focus" + } else { + return "hover" + } + } + opacity: (mouseWatcher.containsMouse||textField.activeFocus) ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: 250 + easing.type: Easing.InOutQuad + } + } + } + MouseArea { + id: mouseWatcher + anchors.fill: hover + hoverEnabled: true + } + + Text { + anchors.fill: textInput + text: placeholderText + visible: textInput.text == "" && !textField.activeFocus + // XXX: using textColor and low opacity for theming placeholderText + color: theme.textColor + opacity: 0.5 + elide: Text.ElideRight + clip: true + } + + TextInput { + id: textInput + + anchors { + left: parent.left + right: parent.right + // TODO: see what is the correct policy for margins + leftMargin: 2 * base.margins.left + rightMargin: 2 * base.margins.right + } + y: (height - font.pixelSize) * 0.4 // XXX: verticalCenter anchor is not centering the text + height: Math.min(2 * font.pixelSize, parent.height) + color: theme.textColor + enabled: textField.enabled + clip: true + + // Proxying keys events is not required by the + // common API but is desired in the plasma API. + Keys.onPressed: textField.Keys.pressed(event); + Keys.onReleased: textField.Keys.released(event); + } +} \ No newline at end of file diff --git a/declarativeimports/plasmacomponents/qml/ToolBar.qml b/declarativeimports/plasmacomponents/qml/ToolBar.qml new file mode 100644 index 000000000..68a7472a4 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ToolBar.qml @@ -0,0 +1,166 @@ +/* +* Copyright (C) 2011 by Marco Martin +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +PlasmaCore.FrameSvgItem { + id: toolBar + imagePath: "widgets/frame" + prefix: "raised" + height: 48 + margins.top + margins.bottom + + // The current set of tools; null if none. + property Item tools + + // The transition type. One of the following: + // set an instantaneous change (default) + // push follows page stack push animation + // pop follows page stack pop animation + // replace follows page stack replace animation + property string transition: "set" + + // Sets the tools with a transition. + function setTools(tools, transition) + { + if (toolBar.tools == tools) { + return + } + + toolBar.transition = transition + toolBar.tools = tools + } + onToolsChanged: { + var newContainer + var oldContainer + if (containerA.current) { + newContainer = containerB + oldContainer = containerA + } else { + newContainer = containerA + oldContainer = containerB + } + containerA.current = !containerA.current + + tools.parent = newContainer + tools.visible = true + tools.anchors.left = newContainer.left + tools.anchors.right = newContainer.right + tools.anchors.verticalCenter = newContainer.verticalCenter + + switch (transition) { + case "push": + containerA.animationsEnabled = true + oldContainer.x = -oldContainer.width + + containerA.animationsEnabled = false + newContainer.x = newContainer.width + newContainer.y = 0 + containerA.animationsEnabled = true + newContainer.x = 0 + break + case "pop": + containerA.animationsEnabled = true + oldContainer.x = oldContainer.width + + containerA.animationsEnabled = false + newContainer.x = -newContainer.width + newContainer.y = 0 + containerA.animationsEnabled = true + newContainer.x = 0 + break + case "replace": + containerA.animationsEnabled = true + oldContainer.y = oldContainer.height + + containerA.animationsEnabled = false + newContainer.x = 0 + newContainer.y = -newContainer.height + containerA.animationsEnabled = true + newContainer.y = 0 + break + case "set": + default: + containerA.animationsEnabled = false + containerA.animationsEnabled = false + oldContainer.x = -oldContainer.width + newContainer.x = 0 + break + } + + newContainer.opacity = 1 + oldContainer.opacity = 0 + } + + Item { + anchors { + fill: parent + leftMargin: parent.margins.left + topMargin: parent.margins.top + rightMargin: parent.margins.right + bottomMargin: parent.margins.bottom + } + + Item { + id: containerA + width: parent.width + height: parent.height + property bool animationsEnabled: false + opacity: 0 + //this asymmetry just to not export a property + property bool current: false + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + Behavior on x { + enabled: containerA.animationsEnabled + PropertyAnimation { + duration: 250 + } + } + Behavior on y { + enabled: containerA.animationsEnabled + PropertyAnimation { + duration: 250 + } + } + } + Item { + id: containerB + width: parent.width + height: parent.height + opacity: 0 + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + Behavior on x { + enabled: containerA.animationsEnabled + PropertyAnimation { + duration: 250 + } + } + Behavior on y { + enabled: containerA.animationsEnabled + PropertyAnimation { + duration: 250 + } + } + } + } +} diff --git a/declarativeimports/plasmacomponents/qml/ToolButton.qml b/declarativeimports/plasmacomponents/qml/ToolButton.qml new file mode 100644 index 000000000..d17cbf40b --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/ToolButton.qml @@ -0,0 +1,179 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.core 0.1 as PlasmaCore + +Item { + id: button + + // Commmon API + property bool flat: true + property bool checked: false + property bool checkable: false + property alias pressed: mouse.pressed + property alias text: label.text + property alias iconSource: icon.source + property alias font: label.font + + signal clicked() + + PlasmaCore.Theme { + id: theme + } + + onFlatChanged: { + surface.opacity = 1 + } + + function pressButton() { + if (button.enabled) + surface.prefix = "pressed"; + } + + function releaseButton() { + if (!button.enabled) + return; + + if (button.checkable) + button.checked = !button.checked; + + // TODO: "checked" state must have special graphics? + if (button.checked) + surface.prefix = "pressed"; + else + surface.prefix = "normal"; + + button.clicked(); + button.forceActiveFocus(); + } + + width: Math.max(50, icon.width + label.paintedWidth + surface.margins.left + surface.margins.right) + height: Math.max(20, Math.max(icon.height, label.paintedHeight) + surface.margins.top + surface.margins.bottom) + // TODO: needs to define if there will be specific graphics for + // disabled buttons + opacity: enabled ? 1.0 : 0.5 + + Keys.onSpacePressed: pressButton(); + Keys.onReturnPressed: pressButton(); + Keys.onReleased: { + if (event.key == Qt.Key_Space || + event.key == Qt.Key_Return) + releaseButton(); + } + + onActiveFocusChanged: { + if (activeFocus) { + shadow.state = "focus" + } else if (checked) { + shadow.state = "hidden" + } else { + shadow.state = "shadow" + } + } + + ButtonShadow { + id: shadow + anchors.fill: parent + visible: !flat + } + + PlasmaCore.FrameSvgItem { + id: surface + + anchors.fill: parent + imagePath: "widgets/button" + prefix: "normal" + opacity: 0 + Behavior on opacity { + PropertyAnimation { duration: 250 } + } + } + + Item { + anchors { + fill: parent + leftMargin: surface.margins.left + topMargin: surface.margins.top + rightMargin: surface.margins.right + bottomMargin: surface.margins.bottom + } + + Image { + id: icon + + anchors { + fill: label.text ? undefined : parent + top: label.text ? parent.top : undefined + left: label.text ? parent.left : undefined + bottom: label.text ? parent.bottom : undefined + } + fillMode: Image.PreserveAspectFit + } + + Text { + id: label + + anchors { + top: parent.top + bottom: parent.bottom + left: icon.right + right: parent.right + } + color: theme.buttonTextColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + + MouseArea { + id: mouse + + anchors.fill: parent + hoverEnabled: true + + onPressed: { + pressButton(); + } + onReleased: { + releaseButton(); + } + onEntered: { + if (flat) { + surface.opacity = 1 + } else { + shadow.state = "hover" + } + } + onExited: { + if (flat) { + surface.opacity = 0 + } else { + if (button.activeFocus) { + shadow.state = "focus" + } else if (checked) { + shadow.state = "hidden" + } else { + shadow.state = "shadow" + } + } + } + } +} + diff --git a/declarativeimports/plasmacomponents/qml/qmldir b/declarativeimports/plasmacomponents/qml/qmldir new file mode 100644 index 000000000..0b95953b1 --- /dev/null +++ b/declarativeimports/plasmacomponents/qml/qmldir @@ -0,0 +1,23 @@ +plugin plasmacomponentsplugin + +BusyIndicator 0.1 BusyIndicator.qml +Button 0.1 Button.qml +ButtonGroup 0.1 ButtonGroup.js +ButtonRow 0.1 ButtonRow.qml +ButtonColumn 0.1 ButtonColumn.qml +CheckBox 0.1 CheckBox.qml +FlashingLabel 0.1 FlashingLabel.qml +Frame 0.1 Frame.qml +IconWidget 0.1 IconWidget.qml +Highlight 0.1 Highlight.qml +PushButton 0.1 PushButton.qml +ProgressBar 0.1 ProgressBar.qml +RadioButton 0.1 RadioButton.qml +ScrollBar 0.1 ScrollBar.qml +ScrollDecorator 0.1 ScrollDecorator.qml +Slider 0.1 Slider.qml +Switch 0.1 Switch.qml +TextField 0.1 TextField.qml +TextArea 0.1 TextArea.qml +ToolBar 0.1 ToolBar.qml +ToolButton 0.1 ToolButton.qml diff --git a/declarativeimports/plasmacomponents/qrangemodel.cpp b/declarativeimports/plasmacomponents/qrangemodel.cpp new file mode 100644 index 000000000..fab6d1d9a --- /dev/null +++ b/declarativeimports/plasmacomponents/qrangemodel.cpp @@ -0,0 +1,522 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project on Qt Labs. +** +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions contained +** in the Technology Preview License Agreement accompanying this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +/*! + \class QRangeModel + \brief The QRangeModel class, helps users to build components that depend + on some value and/or position to be in a certain range previously defined + + With this class, the user sets a value range and a position range, which + represent the valid values/positions the model can assume. It is worth telling + that the value property always has priority over the position property. A nice use + case, would be a Slider implementation with the help of QRangeModel. If the user sets + a value range to [0,100], a position range to [50,100] and sets the value + to 80, the equivalent position would be 90. After that, if the user decides to + resize the slider, the value would be the same, but the knob position would + be updated due to the new position range. + + \ingroup qt-components +*/ + +#ifndef QT_NO_ACCESSIBILITY +#include +#endif + +#include "qrangemodel.h" +#include "qrangemodel_p.h" + +namespace Plasma +{ + +QRangeModelPrivate::QRangeModelPrivate(QRangeModel *qq) + : q_ptr(qq) +{ +} + +QRangeModelPrivate::~QRangeModelPrivate() +{ +} + +void QRangeModelPrivate::init() +{ + minimum = 0; + maximum = 99; + stepSize = 0; + value = 0; + pos = 0; + posatmin = 0; + posatmax = 0; + inverted = false; +} + +/*! + Calculates the position that is going to be seen outside by the component + that is using QRangeModel. It takes into account the \l stepSize, + \l positionAtMinimum, \l positionAtMaximum properties + and \a position that is passed as parameter. +*/ + +qreal QRangeModelPrivate::publicPosition(qreal position) const +{ + // Calculate the equivalent stepSize for the position property. + const qreal min = effectivePosAtMin(); + const qreal max = effectivePosAtMax(); + const qreal valueRange = maximum - minimum; + const qreal positionValueRatio = valueRange ? (max - min) / valueRange : 0; + const qreal positionStep = stepSize * positionValueRatio; + + if (positionStep == 0) + return (min < max) ? qBound(min, position, max) : qBound(max, position, min); + + const int stepSizeMultiplier = (position - min) / positionStep; + + // Test whether value is below minimum range + if (stepSizeMultiplier < 0) + return min; + + qreal leftEdge = (stepSizeMultiplier * positionStep) + min; + qreal rightEdge = ((stepSizeMultiplier + 1) * positionStep) + min; + + if (min < max) { + leftEdge = qMin(leftEdge, max); + rightEdge = qMin(rightEdge, max); + } else { + leftEdge = qMax(leftEdge, max); + rightEdge = qMax(rightEdge, max); + } + + if (qAbs(leftEdge - position) <= qAbs(rightEdge - position)) + return leftEdge; + return rightEdge; +} + +/*! + Calculates the value that is going to be seen outside by the component + that is using QRangeModel. It takes into account the \l stepSize, + \l minimumValue, \l maximumValue properties + and \a value that is passed as parameter. +*/ + +qreal QRangeModelPrivate::publicValue(qreal value) const +{ + // It is important to do value-within-range check this + // late (as opposed to during setPosition()). The reason is + // QML bindings; a position that is initially invalid because it lays + // outside the range, might become valid later if the range changes. + + if (stepSize == 0) + return qBound(minimum, value, maximum); + + const int stepSizeMultiplier = (value - minimum) / stepSize; + + // Test whether value is below minimum range + if (stepSizeMultiplier < 0) + return minimum; + + const qreal leftEdge = qMin(maximum, (stepSizeMultiplier * stepSize) + minimum); + const qreal rightEdge = qMin(maximum, ((stepSizeMultiplier + 1) * stepSize) + minimum); + const qreal middle = (leftEdge + rightEdge) / 2; + + return (value <= middle) ? leftEdge : rightEdge; +} + +/*! + Checks if the \l value or \l position, that is seen by the user, has changed and emits the changed signal if it + has changed. +*/ + +void QRangeModelPrivate::emitValueAndPositionIfChanged(const qreal oldValue, const qreal oldPosition) +{ + Q_Q(QRangeModel); + + // Effective value and position might have changed even in cases when e.g. d->value is + // unchanged. This will be the case when operating with values outside range: + const qreal newValue = q->value(); + const qreal newPosition = q->position(); + if (!qFuzzyCompare(newValue, oldValue)) + emit q->valueChanged(newValue); + if (!qFuzzyCompare(newPosition, oldPosition)) + emit q->positionChanged(newPosition); +} + +/*! + Constructs a QRangeModel with \a parent +*/ + +QRangeModel::QRangeModel(QObject *parent) + : QObject(parent), d_ptr(new QRangeModelPrivate(this)) +{ + Q_D(QRangeModel); + d->init(); +} + +/*! + \internal + Constructs a QRangeModel with private class pointer \a dd and \a parent +*/ + +QRangeModel::QRangeModel(QRangeModelPrivate &dd, QObject *parent) + : QObject(parent), d_ptr(&dd) +{ + Q_D(QRangeModel); + d->init(); +} + +/*! + Destroys the QRangeModel +*/ + +QRangeModel::~QRangeModel() +{ + delete d_ptr; + d_ptr = 0; +} + +/*! + Sets the range of valid positions, that \l position can assume externally, with + \a min and \a max. + Such range is represented by \l positionAtMinimum and \l positionAtMaximum +*/ + +void QRangeModel::setPositionRange(qreal min, qreal max) +{ + Q_D(QRangeModel); + + bool emitPosAtMinChanged = !qFuzzyCompare(min, d->posatmin); + bool emitPosAtMaxChanged = !qFuzzyCompare(max, d->posatmax); + + if (!(emitPosAtMinChanged || emitPosAtMaxChanged)) + return; + + const qreal oldPosition = position(); + d->posatmin = min; + d->posatmax = max; + + // When a new positionRange is defined, the position property must be updated based on the value property. + // For instance, imagine that you have a valueRange of [0,100] and a position range of [20,100], + // if a user set the value to 50, the position would be 60. If this positionRange is updated to [0,100], then + // the new position, based on the value (50), will be 50. + // If the newPosition is different than the old one, it must be updated, in order to emit + // the positionChanged signal. + d->pos = d->equivalentPosition(d->value); + + if (emitPosAtMinChanged) + emit positionAtMinimumChanged(d->posatmin); + if (emitPosAtMaxChanged) + emit positionAtMaximumChanged(d->posatmax); + + d->emitValueAndPositionIfChanged(value(), oldPosition); +} +/*! + Sets the range of valid values, that \l value can assume externally, with + \a min and \a max. The range has the following constraint: \a min must be less or equal \a max + Such range is represented by \l minimumValue and \l maximumValue +*/ + +void QRangeModel::setRange(qreal min, qreal max) +{ + Q_D(QRangeModel); + + bool emitMinimumChanged = !qFuzzyCompare(min, d->minimum); + bool emitMaximumChanged = !qFuzzyCompare(max, d->maximum); + + if (!(emitMinimumChanged || emitMaximumChanged)) + return; + + const qreal oldValue = value(); + const qreal oldPosition = position(); + + d->minimum = min; + d->maximum = qMax(min, max); + + // Update internal position if it was changed. It can occurs if internal value changes, due to range update + d->pos = d->equivalentPosition(d->value); + + if (emitMinimumChanged) + emit minimumChanged(d->minimum); + if (emitMaximumChanged) + emit maximumChanged(d->maximum); + + d->emitValueAndPositionIfChanged(oldValue, oldPosition); +} + +/*! + \property QRangeModel::minimumValue + \brief the minimum value that \l value can assume + + This property's default value is 0 +*/ + +void QRangeModel::setMinimum(qreal min) +{ + Q_D(const QRangeModel); + setRange(min, d->maximum); +} + +qreal QRangeModel::minimum() const +{ + Q_D(const QRangeModel); + return d->minimum; +} + +/*! + \property QRangeModel::maximumValue + \brief the maximum value that \l value can assume + + This property's default value is 99 +*/ + +void QRangeModel::setMaximum(qreal max) +{ + Q_D(const QRangeModel); + // if the new maximum value is smaller than + // minimum, update minimum too + setRange(qMin(d->minimum, max), max); +} + +qreal QRangeModel::maximum() const +{ + Q_D(const QRangeModel); + return d->maximum; +} + +/*! + \property QRangeModel::stepSize + \brief the value that is added to the \l value and \l position property + + Example: If a user sets a range of [0,100] and stepSize + to 30, the valid values that are going to be seen externally would be: 0, 30, 60, 90, 100. +*/ + +void QRangeModel::setStepSize(qreal stepSize) +{ + Q_D(QRangeModel); + + stepSize = qMax(qreal(0.0), stepSize); + if (qFuzzyCompare(stepSize, d->stepSize)) + return; + + const qreal oldValue = value(); + const qreal oldPosition = position(); + d->stepSize = stepSize; + + emit stepSizeChanged(d->stepSize); + d->emitValueAndPositionIfChanged(oldValue, oldPosition); +} + +qreal QRangeModel::stepSize() const +{ + Q_D(const QRangeModel); + return d->stepSize; +} + +/*! + Returns a valid position, respecting the \l positionAtMinimum, + \l positionAtMaximum and the \l stepSize properties. + Such calculation is based on the parameter \a value (which is valid externally). +*/ + +qreal QRangeModel::positionForValue(qreal value) const +{ + Q_D(const QRangeModel); + + const qreal unconstrainedPosition = d->equivalentPosition(value); + return d->publicPosition(unconstrainedPosition); +} + +/*! + \property QRangeModel::position + \brief the current position of the model + + Represents a valid external position, based on the \l positionAtMinimum, + \l positionAtMaximum and the \l stepSize properties. + The user can set it internally with a position, that is not within the current position range, + since it can become valid if the user changes the position range later. +*/ + +qreal QRangeModel::position() const +{ + Q_D(const QRangeModel); + + // Return the internal position but observe boundaries and + // stepSize restrictions. + return d->publicPosition(d->pos); +} + +void QRangeModel::setPosition(qreal newPosition) +{ + Q_D(QRangeModel); + + if (qFuzzyCompare(newPosition, d->pos)) + return; + + const qreal oldPosition = position(); + const qreal oldValue = value(); + + // Update position and calculate new value + d->pos = newPosition; + d->value = d->equivalentValue(d->pos); + d->emitValueAndPositionIfChanged(oldValue, oldPosition); +} + +/*! + \property QRangeModel::positionAtMinimum + \brief the minimum value that \l position can assume + + This property's default value is 0 +*/ + +void QRangeModel::setPositionAtMinimum(qreal min) +{ + Q_D(QRangeModel); + setPositionRange(min, d->posatmax); +} + +qreal QRangeModel::positionAtMinimum() const +{ + Q_D(const QRangeModel); + return d->posatmin; +} + +/*! + \property QRangeModel::positionAtMaximum + \brief the maximum value that \l position can assume + + This property's default value is 0 +*/ + +void QRangeModel::setPositionAtMaximum(qreal max) +{ + Q_D(QRangeModel); + setPositionRange(d->posatmin, max); +} + +qreal QRangeModel::positionAtMaximum() const +{ + Q_D(const QRangeModel); + return d->posatmax; +} + +/*! + Returns a valid value, respecting the \l minimumValue, + \l maximumValue and the \l stepSize properties. + Such calculation is based on the parameter \a position (which is valid externally). +*/ + +qreal QRangeModel::valueForPosition(qreal position) const +{ + Q_D(const QRangeModel); + + const qreal unconstrainedValue = d->equivalentValue(position); + return d->publicValue(unconstrainedValue); +} + +/*! + \property QRangeModel::value + \brief the current value of the model + + Represents a valid external value, based on the \l minimumValue, + \l maximumValue and the \l stepSize properties. + The user can set it internally with a value, that is not within the current range, + since it can become valid if the user changes the range later. +*/ + +qreal QRangeModel::value() const +{ + Q_D(const QRangeModel); + + // Return internal value but observe boundaries and + // stepSize restrictions + return d->publicValue(d->value); +} + +void QRangeModel::setValue(qreal newValue) +{ + Q_D(QRangeModel); + + if (qFuzzyCompare(newValue, d->value)) + return; + + const qreal oldValue = value(); + const qreal oldPosition = position(); + + // Update relative value and position + d->value = newValue; + d->pos = d->equivalentPosition(d->value); + d->emitValueAndPositionIfChanged(oldValue, oldPosition); +} + +/*! + \property QRangeModel::inverted + \brief the model is inverted or not + + The model can be represented with an inverted behavior, e.g. when \l value assumes + the maximum value (represented by \l maximumValue) the \l position will be at its + minimum (represented by \l positionAtMinimum). +*/ + +void QRangeModel::setInverted(bool inverted) +{ + Q_D(QRangeModel); + if (inverted == d->inverted) + return; + + d->inverted = inverted; + emit invertedChanged(d->inverted); + + // After updating the internal value, the position property can change. + setPosition(d->equivalentPosition(d->value)); +} + +bool QRangeModel::inverted() const +{ + Q_D(const QRangeModel); + return d->inverted; +} + +/*! + Sets the \l value to \l minimumValue. +*/ + +void QRangeModel::toMinimum() +{ + Q_D(const QRangeModel); + setValue(d->minimum); +} + +/*! + Sets the \l value to \l maximumValue. +*/ + +void QRangeModel::toMaximum() +{ + Q_D(const QRangeModel); + setValue(d->maximum); +} + +} // Plasma namespace + +#include "qrangemodel.moc" diff --git a/declarativeimports/plasmacomponents/qrangemodel.h b/declarativeimports/plasmacomponents/qrangemodel.h new file mode 100644 index 000000000..bdc8122e7 --- /dev/null +++ b/declarativeimports/plasmacomponents/qrangemodel.h @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project on Qt Labs. +** +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions contained +** in the Technology Preview License Agreement accompanying this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#ifndef QRANGEMODEL_H +#define QRANGEMODEL_H + +#include + +namespace Plasma +{ + +class QRangeModelPrivate; + +class QRangeModel : public QObject +{ + Q_OBJECT + + Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged USER true) + Q_PROPERTY(qreal minimumValue READ minimum WRITE setMinimum NOTIFY minimumChanged) + Q_PROPERTY(qreal maximumValue READ maximum WRITE setMaximum NOTIFY maximumChanged) + Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged) + Q_PROPERTY(qreal position READ position WRITE setPosition NOTIFY positionChanged) + Q_PROPERTY(qreal positionAtMinimum READ positionAtMinimum WRITE setPositionAtMinimum NOTIFY positionAtMinimumChanged) + Q_PROPERTY(qreal positionAtMaximum READ positionAtMaximum WRITE setPositionAtMaximum NOTIFY positionAtMaximumChanged) + Q_PROPERTY(bool inverted READ inverted WRITE setInverted NOTIFY invertedChanged) + +public: + QRangeModel(QObject *parent = 0); + virtual ~QRangeModel(); + + void setRange(qreal min, qreal max); + void setPositionRange(qreal min, qreal max); + + void setStepSize(qreal stepSize); + qreal stepSize() const; + + void setMinimum(qreal min); + qreal minimum() const; + + void setMaximum(qreal max); + qreal maximum() const; + + void setPositionAtMinimum(qreal posAtMin); + qreal positionAtMinimum() const; + + void setPositionAtMaximum(qreal posAtMax); + qreal positionAtMaximum() const; + + void setInverted(bool inverted); + bool inverted() const; + + qreal value() const; + qreal position() const; + + Q_INVOKABLE qreal valueForPosition(qreal position) const; + Q_INVOKABLE qreal positionForValue(qreal value) const; + +public Q_SLOTS: + void toMinimum(); + void toMaximum(); + void setValue(qreal value); + void setPosition(qreal position); + +Q_SIGNALS: + void valueChanged(qreal value); + void positionChanged(qreal position); + + void stepSizeChanged(qreal stepSize); + + void invertedChanged(bool inverted); + + void minimumChanged(qreal min); + void maximumChanged(qreal max); + void positionAtMinimumChanged(qreal min); + void positionAtMaximumChanged(qreal max); + +protected: + QRangeModel(QRangeModelPrivate &dd, QObject *parent); + QRangeModelPrivate* d_ptr; + +private: + Q_DISABLE_COPY(QRangeModel) + Q_DECLARE_PRIVATE(QRangeModel) + +}; + +} // Plasma namespace + +#endif // QRANGEMODEL_H diff --git a/declarativeimports/plasmacomponents/qrangemodel_p.h b/declarativeimports/plasmacomponents/qrangemodel_p.h new file mode 100644 index 000000000..5eb628671 --- /dev/null +++ b/declarativeimports/plasmacomponents/qrangemodel_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Components project on Qt Labs. +** +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions contained +** in the Technology Preview License Agreement accompanying this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +****************************************************************************/ + +#ifndef QRANGEMODEL_P_H +#define QRANGEMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt Components API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qrangemodel.h" + +namespace Plasma +{ + +class QRangeModelPrivate +{ + Q_DECLARE_PUBLIC(QRangeModel) +public: + QRangeModelPrivate(QRangeModel *qq); + virtual ~QRangeModelPrivate(); + + void init(); + + qreal posatmin, posatmax; + qreal minimum, maximum, stepSize, pos, value; + + uint inverted : 1; + + QRangeModel *q_ptr; + + inline qreal effectivePosAtMin() const { + return inverted ? posatmax : posatmin; + } + + inline qreal effectivePosAtMax() const { + return inverted ? posatmin : posatmax; + } + + inline qreal equivalentPosition(qreal value) const { + // Return absolute position from absolute value + const qreal valueRange = maximum - minimum; + if (valueRange == 0) + return effectivePosAtMin(); + + const qreal scale = (effectivePosAtMax() - effectivePosAtMin()) / valueRange; + return (value - minimum) * scale + effectivePosAtMin(); + } + + inline qreal equivalentValue(qreal pos) const { + // Return absolute value from absolute position + const qreal posRange = effectivePosAtMax() - effectivePosAtMin(); + if (posRange == 0) + return minimum; + + const qreal scale = (maximum - minimum) / posRange; + return (pos - effectivePosAtMin()) * scale + minimum; + } + + qreal publicPosition(qreal position) const; + qreal publicValue(qreal value) const; + void emitValueAndPositionIfChanged(const qreal oldValue, const qreal oldPosition); +}; + +} // Plasma namespace + +#endif // QRANGEMODEL_P_H diff --git a/declarativeimports/qtextracomponents/qiconitem.cpp b/declarativeimports/qtextracomponents/qiconitem.cpp index e54c49b33..d72381e47 100644 --- a/declarativeimports/qtextracomponents/qiconitem.cpp +++ b/declarativeimports/qtextracomponents/qiconitem.cpp @@ -73,7 +73,7 @@ void QIconItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, painter->setRenderHint(QPainter::Antialiasing, m_smooth); painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth); - m_icon.paint(painter, boundingRect().toRect()); + m_icon.paint(painter, boundingRect().toRect(), Qt::AlignCenter, isEnabled()?QIcon::Normal:QIcon::Disabled); painter->setRenderHint(QPainter::Antialiasing, wasAntiAlias); painter->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothTransform); } diff --git a/declarativeimports/test/gallery/Busy.qml b/declarativeimports/test/gallery/Busy.qml new file mode 100644 index 000000000..8e77db1ec --- /dev/null +++ b/declarativeimports/test/gallery/Busy.qml @@ -0,0 +1,78 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Busy Indicator" + } + + PlasmaComponents.BusyIndicator { } + + PlasmaComponents.BusyIndicator { running: true } + + Text { + font.pixelSize: 20 + text: "Progress Bar" + } + + Text { text: "Horizontal" } + + PlasmaComponents.ProgressBar { + value: 0.3 + } + + PlasmaComponents.ProgressBar { + indeterminate: true + } + + PlasmaComponents.ProgressBar { + minimumValue: 0 + maximumValue: 100 + value: 30 + } + + Text { text: "Vertical" } + Row { + spacing: 20 + PlasmaComponents.ProgressBar { + value: 0.3 + orientation: Qt.Vertical + width: 20 + height: 100 + } + PlasmaComponents.ProgressBar { + value: 0.4 + orientation: Qt.Vertical + width: 20 + height: 120 + } + PlasmaComponents.ProgressBar { + orientation: Qt.Vertical + width: 20 + height: 100 + indeterminate: true + } + } +} diff --git a/declarativeimports/test/gallery/Buttons.qml b/declarativeimports/test/gallery/Buttons.qml new file mode 100644 index 000000000..b1d9ecf7b --- /dev/null +++ b/declarativeimports/test/gallery/Buttons.qml @@ -0,0 +1,99 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Buttons" + } + + PlasmaComponents.Button { + id: bt1 + width: 140 + height: 30 + text: "Button" + + onClicked: { + console.log("Clicked"); + } + + Keys.onTabPressed: bt2.forceActiveFocus(); + } + + PlasmaComponents.Button { + id: bt2 + width: 140 + height: 30 + text: "Checkable Button" + checkable: true + + onCheckedChanged: { + if (checked) + console.log("Button Checked"); + else + console.log("Button Unchecked"); + } + + Keys.onTabPressed: bt3.forceActiveFocus(); + } + + PlasmaComponents.Button { + id: bt3 + width: 140 + height: 30 + text: "Different Font" + font { + pixelSize: 20 + family: "Helvetica" + } + + Keys.onTabPressed: bt4.forceActiveFocus(); + } + + PlasmaComponents.Button { + id: bt4 + width: 140 + height: 30 + text: "Icon Button" + iconSource: "/home/dakerfp/work/comics-reader/ui/images/random.png" + + Keys.onTabPressed: bt5.forceActiveFocus(); + } + + PlasmaComponents.Button { + id: bt5 + width: 140 + height: 30 + iconSource: "/home/dakerfp/work/comics-reader/ui/images/random.png" + + Keys.onTabPressed: bt1.forceActiveFocus(); + } + + PlasmaComponents.Button { + width: 140 + height: 30 + text: "Disabled Button" + enabled: false + } +} diff --git a/declarativeimports/test/gallery/CheckableButtons.qml b/declarativeimports/test/gallery/CheckableButtons.qml new file mode 100644 index 000000000..fee6032b4 --- /dev/null +++ b/declarativeimports/test/gallery/CheckableButtons.qml @@ -0,0 +1,107 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Check Box" + } + + PlasmaComponents.CheckBox { + width: 140 + height: 30 + text: "Check Box 1" + + onCheckedChanged: { + if (checked) + console.log("CheckBox checked"); + else + console.log("CheckBox unchecked"); + } + onClicked: { + console.log("CheckBox clicked"); + } + } + + PlasmaComponents.CheckBox { + height: 30 + text: "Disabled" + enabled: false + } + + PlasmaComponents.CheckBox { + height: 30 + text: "" + } + + PlasmaComponents.CheckBox { + height: 30 + text: "A loooooooooooooong text" + } + + Text { + font.pixelSize: 20 + text: "Radio Button" + } + + PlasmaComponents.RadioButton { + width: 140 + height: 30 + text: "RadioButton" + + onCheckedChanged: { + if (checked) + console.log("RadioButton Checked"); + else + console.log("RadioButton Unchecked"); + } + } + + PlasmaComponents.Switch { } + + Text { + font.pixelSize: 20 + text: "Button Row" + } + + PlasmaComponents.ButtonRow { + spacing: 20 + PlasmaComponents.RadioButton { text: "A" } + PlasmaComponents.RadioButton { text: "B" } + PlasmaComponents.RadioButton { text: "C" } + } + + Text { + font.pixelSize: 20 + text: "Button Column" + } + + PlasmaComponents.ButtonColumn { + spacing: 20 + PlasmaComponents.RadioButton { text: "Alice" } + PlasmaComponents.RadioButton { text: "Bob" } + PlasmaComponents.RadioButton { text: "Charles" } + } + +} diff --git a/declarativeimports/test/gallery/Gallery.qml b/declarativeimports/test/gallery/Gallery.qml new file mode 100644 index 000000000..bae3ada49 --- /dev/null +++ b/declarativeimports/test/gallery/Gallery.qml @@ -0,0 +1,127 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Rectangle { + width: 1000 + height: 800 + color: "lightgrey" + + PlasmaComponents.ToolBar { + id: toolBar + z: 10 + anchors { + top: parent.top + left: parent.left + right: parent.right + } + tools: toolbarA + } + Row { + id: toolbarA + visible: false + spacing: 5 + PlasmaComponents.ToolButton { + text: "Switch toolbar" + onClicked: toolBar.setTools(toolbarB, "push") + } + PlasmaComponents.ToolButton { + text: "button on first toolbar" + } + } + Row { + id: toolbarB + visible: false + spacing: 5 + PlasmaComponents.ToolButton { + text: "Switch toolbar" + onClicked: toolBar.setTools(toolbarA, "pop") + } + PlasmaComponents.ToolButton { + flat: false + text: "button on second toolbar" + } + PlasmaComponents.TextField {} + } + Flickable { + id: page + + anchors { + top: toolBar.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } + contentWidth: 2200 + contentHeight: 1000 + + Row { + x: 30 + anchors { + top: parent.top + bottom: parent.bottom + margins: 20 + } + spacing: 30 + + Buttons{ } + + CheckableButtons { } + + Busy { } + + Sliders { } + + Scrollers { } + + Texts { } + } + } + + PlasmaComponents.ScrollBar { + id: horizontalScrollBar + + stepSize: 30 + + flickableItem: page + animated: true + anchors { + left: parent.left + right: verticalScrollBar.left + bottom: parent.bottom + } + } + + PlasmaComponents.ScrollBar { + id: verticalScrollBar + + stepSize: 30 + + orientation: Qt.Vertical + flickableItem: page + animated: true + anchors { + top: toolBar.bottom + right: parent.right + bottom: horizontalScrollBar.top + } + } +} diff --git a/declarativeimports/test/gallery/Scrollers.qml b/declarativeimports/test/gallery/Scrollers.qml new file mode 100644 index 000000000..dea2d8c81 --- /dev/null +++ b/declarativeimports/test/gallery/Scrollers.qml @@ -0,0 +1,131 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Scroll Bar" + } + + ListView { + id: scrollList + + width: 200 + height: 200 + clip: true + model: 20 + delegate: Text { + width: 200 + height: 30 + text: index + font.pixelSize: 18 + } + + Rectangle { + anchors.fill: parent + color: "grey" + opacity: 0.3 + } + + PlasmaComponents.ScrollBar { + id: scrollBar + orientation: Qt.Vertical + flickableItem: scrollList + animated: true + stepSize: 40 + scrollButtonInterval: 50 + anchors { + top: scrollList.top + right: scrollList.right + bottom: scrollList.bottom + } + } + } + + Text { + font.pixelSize: 20 + text: "Scroll Decorator" + } + + Item { + width: 200 + height: 200 + PlasmaComponents.Highlight { anchors.fill: parent } + Flickable { + id: scrollArea + anchors.fill: parent + clip: true + contentWidth: 400 + contentHeight: 400 + + // Flickable Contents + Rectangle { + color: "green" + width: 100 + height: 100 + } + Rectangle { + x: 80 + y: 80 + color: "blue" + width: 200 + height: 200 + } + Rectangle { + x: 200 + y: 200 + color: "red" + width: 150 + height: 150 + } + } + + // Scroll Decorators + PlasmaComponents.ScrollDecorator { + orientation: Qt.Vertical + flickableItem: scrollArea + inverted: true + anchors { + top: scrollArea.top + right: scrollArea.right + bottom: scrollArea.bottom + } + Text { + y: parent.height / 2 + x: 13 + rotation: -90 + text: "inverted" + } + } + PlasmaComponents.ScrollDecorator { + orientation: Qt.Horizontal + flickableItem: scrollArea + anchors { + left: scrollArea.left + right: scrollArea.right + bottom: scrollArea.bottom + } + } + } +} diff --git a/declarativeimports/test/gallery/Sliders.qml b/declarativeimports/test/gallery/Sliders.qml new file mode 100644 index 000000000..f90cecf75 --- /dev/null +++ b/declarativeimports/test/gallery/Sliders.qml @@ -0,0 +1,132 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.0 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 20 + + Text { + font.pixelSize: 20 + text: "Slider" + } + + PlasmaComponents.Highlight { + width: 300 + height: 400 + Column { + anchors { + fill: parent + } + spacing: 10 + + Text { text: "Color Selector"; font.pixelSize: 20 } + + Text { text: "Red" } + + PlasmaComponents.Slider { + id: redSlider + height: 20 + width: 255 + orientation: Qt.Horizontal + minimumValue: 0 + maximumValue: 255 + stepSize: 10 + animated: true + Keys.onTabPressed: greenSlider.forceActiveFocus() + } + + Text { text: "Green" } + + PlasmaComponents.Slider { + id: greenSlider + height: 20 + width: 255 + orientation: Qt.Horizontal + minimumValue: 0 + maximumValue: 255 + stepSize: 10 + animated: true + Keys.onTabPressed: blueSlider.forceActiveFocus() + } + + Text { text: "Blue" } + + PlasmaComponents.Slider { + id: blueSlider + height: 20 + width: 255 + orientation: Qt.Horizontal + minimumValue: 0 + maximumValue: 255 + stepSize: 10 + animated: true + Keys.onTabPressed: redSlider.forceActiveFocus() + } + + Rectangle { + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width / 2 + height: width + color: Qt.rgba(redSlider.value / 255, greenSlider.value / 255, blueSlider.value / 255, 1) + } + } + } + + Text { text: "Disabled Horizontal Slider" } + + PlasmaComponents.Slider { + id: horizontalSlider + width: 140 + height: 20 + animated: true + enabled: false + } + + Text { text: "Inverted Horizontal Slider" } + + PlasmaComponents.Slider { + id: invHorizontalSlider + width: 140 + height: 20 + inverted: true + animated: true + enabled: true + } + + Text { text: "Vertical Slider" } + + Row { + spacing: 30 + PlasmaComponents.Slider { + id: verticalSlider + width: 20 + height: 140 + orientation: Qt.Vertical + minimumValue: 10 + maximumValue: 1000 + stepSize: 50 + inverted: true + animated: true + } + Text { text: verticalSlider.value } + } + +} diff --git a/declarativeimports/test/gallery/Texts.qml b/declarativeimports/test/gallery/Texts.qml new file mode 100644 index 000000000..ae3d0df48 --- /dev/null +++ b/declarativeimports/test/gallery/Texts.qml @@ -0,0 +1,99 @@ +/* +* Copyright (C) 2011 by Daker Fernandes Pinheiro +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Library General Public License as +* published by the Free Software Foundation; either version 2, 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 Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import QtQuick 1.1 +import org.kde.plasma.components 0.1 as PlasmaComponents + +Column { + spacing: 30 + Text { + text: "Text Fields" + font.pixelSize: 20 + } + + PlasmaComponents.Highlight { + width: 200 + height: 100 + Column { + spacing: 10 + Row { + Text { + text: "Username: " + anchors.verticalCenter: tf1.verticalCenter + } + PlasmaComponents.TextField { + id: tf1 + placeholderText: "login" + Keys.onTabPressed: tf2.forceActiveFocus(); + } + } + + Row { + Text { + text: "Password: " + anchors.verticalCenter: tf2.verticalCenter + } + PlasmaComponents.TextField { + id: tf2 + width: 120 + echoMode: TextInput.Password + Keys.onTabPressed: loginButton.forceActiveFocus(); + } + } + + PlasmaComponents.Button { + id: loginButton + text: "Login" + anchors { + right: parent.right + rightMargin: 0 + } + width: 100 + } + } + } + + PlasmaComponents.TextField { + width: 120 + placeholderText: "Disabled Text Field" + Keys.onTabPressed: loginButton.forceActiveFocus(); + enabled: false + } + + Text { + text: "Text Area" + font.pixelSize: 20 + } + + PlasmaComponents.TextArea { + width: 200 + height: 200 + placeholderText: "Lorem ipsum et dolor" + wrapMode: TextEdit.WordWrap + contentMaxWidth: 400 + contentMaxHeight: 400 + } + + PlasmaComponents.TextArea { + width: 200 + height: 100 + enabled: false + text: "Disabled Text Area" + } +} diff --git a/kpart/plasma-kpart.desktop b/kpart/plasma-kpart.desktop index b298ca710..578547fa2 100644 --- a/kpart/plasma-kpart.desktop +++ b/kpart/plasma-kpart.desktop @@ -38,6 +38,7 @@ Name[pt]=plasma-kpart Name[pt_BR]=plasma-kpart Name[ro]=plasma-kpart Name[ru]=plasma-kpart +Name[si]=plasma-kpart Name[sk]=plasma-kpart Name[sl]=plasma-kpart Name[sr]=plasma-kpart @@ -45,6 +46,7 @@ Name[sr@ijekavian]=plasma-kpart Name[sr@ijekavianlatin]=plasma-kpart Name[sr@latin]=plasma-kpart Name[sv]=Plasma-delprogram +Name[tg]=plasma-kpart Name[th]=plasma-kpart Name[tr]=plasma-kpart Name[ug]=plasma-kpart diff --git a/kpart/plasmakpart.cpp b/kpart/plasmakpart.cpp index 9af169f55..9259a20b7 100644 --- a/kpart/plasmakpart.cpp +++ b/kpart/plasmakpart.cpp @@ -22,8 +22,15 @@ #include "plasmakpart.h" -#include "plasmakpartcorona.h" -#include "plasmakpartview.h" +#include +#include +#include +#include +#include +#include + +#include +#include #include #include @@ -31,13 +38,8 @@ #include #include -#include -#include - -#include -#include -#include -#include +#include "plasmakpartcorona.h" +#include "plasmakpartview.h" K_PLUGIN_FACTORY(plasmaKPartFactory, registerPlugin();) K_EXPORT_PLUGIN(plasmaKPartFactory("plasma-kpart","plasma-kpart") ) @@ -45,8 +47,7 @@ K_EXPORT_PLUGIN(plasmaKPartFactory("plasma-kpart","plasma-kpart") ) PlasmaKPart::PlasmaKPart(QWidget *parentWidget, QObject *parent, const QVariantList &args) : KParts::ReadOnlyPart(parent), m_corona(0), - m_view(new PlasmaKPartView(0, 1, parentWidget)), - m_service(0) + m_view(new PlasmaKPartView(0, 1)) { setComponentData(plasmaKPartFactory::componentData()); @@ -66,11 +67,24 @@ PlasmaKPart::PlasmaKPart(QWidget *parentWidget, QObject *parent, const QVariantL } } - initCorona(); + setAutoDeletePart(false); + QTimer::singleShot(0, this, SLOT(initCorona())); } PlasmaKPart::~PlasmaKPart() { + delete m_view; + m_view = 0; + + if (!m_configFile.isEmpty()) { + m_corona->saveLayout(); + } + + delete m_corona; + m_corona = 0; + + //TODO: This manual sync() should not be necessary? + syncConfig(); } void PlasmaKPart::setThemeDefaults() @@ -85,32 +99,6 @@ void PlasmaKPart::setThemeDefaults() Plasma::Theme::defaultTheme()->setFont(cg.readEntry("desktopFont", QFont("Sans") )); } -void PlasmaKPart::cleanup() -{ - if (m_corona) { - m_corona->saveLayout(); - } - - if (!m_view->containment()) { - return; - } - - // save the mapping of Views to Containments at the moment - // of application exit so we can restore that when we start again. - KConfigGroup viewIds(KGlobal::config(), "ViewIds"); - viewIds.deleteGroup(); - viewIds.writeEntry(QString::number(m_view->containment()->id()), 1); - - delete m_view; - m_view = 0; - - delete m_corona; - m_corona = 0; - - //TODO: This manual sync() should not be necessary? - syncConfig(); -} - void PlasmaKPart::syncConfig() { KGlobal::config()->sync(); @@ -127,7 +115,7 @@ void PlasmaKPart::initCorona() connect(m_corona, SIGNAL(configSynced()), this, SLOT(syncConfig())); m_corona->setItemIndexMethod(QGraphicsScene::NoIndex); - m_corona->initializeLayout(); + m_corona->initializeLayout(m_configFile); m_view->show(); } @@ -139,13 +127,7 @@ PlasmaKPartCorona* PlasmaKPart::corona() const void PlasmaKPart::createView(Plasma::Containment *containment) { - KConfigGroup viewIds(KGlobal::config(), "ViewIds"); - int id = viewIds.readEntry(QString::number(containment->id()), 1); - - kDebug() << "new containment" << (QObject*)containment << containment->id()<<"view id"<setContainment(containment); - emit viewCreated(); } void PlasmaKPart::addApplet(const QString& name, const QVariantList& args, const QRectF& geometry ) @@ -158,6 +140,19 @@ Plasma::Applet::List PlasmaKPart::listActiveApplets() const return containment()->applets(); } +QString PlasmaKPart::configFile() const +{ + return m_configFile; +} + +void PlasmaKPart::setConfigFile(const QString &file) +{ + m_configFile = file; + if (m_corona && QFile::exists(m_configFile)) { + m_corona->initializeLayout(m_configFile); + } +} + Plasma::Containment* PlasmaKPart::containment() const { return corona()->containments().first(); diff --git a/kpart/plasmakpart.h b/kpart/plasmakpart.h index fa8f3546c..92de38524 100644 --- a/kpart/plasmakpart.h +++ b/kpart/plasmakpart.h @@ -35,7 +35,6 @@ namespace Plasma } #include -#include #include class QVariant; @@ -45,6 +44,7 @@ class PlasmaKPart : public KParts::ReadOnlyPart { Q_OBJECT Q_PROPERTY(Plasma::Applet::List activeApplets READ listActiveApplets) + Q_PROPERTY(QString configFile READ configFile WRITE setConfigFile) public: /** @@ -69,6 +69,9 @@ public: **/ Plasma::Applet::List listActiveApplets() const; + QString configFile() const; + void setConfigFile(const QString &file); + public Q_SLOTS: /** * Add an applet to the currently running containment. @@ -79,14 +82,8 @@ public Q_SLOTS: **/ void addApplet(const QString &pluginName, const QVariantList &args = QVariantList(), const QRectF &dimensions = QRectF()); -Q_SIGNALS: - void viewCreated(); - -private: - void initCorona(); - private Q_SLOTS: - void cleanup(); + void initCorona(); void syncConfig(); void createView(Plasma::Containment* containment); void setThemeDefaults(); @@ -94,9 +91,9 @@ private Q_SLOTS: private: PlasmaKPartCorona* m_corona; PlasmaKPartView* m_view; - KService::Ptr m_service; QHash* m_appletList; QVBoxLayout* m_configLayout; + QString m_configFile; }; #endif // multiple inclusion guard diff --git a/kpart/plasmakpartcorona.cpp b/kpart/plasmakpartcorona.cpp index 99f84da54..6bcece1cd 100644 --- a/kpart/plasmakpartcorona.cpp +++ b/kpart/plasmakpartcorona.cpp @@ -33,11 +33,6 @@ PlasmaKPartCorona::PlasmaKPartCorona(QObject *parent) : Plasma::Corona(parent) -{ - init(); -} - -void PlasmaKPartCorona::init() { enableAction("Lock Widgets", false); enableAction("Shortcut Settings", false); @@ -47,7 +42,6 @@ void PlasmaKPartCorona::init() void PlasmaKPartCorona::loadDefaultLayout() { // used to force a save into the config file - KConfigGroup invalidConfig; Plasma::Containment *c = addContainment(QString()); if (!c) { @@ -85,15 +79,4 @@ void PlasmaKPartCorona::printScriptMessage(const QString &error) kDebug() << "Startup script: " << error; } -Plasma::Containment* PlasmaKPartCorona::containment() -{ - // We only have one containment, so just try and return the first one - QList list = containments(); - if (!list.isEmpty()) { - return list.first(); - } - - return 0; -} - #include "plasmakpartcorona.moc" diff --git a/kpart/plasmakpartcorona.h b/kpart/plasmakpartcorona.h index 3df552502..6137b8c8b 100644 --- a/kpart/plasmakpartcorona.h +++ b/kpart/plasmakpartcorona.h @@ -38,13 +38,9 @@ Q_OBJECT public: PlasmaKPartCorona(QObject* parent); - Plasma::Containment *containment(); - +protected: void loadDefaultLayout(); - -private: void evaluateScripts(const QStringList &scripts); - void init(); private Q_SLOTS: void printScriptError(const QString &error); diff --git a/remotewidgetshelper/kcm_remotewidgets.actions b/remotewidgetshelper/kcm_remotewidgets.actions index 3d110c183..e8ba43ee5 100644 --- a/remotewidgetshelper/kcm_remotewidgets.actions +++ b/remotewidgetshelper/kcm_remotewidgets.actions @@ -49,6 +49,7 @@ Name[sr@ijekavian]=Сачувај смјернице за удаљене виџ Name[sr@ijekavianlatin]=Sačuvaj smjernice za udaljene vidžete Name[sr@latin]=Sačuvaj smernice za udaljene vidžete Name[sv]=Spara policy för grafiska fjärrkomponenter +Name[tg]=Танзимоти видҷетҳои дурдастро сабт кунед Name[th]=บันทึกกฎของวิดเจ็ตระยะไกล Name[tr]=Uzak programcık politikalarını kaydet Name[ug]=يىراقتىكى ۋىجېتلارنى ساقلاش تەدبىرى @@ -104,6 +105,7 @@ Description[sr@ijekavian]=Спречава систем да сачува смј Description[sr@ijekavianlatin]=Sprečava sistem da sačuva smjernice udaljenih plasma vidžeta Description[sr@latin]=Sprečava sistem da sačuva smernice udaljenih plasma vidžeta Description[sv]=Förhindrar systemet från att spara policy för Plasma grafiska fjärrkomponenter +Description[tg]=Системаро аз сабткунии танзимоти видҷетҳои plasma-и дурдаст пешгирӣ мекунад Description[th]=ป้องกันระบบจากการบันทึกกฎของวิดเจ็ตของพลาสมาจากทางไกล Description[tr]=Sistemin uzak plasma programcık politikalarını kaydetmesini engelle Description[ug]=سىستېما يىراقتىكى پلازما ۋىجېتلىرىنىڭ تەدبىرىنى ساقلاشنى چەكلەيدۇ diff --git a/scriptengines/javascript/data/plasma-javascriptaddon.desktop b/scriptengines/javascript/data/plasma-javascriptaddon.desktop index 293c42af6..1743ab726 100644 --- a/scriptengines/javascript/data/plasma-javascriptaddon.desktop +++ b/scriptengines/javascript/data/plasma-javascriptaddon.desktop @@ -38,6 +38,7 @@ Name[pt]=Extensão de JavaScript do Plasma Name[pt_BR]=Complementos de JavaScript do Plasma Name[ro]=Supliment JavaScript Plasma Name[ru]=Расширение Plasma, использующее JavaScript +Name[si]=ප්ලාස්මා හා ජාවාස්ක්‍රිප්ට ඇඩොන Name[sk]=Doplnok JavaScript pre plasmu Name[sl]=Dodatek za JavaScript za Plasmo Name[sr]=Плазма јаваскриптни додатак @@ -45,7 +46,7 @@ Name[sr@ijekavian]=Плазма јаваскриптни додатак Name[sr@ijekavianlatin]=Plasma JavaScript dodatak Name[sr@latin]=Plasma JavaScript dodatak Name[sv]=Plasma Javaskript-tillägg -Name[tg]=Иловаҳои Plasma JavaScript +Name[tg]=Барномаи иловагии Plasma JavaScript Name[th]=ส่วนเสริมจาวาและจาวาสคริปต์สำหรับพลาสมาส่วนเสริมจาวาและจาวาสคริปต์สำหรับ Name[tr]=Plasma JavaScript Eklentisi Name[ug]=Plasma JavaScript قوشۇلما diff --git a/scriptengines/javascript/data/plasma-packagestructure-javascript-addon.desktop b/scriptengines/javascript/data/plasma-packagestructure-javascript-addon.desktop index 8d14d27a0..e96fc6552 100644 --- a/scriptengines/javascript/data/plasma-packagestructure-javascript-addon.desktop +++ b/scriptengines/javascript/data/plasma-packagestructure-javascript-addon.desktop @@ -38,6 +38,7 @@ Name[pt]=Extensão de JavaScript Name[pt_BR]=Complementos de JavaScript Name[ro]=Supliment Javascript Name[ru]=Дополнение, использующее JavaScript +Name[si]=ජාවාස්ක්‍රිප්ට ඇඩෝන Name[sk]=Doplnok JavaScript Name[sl]=Dodatek za JavaScript Name[sr]=Јаваскриптни додатак @@ -45,6 +46,7 @@ Name[sr@ijekavian]=Јаваскриптни додатак Name[sr@ijekavianlatin]=JavaScript dodatak Name[sr@latin]=JavaScript dodatak Name[sv]=Javaskript-tillägg +Name[tg]=Барномаи иловагии Javascript Name[th]=ส่วนเสริมจาวาสคริปต์ Name[tr]=Javascript Eklentisi Name[ug]=Javascript قوشۇلما @@ -90,6 +92,7 @@ Comment[pt]=Extras para os 'plugins' do Plasma em JavaScript Comment[pt_BR]=Complementos para os plug-ins do Plasma em JavaScript Comment[ro]=Suplimente pentru module JavaScript Plasma Comment[ru]=Модули поддержки дополнений Plasma, использующих JavaScript +Comment[si]=ජාවාස්ක්‍රිප්ට ප්ලාස්මා ප්ලගින සඳහා ඇඩෝන Comment[sk]=Doplnky pre Javascriptové moduly plasmy Comment[sl]=Dodatki za vstavke JavaScript za Plasmo Comment[sr]=Додаци за јаваскриптне плазма прикључке @@ -97,6 +100,7 @@ Comment[sr@ijekavian]=Додаци за јаваскриптне плазма п Comment[sr@ijekavianlatin]=Dodaci za JavaScript plasma priključke Comment[sr@latin]=Dodaci za JavaScript plasma priključke Comment[sv]=Tillägg för Javascript Plasma-insticksprogram +Comment[tg]=Барномаҳои иловагӣ барои плагинҳои Javascript Plasma Comment[th]=ส่วนขยายสำหรับส่วนเสริมพลาสมาที่เป็นจาวาสคริปต์ Comment[tr]=Javascript Plasma eklentileri için ek araçlar Comment[ug]=Javascript Plasma قىستۇرمىسى ئۈچۈن قوشۇلما diff --git a/scriptengines/javascript/data/plasma-scriptengine-applet-declarative.desktop b/scriptengines/javascript/data/plasma-scriptengine-applet-declarative.desktop index 6f9730a5f..4a565bd84 100644 --- a/scriptengines/javascript/data/plasma-scriptengine-applet-declarative.desktop +++ b/scriptengines/javascript/data/plasma-scriptengine-applet-declarative.desktop @@ -33,6 +33,7 @@ Name[pt]=Item declarativo Name[pt_BR]=Widget declarativo Name[ro]=Control declarativ Name[ru]=Декларативный виджет +Name[si]=ප්‍රකාශන විජෙට්ටටුව Name[sk]=Deklaratívny widget Name[sl]=Deklarativni gradnik Name[sr]=Декларативни виџет @@ -40,6 +41,7 @@ Name[sr@ijekavian]=Декларативни виџет Name[sr@ijekavianlatin]=Deklarativni vidžet Name[sr@latin]=Deklarativni vidžet Name[sv]=Deklarativ grafisk komponent +Name[tg]=Видҷети эълонкунӣ Name[tr]=Bildirim parçacığı Name[ug]=ئېنىقلىما ۋىجېت Name[uk]=Декларативний віджет @@ -85,6 +87,7 @@ Comment[pt]=Elemento nativo do Plasma feito em QML e JavaScript Comment[pt_BR]=Widget do Plasma nativo escrito em QML e JavaScript Comment[ro]=Miniaplicație Plasma nativă scrisă în QML și JavaScript Comment[ru]=Виджет Plasma, написанный на языках QML и JavaScript +Comment[si]=ජාවා ස්ක්‍රිප්ට හා QML මගින් ලියූ ප්ලාස්මා විජෙට්ටු Comment[sk]=Natívny plasma widget napísaný v QML a JavaScripte Comment[sl]=Pravi gradnik za Plasmo, ki je napisan v QML-u in JavaScriptu Comment[sr]=Самосвојни плазма виџет написан у КуМЛ‑у и јаваскрипту @@ -92,6 +95,7 @@ Comment[sr@ijekavian]=Самосвојни плазма виџет написа Comment[sr@ijekavianlatin]=Samosvojni plasma vidžet napisan u QML‑u i JavaScriptu Comment[sr@latin]=Samosvojni plasma vidžet napisan u QML‑u i JavaScriptu Comment[sv]=Inbyggd grafisk Plasma-komponent skriven i QML och Javascript +Comment[tg]=Ин модули Plasma дар QML ва JavaScript навишта шуд Comment[th]=วิดเจ็ตพลาสมาแบบดั้งเดิมที่เขียนด้วย QML และจาวาสคริปต์ Comment[tr]=JavaScript ve QML ile yazılmış gerçek Plasma gereci Comment[ug]=QML ۋە JavaScript بىلەن يېزىلغان ئەسلى Plasma ۋىجېتى diff --git a/scriptengines/javascript/data/plasma-scriptengine-applet-simple-javascript.desktop b/scriptengines/javascript/data/plasma-scriptengine-applet-simple-javascript.desktop index 422d20385..07dc02a8f 100644 --- a/scriptengines/javascript/data/plasma-scriptengine-applet-simple-javascript.desktop +++ b/scriptengines/javascript/data/plasma-scriptengine-applet-simple-javascript.desktop @@ -136,7 +136,7 @@ Comment[sr@latin]=Samosvojni plasma vidžet napisan u JavaScriptu Comment[sv]=Inbyggd grafisk Plasma-komponent skriven i Javascript Comment[ta]=Native Plasma widget written in JavaScript Comment[te]=జావాస్క్రిప్‍ట్‌లో వ్రాసిన నేటివ్ ప్లాజ్మా విడ్‍జ్‌ట్ -Comment[tg]=Модуль Plasma, написанный на языке JavaScript +Comment[tg]=Ин модули Plasma дар JavaScript навишта шуд Comment[th]=วิดเจ็ตพลาสมาที่ถูกเขียนด้วยจาวาสคริปต์ Comment[tr]=JavaScript ile yazılmış gerçek Plasma gereci Comment[ug]=JavaScript بىلەن يېزىلغان ئەسلى Plasma ۋىجېتى diff --git a/scriptengines/javascript/data/plasma-scriptengine-dataengine-javascript.desktop b/scriptengines/javascript/data/plasma-scriptengine-dataengine-javascript.desktop index 3b0c00e8a..088e0a121 100644 --- a/scriptengines/javascript/data/plasma-scriptengine-dataengine-javascript.desktop +++ b/scriptengines/javascript/data/plasma-scriptengine-dataengine-javascript.desktop @@ -55,7 +55,7 @@ Name[sr@ijekavian]=јаваскриптни датомотор Name[sr@ijekavianlatin]=JavaScript datomotor Name[sr@latin]=JavaScript datomotor Name[sv]=Javascript-datagränssnitt -Name[tg]=Иҷрогари JavaScript +Name[tg]=Маълумоти муҳаррики JavaScript Name[th]=กลไกข้อมูลของจาวาสคริปต์ Name[tr]=JavaScript Veri Motoru Name[ug]=JavaScript سانلىق مەلۇمات ماتورى diff --git a/scriptengines/javascript/data/plasma-scriptengine-runner-javascript.desktop b/scriptengines/javascript/data/plasma-scriptengine-runner-javascript.desktop index 5f47b3933..c0082b695 100644 --- a/scriptengines/javascript/data/plasma-scriptengine-runner-javascript.desktop +++ b/scriptengines/javascript/data/plasma-scriptengine-runner-javascript.desktop @@ -18,6 +18,7 @@ Name[eo]=Ĝavaskripta ruligilo Name[es]=Motor de javascript Name[et]=JavaScripti käivitaja Name[eu]=JavaScript abiarazlea +Name[fa]=اجراکننده جاوااسکریپت Name[fi]=JavaScript-suoritusohjelma Name[fr]=Lanceur JavaScript Name[fy]=JavaSkript rinner @@ -93,6 +94,7 @@ Comment[eo]=Ĝavaskripta ruligilo Comment[es]=Motor de javascript Comment[et]=JavaScripti käivitaja Comment[eu]=JavaScript abiarazlea +Comment[fa]=اجراکننده جاوااسکریپت Comment[fi]=JavaScript-suoritusohjelma Comment[fr]=Lanceur JavaScript Comment[fy]=JavaSkript rinner diff --git a/scriptengines/javascript/plasmoid/appletinterface.cpp b/scriptengines/javascript/plasmoid/appletinterface.cpp index f712d220d..df7996244 100644 --- a/scriptengines/javascript/plasmoid/appletinterface.cpp +++ b/scriptengines/javascript/plasmoid/appletinterface.cpp @@ -223,6 +223,9 @@ QList AppletInterface::contextualActions() const { QList actions; Plasma::Applet *a = applet(); + if (a->hasFailedToLaunch()) { + return actions; + } foreach (const QString &name, m_actions) { QAction *action = a->action(name); @@ -257,7 +260,7 @@ void AppletInterface::setAction(const QString &name, const QString &text, const a->addAction(name, action); Q_ASSERT(!m_actions.contains(name)); - m_actions.insert(name); + m_actions.append(name); if (!m_actionSignals) { m_actionSignals = new QSignalMapper(this); @@ -293,7 +296,7 @@ void AppletInterface::removeAction(const QString &name) delete action; } - m_actions.remove(name); + m_actions.removeAll(name); } QAction *AppletInterface::action(QString name) const @@ -467,6 +470,11 @@ ContainmentInterface::ContainmentInterface(AbstractJsAppletScript *parent) connect(containment()->context(), SIGNAL(activityChanged(Plasma::Context *)), this, SIGNAL(activityNameChanged())); connect(containment()->context(), SIGNAL(changed(Plasma::Context *)), this, SIGNAL(activityIdChanged())); + + if (containment()->corona()) { + connect(containment()->corona(), SIGNAL(availableScreenRegionChanged()), + this, SIGNAL(availableScreenRegionChanged())); + } } QScriptValue ContainmentInterface::applets() diff --git a/scriptengines/javascript/plasmoid/appletinterface.h b/scriptengines/javascript/plasmoid/appletinterface.h index 9f9181515..51278b04a 100644 --- a/scriptengines/javascript/plasmoid/appletinterface.h +++ b/scriptengines/javascript/plasmoid/appletinterface.h @@ -317,7 +317,7 @@ protected: AbstractJsAppletScript *m_appletScriptEngine; private: - QSet m_actions; + QStringList m_actions; QSignalMapper *m_actionSignals; QString m_currentConfig; QMap m_configs; @@ -422,6 +422,7 @@ Q_SIGNALS: void screenChanged(); void activityNameChanged(); void activityIdChanged(); + void availableScreenRegionChanged(); protected Q_SLOTS: void appletAddedForward(Plasma::Applet *applet, const QPointF &pos); diff --git a/scriptengines/javascript/plasmoid/declarativeappletscript.cpp b/scriptengines/javascript/plasmoid/declarativeappletscript.cpp index 6f5cc956d..249f5e3c0 100644 --- a/scriptengines/javascript/plasmoid/declarativeappletscript.cpp +++ b/scriptengines/javascript/plasmoid/declarativeappletscript.cpp @@ -66,6 +66,7 @@ QScriptValue constructKUrlClass(QScriptEngine *engine); void registerSimpleAppletMetaTypes(QScriptEngine *engine); DeclarativeAppletScript::DeclarativeAppletScript(QObject *parent, const QVariantList &args) : AbstractJsAppletScript(parent, args), + m_interface(0), m_engine(0), m_env(0), m_auth(this) @@ -118,7 +119,6 @@ bool DeclarativeAppletScript::init() lay->addItem(m_declarativeWidget); } - m_interface = 0; if (pa) { m_interface = new PopupAppletInterface(this); } else if (cont) { @@ -492,6 +492,10 @@ QScriptValue DeclarativeAppletScript::loadService(QScriptContext *context, QScri QList DeclarativeAppletScript::contextualActions() { + if (!m_interface) { + return QList(); + } + return m_interface->contextualActions(); } diff --git a/scriptengines/javascript/plasmoid/simplejavascriptapplet.cpp b/scriptengines/javascript/plasmoid/simplejavascriptapplet.cpp index dba71f2a4..f879ae94b 100644 --- a/scriptengines/javascript/plasmoid/simplejavascriptapplet.cpp +++ b/scriptengines/javascript/plasmoid/simplejavascriptapplet.cpp @@ -100,7 +100,8 @@ KSharedPtr SimpleJavaScriptApplet::s_widgetLoader; QHash SimpleJavaScriptApplet::s_animationDefs; SimpleJavaScriptApplet::SimpleJavaScriptApplet(QObject *parent, const QVariantList &args) - : AbstractJsAppletScript(parent) + : AbstractJsAppletScript(parent), + m_interface(0) { Q_UNUSED(args); // kDebug() << "Script applet launched, args" << applet()->startupArguments(); @@ -231,6 +232,10 @@ void SimpleJavaScriptApplet::paintInterface(QPainter *p, const QStyleOptionGraph QList SimpleJavaScriptApplet::contextualActions() { + if (!m_interface) { + return QList(); + } + return m_interface->contextualActions(); } diff --git a/scriptengines/javascript/simplebindings/dataengine.cpp b/scriptengines/javascript/simplebindings/dataengine.cpp index bc3f467d3..299e00c2f 100644 --- a/scriptengines/javascript/simplebindings/dataengine.cpp +++ b/scriptengines/javascript/simplebindings/dataengine.cpp @@ -66,5 +66,7 @@ void registerDataEngineMetaTypes(QScriptEngine *engine) qScriptRegisterMetaType(engine, qScriptValueFromService, serviceFromQScriptValue); qScriptRegisterMetaType(engine, qScriptValueFromDataEngine, dataEngineFromQScriptValue); qScriptRegisterMetaType(engine, qScriptValueFromServiceJob, serviceJobFromQScriptValue); + qRegisterMetaType("Service*"); + qRegisterMetaType("ServiceJob*"); }