Merge branch 'mart/customShell'

Conflicts:
	examples/CMakeLists.txt
	src/plasma/pluginloader.cpp
This commit is contained in:
Marco Martin 2016-03-08 15:38:31 +01:00
commit 12ea79b341
12 changed files with 314 additions and 189 deletions

View File

@ -10,3 +10,4 @@ add_subdirectory(wallpapers)
add_subdirectory(dataengines)
add_subdirectory(testcontainmentactionsplugin)
add_subdirectory(developerguide)
add_subdirectory(shell)

View File

@ -0,0 +1,27 @@
/*
* Copyright 2015 Marco Martin <mart@kde.org>
*
* 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 2.1
Item {
id: plasmoidContainer
width: 300
height: 300
property Item applet
}

View File

@ -20,6 +20,7 @@ import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.plasmoid 2.0
Item {
id: root
@ -28,188 +29,21 @@ Item {
property Item toolBox
Connections {
target: plasmoid
onAppletAdded: {
var container = appletContainerComponent.createObject(root)
container.visible = true
print("Applet added: " + applet)
applet.parent = container
container.applet = applet
applet.anchors.fill= applet.parent
function addApplet(applet, x, y) {
var component = Qt.createComponent("PlasmoidContainer.qml")
var plasmoidContainer = component.createObject(root, {"x": x, "y": y});
plasmoidContainer.parent = root;
plasmoidContainer.applet = applet
applet.parent = plasmoidContainer
applet.anchors.fill = plasmoidContainer
applet.visible = true
}
plasmoidContainer.visible = true
}
Component {
id: appletContainerComponent
Item {
id: frameParent
x: 50
y: 50
property int small: 90
property int large: 400
width: large + frame.margins.left + frame.margins.right
height: large + frame.margins.top + frame.margins.bottom
property alias applet: appletContainer.children
onAppletChanged: {
if (appletContainer.children.length == 0) {
killAnim.running = true
}
}
PlasmaCore.FrameSvgItem {
id: frame
anchors.fill: parent
property int tm: 0
property int lm: 0
imagePath: applet.length > 0 && applet[0].backgroundHints == 0 ? "" : "widgets/background"
onImagePathChanged: {
// Reposition applet so it fits into the frame
if (imagePath == "") {
frameParent.x = frameParent.x + lm;
frameParent.y = frameParent.y + tm;
} else {
// Cache values, so we can subtract them when the background is removed
frame.lm = frame.margins.left;
frame.tm = frame.margins.top;
frameParent.x = frameParent.x - frame.margins.left;
frameParent.y = frameParent.y - frame.margins.top;
}
}
MouseArea {
id: mouseArea
property real dx: 0
property real dy: 0
property real startX
property real startY
anchors.fill: parent
drag.target: frameParent
onClicked: {
var s = (frameParent.width == frameParent.large) ? frameParent.small : frameParent.large;
frameParent.height = s
frameParent.width = s
}
onPressed: {
speedSampleTimer.running = true
mouseArea.startX = mouse.x
mouseArea.startY = mouse.y
speedSampleTimer.lastFrameParentX = frameParent.x
speedSampleTimer.lastFrameParentY = frameParent.y
}
onPositionChanged: {
//mouseArea.dx = mouse.x - mouseArea.startX
//mouseArea.dy = mouse.y - mouseArea.startY
dxAnim.running = false
dyAnim.running = false
}
onReleased: {
speedSampleTimer.running = false
dxAnim.running = true
dyAnim.running = true
}
Timer {
id: speedSampleTimer
interval: 40
repeat: true
property real lastFrameParentX
property real lastFrameParentY
onTriggered: {
mouseArea.dx = frameParent.x - lastFrameParentX
mouseArea.dy = frameParent.y - lastFrameParentY
lastFrameParentX = frameParent.x
lastFrameParentY = frameParent.y
dxAnim.running = true
dyAnim.running = true
}
}
}
Item {
id: appletContainer
anchors {
fill: parent
leftMargin: frame.margins.left
rightMargin: parent.margins.right
topMargin: parent.margins.top
bottomMargin: parent.margins.bottom
}
}
PlasmaComponents.BusyIndicator {
id: busyIndicator
z: 1000
visible: applet.length > 0 && applet[0].busy
running: visible
anchors.centerIn: parent
}
SequentialAnimation {
id: killAnim
NumberAnimation {
target: frame
properties: "scale"
to: 0
duration: units.longDuration
}
ScriptAction { script: frame.destroy()}
}
}
ShaderEffect {
id: wobbleShader
anchors.fill: frame
property variant source: ShaderEffectSource {
hideSource: true
sourceItem: frame
}
property int fadeDuration: 150
property real time: 0
property real dx: mouseArea.dx
property real dy: mouseArea.dy
property real startX: mouseArea.startX/mouseArea.width
property real startY: mouseArea.startY/mouseArea.height
NumberAnimation on dx { id: dxAnim; to: 0; duration: units.longDuration; easing.type: Easing.OutElastic }
NumberAnimation on dy { id: dyAnim; to: 0; duration: units.longDuration; easing.type: Easing.OutElastic }
//! [fragment]
fragmentShader: {
"uniform lowp float qt_Opacity;" +
"uniform highp float dx;" +
"uniform highp float dy;" +
"uniform highp float startX;" +
"uniform highp float startY;" +
"uniform sampler2D source;" +
"varying highp vec2 qt_TexCoord0;" +
"void main() {" +
" highp vec2 tmp = 1.0 / (1.0 + abs(qt_TexCoord0 - vec2(startX, startY)));" +
" vec2 wave = qt_TexCoord0 - vec2(dx, dy) * 0.0025 * tmp.xx * tmp.yy;" +
" gl_FragColor = texture2D(source, wave);" +
"}"
}
//! [fragment]
}
}
}
PlasmaCore.IconItem {
width: 24
height: 24
source: "list-add"
MouseArea {
anchors.fill: parent
onClicked: {
print("Add widgets ...");
plasmoid.action("add widgets").trigger();
}
}
Containment.onAppletAdded: {
addApplet(applet, x, y);
}
Component.onCompleted: {

View File

@ -0,0 +1,21 @@
set(exampleplasmashell-app_SRCS
customcorona.cpp
main.cpp
)
add_executable(exampleplasmashell ${exampleplasmashell-app_SRCS})
target_link_libraries(
exampleplasmashell
Qt5::Widgets
Qt5::Quick
Qt5::Qml
KF5::I18n
KF5::XmlGui
KF5::PlasmaQuick
KF5::Plasma
KF5::DBusAddons
KF5::Notifications
KF5::QuickAddons
)

View File

@ -0,0 +1,91 @@
/*
* Copyright 2015 Marco Martin <notmart@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software desktopFoundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "customcorona.h"
#include <QDebug>
#include <QAction>
#include <KActionCollection>
#include <KPackage/Package>
#include <KPackage/PackageLoader>
#include <Plasma/PluginLoader>
CustomCorona::CustomCorona(QObject *parent)
: Plasma::Corona(parent)
{
KPackage::Package package = KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Shell"));
//applications that want to load a plasma scene would have to load their own shell.. TODO: have a simple shell in plasma-framework for this purpose?
package.setPath(QStringLiteral("org.kde.plasma.desktop"));
setKPackage(package);
qmlRegisterUncreatableType<PlasmaQuick::ContainmentView>("org.kde.plasma.shell", 2, 0, "Desktop", QStringLiteral("It is not possible to create objects of type Desktop"));
m_view = new PlasmaQuick::ContainmentView(this);
m_view->setSource(QUrl::fromLocalFile(package.filePath("views", QStringLiteral("Desktop.qml"))));
m_view->show();
load();
}
QRect CustomCorona::screenGeometry(int id) const
{
Q_UNUSED(id);
//TODO?
return QRect();
}
void CustomCorona::load()
{
loadLayout(QStringLiteral("exampleplasmashell-appletsrc"));
bool desktopFound = false;
for (auto c : containments()) {
if (c->containmentType() == Plasma::Types::DesktopContainment) {
desktopFound = true;
break;
}
}
if (!desktopFound) {
qDebug() << "Loading default layout";
Plasma::Containment *c = createContainment(QStringLiteral("org.kde.desktopcontainment"));
c->createApplet("org.kde.plasma.analogclock");
saveLayout(QStringLiteral("exampleplasmashell-appletsrc"));
}
//don't let containments to be removed
for (auto c : containments()) {
if (c->containmentType() == Plasma::Types::DesktopContainment) {
//example of a shell without a wallpaper
c->setWallpaper("null");
m_view->setContainment(c);
QAction *removeAction = c->actions()->action(QStringLiteral("remove"));
if(removeAction) {
removeAction->deleteLater();
}
break;
}
}
}
#include "moc_customcorona.cpp"

View File

@ -0,0 +1,42 @@
/*
* Copyright 2015 Marco Martin <notmart@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef CUSTOMCORONA_H
#define CUSTOMCORONA_H
#include <Plasma/Corona>
#include <PlasmaQuick/ContainmentView>
class CustomCorona : public Plasma::Corona
{
Q_OBJECT
public:
explicit CustomCorona(QObject * parent = 0);
QRect screenGeometry(int id) const;
public Q_SLOTS:
void load();
private:
PlasmaQuick::ContainmentView *m_view;
};
#endif

53
examples/shell/main.cpp Normal file
View File

@ -0,0 +1,53 @@
/*
* Copyright 2015 Marco Martin <notmart@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <QApplication>
#include <qcommandlineparser.h>
#include <qcommandlineoption.h>
#include <KDBusService>
#include <KLocalizedString>
#include "customcorona.h"
static const char version[] = "1.0";
int main(int argc, char **argv)
{
QQuickWindow::setDefaultAlphaBuffer(true);
QApplication app(argc, argv);
app.setApplicationVersion(version);
app.setOrganizationDomain(QStringLiteral("kde.org"));
KDBusService service(KDBusService::Unique);
QCommandLineParser parser;
parser.setApplicationDescription(i18n("Plasma Example shell"));
parser.addVersionOption();
parser.addHelpOption();
parser.process(app);
CustomCorona *corona = new CustomCorona();
const int ret = app.exec();
delete corona;
return ret;
}

View File

@ -67,6 +67,9 @@ Type=QString
[PropertyDef::X-Plasma-DBusActivationService]
Type=QString
[PropertyDef::X-Plasma-ParentApp]
Type=QString
[PropertyDef::X-Plasma-Provides]
Type=QStringList

View File

@ -57,6 +57,7 @@ class PluginLoaderPrivate
public:
PluginLoaderPrivate()
: isDefaultLoader(false),
plasmoidsDataDir(PLASMA_RELATIVE_DATA_INSTALL_DIR),
packageRE(QLatin1String("[^a-zA-Z0-9\\-_]"))
{
KPackage::PackageLoader::self()->addKnownPackageStructure(QStringLiteral("Plasma/Applet"), new PlasmoidPackage());
@ -78,6 +79,7 @@ public:
static QString s_plasmoidsPluginDir;
static QString s_servicesPluginDir;
static QString s_containmentActionsPluginDir;
QString plasmoidsDataDir;
QRegExp packageRE;
};
@ -231,6 +233,7 @@ Applet *PluginLoader::loadApplet(const QString &name, uint appletId, const QVari
}
}
p.setDefaultPackageRoot(d->plasmoidsDataDir + "/plasmoids/");
// backwards compatibility: search in the root plugins directory
// TODO: remove when Plasma 5.4 is released
{
@ -273,6 +276,16 @@ Applet *PluginLoader::loadApplet(const QString &name, uint appletId, const QVari
return applet;
}
void PluginLoader::setAppletsDataDirectory(const QString &dir)
{
d->plasmoidsDataDir = dir;
}
QString PluginLoader::appletsDataDirectory() const
{
return d->plasmoidsDataDir;
}
DataEngine *PluginLoader::loadDataEngine(const QString &name)
{
DataEngine *engine = d->isDefaultLoader ? 0 : internalLoadDataEngine(name);
@ -529,7 +542,11 @@ Package PluginLoader::loadPackage(const QString &packageFormat, const QString &s
structure = new PackageStructure();
structure->d->internalStructure = internalStructure;
d->structures.insert(hashkey, structure);
return Package(structure);
Package p(structure);
if (packageFormat == "Plasma/Applet") {
p.setDefaultPackageRoot(d->plasmoidsDataDir + "/plasmoids/");
}
return p;
}
}

View File

@ -66,6 +66,31 @@ public:
Applet *loadApplet(const QString &name, uint appletId = 0,
const QVariantList &args = QVariantList());
/**
* Sets the data directory for plasmoids.
* By default plasmoid packages will be loaded from the
* "plasma" data directory, usually under the "share"
* subdirectory of the install prefix.
* An application that uses a custom plasma shell
* can have its private plasmoids
* in its own data directory, not having them mixeed
* with the ones from plasma desktop.
* It takes effect only in applets loaded after setting
* this, so use it at the application startup.
*
* @param dir data directory name
* @since 5.18
*/
void setAppletsDataDirectory(const QString &dir);
/**
* @return the custom applets data directory.
* Default is "plasma"
*
* @since 5.18
*/
QString appletsDataDirectory() const;
/**
* Load a DataEngine plugin.
*

View File

@ -22,7 +22,7 @@ set(plasmaquick_LIB_SRC
add_library(KF5PlasmaQuick SHARED ${plasmaquick_LIB_SRC})
add_library(KF5::PlasmaQuick ALIAS KF5PlasmaQuick)
target_include_directories(KF5PlasmaQuick PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
target_include_directories(KF5PlasmaQuick PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR};${CMAKE_CURRENT_BINARY_DIR}/..>")
target_link_libraries(KF5PlasmaQuick
PUBLIC
@ -68,18 +68,29 @@ generate_export_header(KF5PlasmaQuick BASE_NAME PlasmaQuick)
set(plasmaquick_LIB_INCLUDES
${CMAKE_CURRENT_BINARY_DIR}/plasmaquick_export.h
appletquickitem.h
view.h
containmentview.h
configview.h
configmodel.h
dialog.h
packageurlinterceptor.h
)
#install(FILES ${plasmaquick_LIB_INCLUDES}
# DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/plasmaquick COMPONENT Devel)
ecm_generate_headers(PlasmaQuick_CamelCase_HEADERS
HEADER_NAMES
AppletQuickItem
ContainmentView
ConfigView
ConfigModel
Dialog
REQUIRED_HEADERS plasmaquick_LIB_INCLUDES
PREFIX PlasmaQuick
)
#install(DIRECTORY
# includes/PlasmaQuick
# DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KDE COMPONENT Devel)
install(FILES ${plasmaquick_LIB_INCLUDES}
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/plasmaquick COMPONENT Devel)
install(FILES ${PlasmaQuick_CamelCase_HEADERS}
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/PlasmaQuick COMPONENT Devel)
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5PlasmaQuick")

View File

@ -21,7 +21,7 @@
#include <kquickaddons/quickviewsharedengine.h>
#include <plasmaquick_export.h>
#include <plasmaquick/plasmaquick_export.h>
#include "plasma/corona.h"
#include "plasma/containment.h"