subtree merge of kdelibs/plasma into plasma
This commit is contained in:
commit
7d636803e6
2
plasma/.krazy
Normal file
2
plasma/.krazy
Normal file
@ -0,0 +1,2 @@
|
||||
EXTRA defines,kdebug,qenums,tipsandthis
|
||||
SKIP /widgets/template\.h
|
304
plasma/CMakeLists.txt
Normal file
304
plasma/CMakeLists.txt
Normal file
@ -0,0 +1,304 @@
|
||||
|
||||
# This option should be removed, or moved down as far as possible.
|
||||
# That means porting the existing frameworks to the CMake automoc
|
||||
# feature. Porting is mostly removing explicit moc includes, and
|
||||
# leaving the ones which are truly needed (ie, if you remove
|
||||
# them, the build fails).
|
||||
set(CMAKE_AUTOMOC_RELAXED_MODE ON)
|
||||
|
||||
if(KDE_PLATFORM_FEATURE_BINARY_COMPATIBLE_FEATURE_REDUCTION)
|
||||
set(PLASMA_NO_KNEWSTUFF TRUE)
|
||||
set(PLASMA_NO_SOLID TRUE)
|
||||
set(PLASMA_NO_KIO TRUE)
|
||||
set(PLASMA_NO_PACKAGEKIT TRUE)
|
||||
set(PLASMA_NO_PACKAGE_EXTRADATA TRUE)
|
||||
set(PLASMA_NO_KUTILS TRUE)
|
||||
set(PLASMA_NO_GLOBAL_SHORTCUTS TRUE)
|
||||
endif(KDE_PLATFORM_FEATURE_BINARY_COMPATIBLE_FEATURE_REDUCTION)
|
||||
|
||||
if(NOT X11_FOUND)
|
||||
set(PLASMA_NO_PACKAGEKIT TRUE)
|
||||
endif(NOT X11_FOUND)
|
||||
|
||||
#find_package(KdepimLibs 4.5.60)
|
||||
#find_package(Gpgme)
|
||||
#macro_log_feature(KDEPIMLIBS_FOUND "kdepimlibs" "KDE PIM libraries" "http://www.kde.org" FALSE "" "Needed for building several Plasma DataEngines")
|
||||
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${KDE4_KDECORE_INCLUDES}
|
||||
${KDE4_KDEUI_INCLUDES}
|
||||
${CMAKE_SOURCE_DIR}/experimental/libkdeclarative
|
||||
${CMAKE_BINARY_DIR}/experimental/libkdeclarative
|
||||
${karchive_SOURCE_DIR}/src
|
||||
${karchive_BINARY_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/tier2/kauth/src/
|
||||
${CMAKE_BINARY_DIR}/tier2/kauth/src/
|
||||
${CMAKE_SOURCE_DIR}/tier1/threadweaver/src
|
||||
${CMAKE_BINARY_DIR}/tier1/threadweaver/src
|
||||
${CMAKE_BINARY_DIR}/tier1/threadweaver/src/Weaver
|
||||
${CMAKE_SOURCE_DIR}/tier1/kwindowsystem/
|
||||
${CMAKE_BINARY_DIR}/tier1/kwindowsystem/
|
||||
${CMAKE_SOURCE_DIR}/tier1/solid/src
|
||||
${CMAKE_BINARY_DIR}/tier1/solid/src
|
||||
${CMAKE_SOURCE_DIR}/plasma/remote
|
||||
${CMAKE_SOURCE_DIR}/plasma/private/qtjolie-branch/qtjolie
|
||||
${CMAKE_SOURCE_DIR}/plasma/private/qtjolie-branch
|
||||
${CMAKE_SOURCE_DIR}/plasma/private/qtjolie-branch/includes
|
||||
${CMAKE_SOURCE_DIR}/tier1/kcoreaddons/src/caching
|
||||
${ki18n_SOURCE_DIR}/src
|
||||
${ki18n_BINARY_DIR}/src
|
||||
)
|
||||
|
||||
if(NOT PLASMA_NO_KIO)
|
||||
include_directories(${KDE4_KIO_INCLUDES})
|
||||
set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} ${KDE4_KIO_LIBS})
|
||||
endif(NOT PLASMA_NO_KIO)
|
||||
|
||||
if(NOT PLASMA_NO_KNEWSTUFF)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/knewstuff/)
|
||||
include_directories(${CMAKE_BINARY_DIR}/knewstuff/)
|
||||
set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} knewstuff3)
|
||||
endif(NOT PLASMA_NO_KNEWSTUFF)
|
||||
|
||||
if(NOT PLASMA_NO_SOLID)
|
||||
include_directories(${CMAKE_BINARY_DIR}/tier1/solid/)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/tier1/solid/)
|
||||
set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} ${KDE4_SOLID_LIBS})
|
||||
endif(NOT PLASMA_NO_SOLID)
|
||||
|
||||
if(NOT PLASMA_NO_PACKAGEKIT)
|
||||
add_definitions(-DPLASMA_ENABLE_PACKAGEKIT_SUPPORT=1)
|
||||
set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} ${QT_QTDBUS_LIBRARY})
|
||||
endif(NOT PLASMA_NO_PACKAGEKIT)
|
||||
|
||||
if (NOT PLASMA_NO_KUTILS)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/kutils)
|
||||
include_directories(${CMAKE_BINARY_DIR}/kutils)
|
||||
set(PLASMA_EXTRA_LIBS ${PLASMA_EXTRA_LIBS} ${KDE4_KUTILS_LIBS})
|
||||
endif(NOT PLASMA_NO_KUTILS)
|
||||
|
||||
if(QCA2_FOUND)
|
||||
include_directories(${QCA2_INCLUDE_DIR})
|
||||
set(ENABLE_REMOTE_WIDGETS TRUE)
|
||||
endif(QCA2_FOUND)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-plasma.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-plasma.h)
|
||||
|
||||
#FIXME: gpgme++ is in kdepimlibs, must move somewhere else!
|
||||
include_directories(${KDEPIMLIBS_INCLUDE_DIRS} ${GPGME_INCLUDES})
|
||||
|
||||
add_subdirectory(tests)
|
||||
add_definitions(-DKDE_DEFAULT_DEBUG_AREA=1209)
|
||||
|
||||
########### next target ###############
|
||||
|
||||
set(plasma_LIB_SRCS
|
||||
abstractrunner.cpp
|
||||
${plasmagik_SRCS}
|
||||
abstractdialogmanager.cpp
|
||||
configloader.cpp
|
||||
containmentactions.cpp
|
||||
containmentactionspluginsconfig.cpp
|
||||
datacontainer.cpp
|
||||
dataengine.cpp
|
||||
dataengineconsumer.cpp
|
||||
package.cpp
|
||||
packagestructure.cpp
|
||||
paintutils.cpp
|
||||
pluginloader.cpp
|
||||
framesvg.cpp
|
||||
plasma.cpp
|
||||
pluginloader.cpp
|
||||
|
||||
private/associatedapplicationmanager.cpp
|
||||
private/componentinstaller.cpp
|
||||
private/datacontainer_p.cpp
|
||||
private/dataenginemanager.cpp
|
||||
private/dataengineservice.cpp
|
||||
private/effects/halopainter.cpp
|
||||
private/getsource.cpp
|
||||
|
||||
private/packages.cpp
|
||||
private/packagejob.cpp
|
||||
private/packagejobthread.cpp
|
||||
private/plasmoidservice.cpp
|
||||
private/remotedataengine.cpp
|
||||
private/remoteservice.cpp
|
||||
private/remoteservicejob.cpp
|
||||
private/runnerjobs.cpp
|
||||
private/serviceprovider.cpp
|
||||
private/storage.cpp
|
||||
private/storagethread.cpp
|
||||
private/windowpreview.cpp
|
||||
private/windowshadows.cpp
|
||||
private/applet_p.cpp
|
||||
private/containment_p.cpp
|
||||
|
||||
querymatch.cpp
|
||||
remote/accessmanager.cpp
|
||||
remote/accessappletjob.cpp
|
||||
remote/authorizationinterface.cpp
|
||||
remote/authorizationmanager.cpp
|
||||
remote/authorizationrule.cpp
|
||||
remote/clientpinrequest.cpp
|
||||
remote/credentials.cpp
|
||||
remote/denyallauthorization.cpp
|
||||
remote/pinpairingauthorization.cpp
|
||||
remote/pinpairingdialog.cpp
|
||||
remote/serviceaccessjob.cpp
|
||||
#remote/signing.cpp TODO: re-enable, needs gpgmepp though
|
||||
remote/trustedonlyauthorization.cpp
|
||||
runnercontext.cpp
|
||||
runnermanager.cpp
|
||||
runnersyntax.cpp
|
||||
scripting/appletscript.cpp
|
||||
scripting/dataenginescript.cpp
|
||||
scripting/runnerscript.cpp
|
||||
scripting/scriptengine.cpp
|
||||
service.cpp
|
||||
servicejob.cpp
|
||||
svg.cpp
|
||||
theme.cpp
|
||||
version.cpp
|
||||
|
||||
|
||||
#Temporary QtJolie branch
|
||||
private/qtjolie-branch/qtjolie/abstractadaptor.cpp
|
||||
private/qtjolie-branch/qtjolie/client.cpp
|
||||
private/qtjolie-branch/qtjolie/clientthread.cpp
|
||||
private/qtjolie-branch/qtjolie/value.cpp
|
||||
private/qtjolie-branch/qtjolie/fault.cpp
|
||||
private/qtjolie-branch/qtjolie/message.cpp
|
||||
private/qtjolie-branch/qtjolie/metaservice.cpp
|
||||
private/qtjolie-branch/qtjolie/pendingcall.cpp
|
||||
private/qtjolie-branch/qtjolie/pendingcallwatcher.cpp
|
||||
private/qtjolie-branch/qtjolie/pendingreply.cpp
|
||||
private/qtjolie-branch/qtjolie/server.cpp
|
||||
private/qtjolie-branch/qtjolie/serverthread.cpp
|
||||
applet.cpp
|
||||
containment.cpp
|
||||
corona.cpp
|
||||
)
|
||||
|
||||
if (QT5_BUILD)
|
||||
set(plasma_LIB_SRCS ${plasma_LIB_SRCS} private/effectwatcher.cpp)
|
||||
endif()
|
||||
|
||||
kconfig_add_kcfg_files(plasma_LIB_SRCS data/kconfigxt/libplasma-theme-global.kcfgc)
|
||||
|
||||
kde4_add_ui_files(plasma_LIB_SRCS
|
||||
remote/pinpairing.ui
|
||||
private/publish.ui)
|
||||
#NEPOMUK_GENERATE_FROM_ONTOLOGY(
|
||||
# nwc.nrl
|
||||
# ${metadata_test_BINARY_DIR}
|
||||
# TEST_HEADERS
|
||||
# TEST_SOURCES
|
||||
# TEST_INCLUDES
|
||||
#)
|
||||
|
||||
|
||||
kde4_add_library(plasma ${LIBRARY_TYPE} ${plasma_LIB_SRCS})
|
||||
|
||||
target_link_libraries(plasma ${QT_QTUITOOLS_LIBRARY}
|
||||
${QT_QTNETWORK_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTSQL_LIBRARY}
|
||||
${KDE4_KDEUI_LIBS} kdnssd threadweaver kauth kwindowsystem ${PLASMA_EXTRA_LIBS} kcoreaddons ki18n)
|
||||
#FIXME gpgme++ is in kdepimlibs, neeeds to be elsewhere
|
||||
target_link_libraries(plasma ${KDEPIMLIBS_GPGMEPP_LIBS} kdeclarative karchive)
|
||||
|
||||
if(QCA2_FOUND)
|
||||
target_link_libraries(plasma ${QCA2_LIBRARIES})
|
||||
endif(QCA2_FOUND)
|
||||
|
||||
if(X11_FOUND)
|
||||
target_link_libraries(plasma ${X11_LIBRARIES})
|
||||
endif(X11_FOUND)
|
||||
|
||||
if(DL_LIBRARY)
|
||||
target_link_libraries(plasma ${DL_LIBRARY})
|
||||
endif(DL_LIBRARY)
|
||||
|
||||
target_link_libraries(plasma LINK_INTERFACE_LIBRARIES kdeui kdecore kwindowsystem Qt5::Widgets)
|
||||
|
||||
#do NOT use GENERIC versioning -- the plasma team will take care of versioning
|
||||
set_target_properties(plasma PROPERTIES
|
||||
VERSION 4.0.0
|
||||
SOVERSION 4
|
||||
)
|
||||
|
||||
install(TARGETS plasma EXPORT kdelibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
########### install files ###############
|
||||
generate_export_header(plasma)
|
||||
|
||||
set(plasma_LIB_INCLUDES
|
||||
abstractdialogmanager.h
|
||||
abstractrunner.h
|
||||
applet.h
|
||||
configloader.h
|
||||
containment.h
|
||||
containmentactions.h
|
||||
containmentactionspluginsconfig.h
|
||||
corona.h
|
||||
datacontainer.h
|
||||
dataengine.h
|
||||
pluginloader.h
|
||||
paintutils.h
|
||||
framesvg.h
|
||||
package.h
|
||||
packagestructure.h
|
||||
plasma.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/plasma_export.h
|
||||
querymatch.h
|
||||
remote/accessappletjob.h
|
||||
remote/accessmanager.h
|
||||
remote/authorizationmanager.h
|
||||
remote/authorizationrule.h
|
||||
remote/authorizationinterface.h
|
||||
remote/clientpinrequest.h
|
||||
remote/credentials.h
|
||||
remote/serviceaccessjob.h
|
||||
runnercontext.h
|
||||
runnermanager.h
|
||||
runnersyntax.h
|
||||
service.h
|
||||
servicejob.h
|
||||
svg.h
|
||||
theme.h
|
||||
version.h)
|
||||
|
||||
|
||||
install(FILES
|
||||
${plasma_LIB_INCLUDES}
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/plasma COMPONENT Devel)
|
||||
|
||||
|
||||
install(FILES
|
||||
scripting/appletscript.h
|
||||
scripting/dataenginescript.h
|
||||
scripting/runnerscript.h
|
||||
scripting/scriptengine.h
|
||||
DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/scripting COMPONENT Devel)
|
||||
|
||||
install(FILES
|
||||
data/servicetypes/plasma-applet.desktop
|
||||
data/servicetypes/plasma-containment.desktop
|
||||
data/servicetypes/plasma-containmentactions.desktop
|
||||
data/servicetypes/plasma-dataengine.desktop
|
||||
data/servicetypes/plasma-packagestructure.desktop
|
||||
data/servicetypes/plasma-runner.desktop
|
||||
data/servicetypes/plasma-scriptengine.desktop
|
||||
data/servicetypes/plasma-service.desktop
|
||||
DESTINATION ${SERVICETYPES_INSTALL_DIR})
|
||||
|
||||
install(FILES
|
||||
data/services/plasma.protocol
|
||||
DESTINATION ${SERVICES_INSTALL_DIR})
|
||||
|
||||
install(FILES data/knewstuff/plasmoids.knsrc DESTINATION ${CONFIG_INSTALL_DIR})
|
||||
|
||||
install(FILES data/operations/dataengineservice.operations DESTINATION ${DATA_INSTALL_DIR}/plasma/services)
|
||||
install(FILES data/operations/plasmoidservice.operations DESTINATION ${DATA_INSTALL_DIR}/plasma/services)
|
||||
install(FILES data/operations/storage.operations DESTINATION ${DATA_INSTALL_DIR}/plasma/services)
|
||||
|
100
plasma/Mainpage.dox
Normal file
100
plasma/Mainpage.dox
Normal file
@ -0,0 +1,100 @@
|
||||
/** @mainpage Plasma libraries
|
||||
|
||||
libplasma is the core of the Plasma desktop. It provides a framework of graphical
|
||||
widgets (Plasma::Applet) that can be organised into managed groupings
|
||||
(Plasma::Containment), such as a desktop or panel. It also provides a data
|
||||
abstraction layer (Plasma::DataEngine) and a corresponding service interaction
|
||||
layer (Plasma::Service) to make implementing widgets easier and a
|
||||
system of callouts (Plasma::AbstractRunner) that provide responses to queries,
|
||||
from running an application to performing a quick calculation.
|
||||
|
||||
The <a href="http://doc.trolltech.com/latest/graphicsview.html">Qt Graphics View
|
||||
framework</a> and the <a href="http://api.kde.org/4.x-api/kdelibs-apidocs/">KDE
|
||||
libraries</a> provide the underpinning for libplasma. As a result, it should
|
||||
work anywhere that Qt and KDE do.
|
||||
|
||||
Although libplasma is developed for the use of the Plasma desktop shell in
|
||||
KDE 4, it is general enough to be useful in other applications.
|
||||
<a href="http://amarok.kde.org">Amarok</a> is using it for its context
|
||||
view, allowing for pluggable widgets to display and interact with the music
|
||||
collection, such as "current track" and "tag cloud" widgets.
|
||||
|
||||
libplasma itself only provides a framework, and the widgets, containments,
|
||||
data engines and runners are all implemented as plugins. However, the framework
|
||||
is designed to make implementing these plugins as easy as possible, including
|
||||
providing scripting support.
|
||||
|
||||
Other important classes are:
|
||||
|
||||
- Plasma::Corona: the canvas that containments are placed on
|
||||
- Plasma::View: a QWidget for displaying a containment
|
||||
- Plasma::Theme: provides theming support
|
||||
- Plasma::Animator: provides animations for things like elements appearing
|
||||
and disappearing
|
||||
- Plasma::Delegate: provides an item delegate for Qt's
|
||||
<a href="http://doc.trolltech.com/latest/model-view-programming.html">Model /
|
||||
View framework</a> for menu items.
|
||||
- Plasma::ToolTipManager: allows widgets have (themed) tooltips displayed when the
|
||||
mouse is hovered over them
|
||||
- Plasma::Dialog: displays a themed application dialog
|
||||
- Plasma::Extender: provides detachable sections to Plasma::Applet
|
||||
- Plasma::GLApplet: provides an OpenGL-rendered Plasma::Applet
|
||||
- Plasma::Package: provides descriptions of packages containing plugins
|
||||
for libplasma
|
||||
- Plasma::PopupApplet: provides a simple way of implementing a Plasma::Applet
|
||||
consisting of an icon that shows a popup when clicked
|
||||
- Plasma::Svg and Plasma::FrameSvg: provides themable, cached SVGs
|
||||
- Plasma::Wallpaper: provides pluggable backgrounds for containments
|
||||
- Plasma::AppletScript, Plasma::DataEngineScript, Plasma::RunnerScript and
|
||||
Plasma::ScriptEngine: provide scripting interfaces for plugins
|
||||
- Various themed QGraphicsWidgets for use in creating a Plasma::Applet
|
||||
|
||||
|
||||
The
|
||||
<a href="http://techbase.kde.org/Development/Tutorials/Plasma">Plasma tutorials</a>
|
||||
on TechBase provide a good introduction to writing plugins, such as widgets and
|
||||
data engines, for libplasma-based applications.
|
||||
|
||||
@authors
|
||||
Aaron Seigo \<aseigo@kde.org\><br>
|
||||
Alessandro Diaferia \<alediaferia@gmail.com\><br>
|
||||
Alex Merry \<kde@randomguy3.me.uk\><br>
|
||||
Alexander Wiedenbruch \<wirr01@gmail.com\><br>
|
||||
Alexis Ménard \<darktears31@gmail.com\><br>
|
||||
André Duffeck \<andre@duffeck.de\><br>
|
||||
Andrew Lake \<jamboarder@yahoo.com\><br>
|
||||
Artur de Souza \<asouza@kde.org\><br>
|
||||
Bertjan Broeksema \<b.broeksema@kdemail.net\><br>
|
||||
Chani Armitage \<chanika@gmail.com\><br>
|
||||
Davide Bettio \<davide.bettio@kdemail.net\><br>
|
||||
Dan Meltzer \<hydrogen@notyetimplemented.com\><br>
|
||||
Fredrik Höglund \<fredrik@kde.org\><br>
|
||||
Ivan Cukic \<ivan.cukic+kde@gmail.com\><br>
|
||||
John Tapsell \<tapsell@kde.org\><br>
|
||||
Jordi Polo \<mumismo@gmail.com\><br>
|
||||
Kevin Ottens \<ervin@kde.org\><br>
|
||||
Montel Laurent \<montel@kde.org\><br>
|
||||
Marco Martin \<notmart@gmail.com\><br>
|
||||
Matt Broadstone \<mbroadst@gmail.com\><br>
|
||||
Petri Damsten \<damu@iki.fi\><br>
|
||||
Rafael Fernández López \<ereslibre@kde.org\><br>
|
||||
Riccardo Iaconelli \<riccardo@kde.org\><br>
|
||||
Richard J. Moore \<rich@kde.org\><br>
|
||||
Rob Scheepmaker \<r.scheepmaker@student.utwente.nl\><br>
|
||||
Robert Knight \<robertknight@gmail.com\><br>
|
||||
Sebastian Kuegler \<sebas@kde.org\><br>
|
||||
Siraj Razick \<siraj@kde.net\><br>
|
||||
Zack Rusin \<zack@kde.org\>
|
||||
|
||||
@maintainers
|
||||
Aaron Seigo \<aseigo@kde.org\>
|
||||
|
||||
@licenses
|
||||
@lgpl
|
||||
|
||||
*/
|
||||
|
||||
// DOXYGEN_SET_PROJECT_NAME = Plasma
|
||||
// DOXYGEN_SET_RECURSIVE = YES
|
||||
// DOXYGEN_EXCLUDE_PATTERNS = *_p.h */private/* */tests/*
|
||||
// vim:ts=4:sw=4:expandtab:filetype=doxygen
|
4
plasma/Messages.sh
Normal file
4
plasma/Messages.sh
Normal file
@ -0,0 +1,4 @@
|
||||
#! /usr/bin/env bash
|
||||
$EXTRACTRC private/*.ui >> rc.cpp
|
||||
$XGETTEXT `ls *.cpp *.h */*.h */*.cpp | grep -v 'tests/'` -o $podir/libplasma.pot
|
||||
rm -f *.ui
|
29
plasma/README
Normal file
29
plasma/README
Normal file
@ -0,0 +1,29 @@
|
||||
libplasma
|
||||
|
||||
This directory contains the classes making up libplasma, which provides the
|
||||
core framework used by Plasma applications, such as the Plasma desktop shell
|
||||
and its components. This includes applet and extension definitions and loading,
|
||||
common GUI elements, data and service interaction, search system, etc.
|
||||
|
||||
Domain specific sets of functionality, e.g. for network awareness or sensors,
|
||||
are not found here but as DataEngine, Service, Applet, Package, Wallpaper,
|
||||
ContainmentActions, Containment and other plugins.
|
||||
|
||||
Commit Guidelines:
|
||||
* If your patch is not an obvious or trivial bug fix, have it peer reviewed
|
||||
by another Plasma developer; http://reviewboard.kde.org is your friend :)
|
||||
|
||||
* All code MUST follow the kdelibs coding style, as found at:
|
||||
http://techbase.kde.org/Policies/Kdelibs_Coding_Style
|
||||
|
||||
* All new public API MUST have apidox written before committing and must go
|
||||
through an API review with another Plasma developer. We have to maintain
|
||||
binary compatibility, remember!
|
||||
|
||||
Unit tests are next to godliness. (Though as you can see, right now libplasma
|
||||
is hellbound.)
|
||||
|
||||
Please refer to the Plasma website (http://plasma.kde.org) and Plasma wiki
|
||||
(http://techbase.kde.org/Projects/Plasma) for API documentation and design
|
||||
documents regarding this library.
|
||||
|
56
plasma/abstractdialogmanager.cpp
Normal file
56
plasma/abstractdialogmanager.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* 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 "abstractdialogmanager.h"
|
||||
|
||||
#include "corona.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AbstractDialogManagerPrivate
|
||||
{
|
||||
public:
|
||||
AbstractDialogManagerPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
AbstractDialogManager::AbstractDialogManager(Corona *parent)
|
||||
: QObject(parent),
|
||||
d(new AbstractDialogManagerPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractDialogManager::~AbstractDialogManager()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void AbstractDialogManager::showDialog(QWidget *widget, Plasma::Applet *applet)
|
||||
{
|
||||
Q_UNUSED(applet)
|
||||
widget->show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include "moc_abstractdialogmanager.cpp"
|
67
plasma/abstractdialogmanager.h
Normal file
67
plasma/abstractdialogmanager.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* 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 PLASMA_DIALOGMANAGER_H
|
||||
#define PLASMA_DIALOGMANAGER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
class Applet;
|
||||
class Corona;
|
||||
|
||||
class AbstractDialogManagerPrivate;
|
||||
|
||||
/**
|
||||
* @class AbstractDialogManager plasma/dialogmanager.h <Plasma/AbstractDialogManager>
|
||||
*
|
||||
* @short The AbstractDialogManager class shows the dialogs shown by applets and the rest of the shell.
|
||||
* a AbstractDialogManager can manage aspects like positioning, sizing and widget style
|
||||
* of dialogs sich as the applet configuration dialog.
|
||||
* @since 4.5
|
||||
*/
|
||||
class PLASMA_EXPORT AbstractDialogManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AbstractDialogManager(Plasma::Corona *parent=0);
|
||||
~AbstractDialogManager();
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* This fake virtual slot shows a dialog belonging to an applet.
|
||||
* There is no guarantee how the implementation will show it
|
||||
* @param widget the dialog widget
|
||||
* @param applet the applet that owns the dialog
|
||||
*/
|
||||
void showDialog(QWidget *widget, Plasma::Applet *applet);
|
||||
|
||||
private:
|
||||
|
||||
AbstractDialogManagerPrivate * const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
460
plasma/abstractrunner.cpp
Normal file
460
plasma/abstractrunner.cpp
Normal file
@ -0,0 +1,460 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 "abstractrunner.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QHash>
|
||||
#include <QMenu>
|
||||
#include <QMimeData>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QTimer>
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <kplugininfo.h>
|
||||
#include <kservicetypetrader.h>
|
||||
#include <kstandarddirs.h>
|
||||
#include <klocalizedstring.h>
|
||||
#include <kiconloader.h>
|
||||
#include <kglobal.h>
|
||||
#include <qstandardpaths.h>
|
||||
|
||||
#include "package.h"
|
||||
#include "pluginloader.h"
|
||||
#include "private/abstractrunner_p.h"
|
||||
#include "querymatch.h"
|
||||
#include "runnercontext.h"
|
||||
#include "scripting/runnerscript.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
AbstractRunner::AbstractRunner(QObject *parent, const QString &path)
|
||||
: QObject(parent),
|
||||
d(new AbstractRunnerPrivate(this))
|
||||
{
|
||||
d->init(path);
|
||||
}
|
||||
|
||||
AbstractRunner::AbstractRunner(const KService::Ptr service, QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new AbstractRunnerPrivate(this))
|
||||
{
|
||||
d->init(service);
|
||||
}
|
||||
|
||||
AbstractRunner::AbstractRunner(QObject *parent, const QVariantList &args)
|
||||
: QObject(parent),
|
||||
d(new AbstractRunnerPrivate(this))
|
||||
{
|
||||
if (args.count() > 0) {
|
||||
KService::Ptr service = KService::serviceByStorageId(args[0].toString());
|
||||
if (service) {
|
||||
d->init(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AbstractRunner::~AbstractRunner()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
KConfigGroup AbstractRunner::config() const
|
||||
{
|
||||
QString group = id();
|
||||
if (group.isEmpty()) {
|
||||
group = "UnnamedRunner";
|
||||
}
|
||||
|
||||
KConfigGroup runners(KSharedConfig::openConfig(), "Runners");
|
||||
return KConfigGroup(&runners, group);
|
||||
}
|
||||
|
||||
void AbstractRunner::reloadConfiguration()
|
||||
{
|
||||
if (d->script) {
|
||||
emit d->script->reloadConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRunner::addSyntax(const RunnerSyntax &syntax)
|
||||
{
|
||||
d->syntaxes.append(syntax);
|
||||
}
|
||||
|
||||
void AbstractRunner::setDefaultSyntax(const RunnerSyntax &syntax)
|
||||
{
|
||||
d->syntaxes.append(syntax);
|
||||
d->defaultSyntax = &(d->syntaxes.last());
|
||||
}
|
||||
|
||||
void AbstractRunner::setSyntaxes(const QList<RunnerSyntax> &syntaxes)
|
||||
{
|
||||
d->syntaxes = syntaxes;
|
||||
}
|
||||
|
||||
QList<RunnerSyntax> AbstractRunner::syntaxes() const
|
||||
{
|
||||
return d->syntaxes;
|
||||
}
|
||||
|
||||
RunnerSyntax *AbstractRunner::defaultSyntax() const
|
||||
{
|
||||
return d->defaultSyntax;
|
||||
}
|
||||
|
||||
void AbstractRunner::performMatch(Plasma::RunnerContext &localContext)
|
||||
{
|
||||
static const int reasonableRunTime = 1500;
|
||||
static const int fastEnoughTime = 250;
|
||||
|
||||
if (d->suspendMatching) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTime time;
|
||||
time.restart();
|
||||
|
||||
//The local copy is already obtained in the job
|
||||
match(localContext);
|
||||
|
||||
// automatically rate limit runners that become slooow
|
||||
const int runtime = time.elapsed();
|
||||
bool slowed = speed() == SlowSpeed;
|
||||
|
||||
if (!slowed && runtime > reasonableRunTime) {
|
||||
// we punish runners that return too slowly, even if they don't bring
|
||||
// back matches
|
||||
#ifndef NDEBUG
|
||||
kDebug() << id() << "runner is too slow, putting it on the back burner.";
|
||||
#endif
|
||||
d->fastRuns = 0;
|
||||
setSpeed(SlowSpeed);
|
||||
}
|
||||
|
||||
if (slowed && runtime < fastEnoughTime && localContext.query().size() > 2) {
|
||||
++d->fastRuns;
|
||||
|
||||
if (d->fastRuns > 2) {
|
||||
// we reward slowed runners who bring back matches fast enough
|
||||
// 3 times in a row
|
||||
#ifndef NDEBUG
|
||||
kDebug() << id() << "runner is faster than we thought, kicking it up a notch";
|
||||
#endif
|
||||
setSpeed(NormalSpeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<QAction*> AbstractRunner::actionsForMatch(const Plasma::QueryMatch &match)
|
||||
{
|
||||
Q_UNUSED(match)
|
||||
QList<QAction*> ret;
|
||||
if (d->script) {
|
||||
emit d->script->actionsForMatch(match, &ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QAction* AbstractRunner::addAction(const QString &id, const QIcon &icon, const QString &text)
|
||||
{
|
||||
QAction *a = new QAction(icon, text, this);
|
||||
d->actions.insert(id, a);
|
||||
return a;
|
||||
}
|
||||
|
||||
void AbstractRunner::addAction(const QString &id, QAction *action)
|
||||
{
|
||||
d->actions.insert(id, action);
|
||||
}
|
||||
|
||||
void AbstractRunner::removeAction(const QString &id)
|
||||
{
|
||||
QAction *a = d->actions.take(id);
|
||||
delete a;
|
||||
}
|
||||
|
||||
QAction* AbstractRunner::action(const QString &id) const
|
||||
{
|
||||
return d->actions.value(id);
|
||||
}
|
||||
|
||||
QHash<QString, QAction*> AbstractRunner::actions() const
|
||||
{
|
||||
return d->actions;
|
||||
}
|
||||
|
||||
void AbstractRunner::clearActions()
|
||||
{
|
||||
qDeleteAll(d->actions);
|
||||
d->actions.clear();
|
||||
}
|
||||
|
||||
QMimeData *AbstractRunner::mimeDataForMatch(const QueryMatch &match)
|
||||
{
|
||||
Q_UNUSED(match)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AbstractRunner::hasRunOptions()
|
||||
{
|
||||
return d->hasRunOptions;
|
||||
}
|
||||
|
||||
void AbstractRunner::setHasRunOptions(bool hasRunOptions)
|
||||
{
|
||||
d->hasRunOptions = hasRunOptions;
|
||||
}
|
||||
|
||||
void AbstractRunner::createRunOptions(QWidget *parent)
|
||||
{
|
||||
if (d->script) {
|
||||
emit d->script->createRunOptions(parent);
|
||||
}
|
||||
}
|
||||
|
||||
AbstractRunner::Speed AbstractRunner::speed() const
|
||||
{
|
||||
// the only time the read lock will fail is if we were slow are going to speed up
|
||||
// or if we were fast and are going to slow down; so don't wait in this case, just
|
||||
// say we're slow. we either will be soon or were just a moment ago and it doesn't
|
||||
// hurt to do one more run the slow way
|
||||
if (!d->speedLock.tryLockForRead()) {
|
||||
return SlowSpeed;
|
||||
}
|
||||
Speed s = d->speed;
|
||||
d->speedLock.unlock();
|
||||
return s;
|
||||
}
|
||||
|
||||
void AbstractRunner::setSpeed(Speed speed)
|
||||
{
|
||||
d->speedLock.lockForWrite();
|
||||
d->speed = speed;
|
||||
d->speedLock.unlock();
|
||||
}
|
||||
|
||||
AbstractRunner::Priority AbstractRunner::priority() const
|
||||
{
|
||||
return d->priority;
|
||||
}
|
||||
|
||||
void AbstractRunner::setPriority(Priority priority)
|
||||
{
|
||||
d->priority = priority;
|
||||
}
|
||||
|
||||
RunnerContext::Types AbstractRunner::ignoredTypes() const
|
||||
{
|
||||
return d->blackListed;
|
||||
}
|
||||
|
||||
void AbstractRunner::setIgnoredTypes(RunnerContext::Types types)
|
||||
{
|
||||
d->blackListed = types;
|
||||
}
|
||||
|
||||
void AbstractRunner::run(const Plasma::RunnerContext &search, const Plasma::QueryMatch &action)
|
||||
{
|
||||
if (d->script) {
|
||||
return d->script->run(search, action);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRunner::match(Plasma::RunnerContext &search)
|
||||
{
|
||||
if (d->script) {
|
||||
return d->script->match(search);
|
||||
}
|
||||
}
|
||||
|
||||
QString AbstractRunner::name() const
|
||||
{
|
||||
if (d->runnerDescription.isValid()) {
|
||||
return d->runnerDescription.name();
|
||||
}
|
||||
|
||||
return objectName();
|
||||
}
|
||||
|
||||
QIcon AbstractRunner::icon() const
|
||||
{
|
||||
if (d->runnerDescription.isValid()) {
|
||||
return KDE::icon(d->runnerDescription.icon());
|
||||
}
|
||||
|
||||
return QIcon();
|
||||
}
|
||||
|
||||
QString AbstractRunner::id() const
|
||||
{
|
||||
if (d->runnerDescription.isValid()) {
|
||||
return d->runnerDescription.pluginName();
|
||||
}
|
||||
|
||||
return objectName();
|
||||
}
|
||||
|
||||
QString AbstractRunner::description() const
|
||||
{
|
||||
if (d->runnerDescription.isValid()) {
|
||||
return d->runnerDescription.property("Comment").toString();
|
||||
}
|
||||
|
||||
return objectName();
|
||||
}
|
||||
|
||||
Package AbstractRunner::package() const
|
||||
{
|
||||
return d->package ? *d->package : Package();
|
||||
}
|
||||
|
||||
|
||||
void AbstractRunner::init()
|
||||
{
|
||||
if (d->script) {
|
||||
d->setupScriptSupport();
|
||||
d->script->init();
|
||||
}
|
||||
|
||||
reloadConfiguration();
|
||||
}
|
||||
|
||||
DataEngine *AbstractRunner::dataEngine(const QString &name) const
|
||||
{
|
||||
return d->dataEngine(name);
|
||||
}
|
||||
|
||||
bool AbstractRunner::isMatchingSuspended() const
|
||||
{
|
||||
return d->suspendMatching;
|
||||
}
|
||||
|
||||
void AbstractRunner::suspendMatching(bool suspend)
|
||||
{
|
||||
if (d->suspendMatching == suspend) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->suspendMatching = suspend;
|
||||
emit matchingSuspended(suspend);
|
||||
}
|
||||
|
||||
AbstractRunnerPrivate::AbstractRunnerPrivate(AbstractRunner *r)
|
||||
: priority(AbstractRunner::NormalPriority),
|
||||
speed(AbstractRunner::NormalSpeed),
|
||||
blackListed(0),
|
||||
script(0),
|
||||
runner(r),
|
||||
fastRuns(0),
|
||||
package(0),
|
||||
defaultSyntax(0),
|
||||
hasRunOptions(false),
|
||||
suspendMatching(false)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractRunnerPrivate::~AbstractRunnerPrivate()
|
||||
{
|
||||
delete script;
|
||||
script = 0;
|
||||
delete package;
|
||||
package = 0;
|
||||
}
|
||||
|
||||
void AbstractRunnerPrivate::init(const KService::Ptr service)
|
||||
{
|
||||
runnerDescription = KPluginInfo(service);
|
||||
if (runnerDescription.isValid()) {
|
||||
const QString api = runnerDescription.property("X-Plasma-API").toString();
|
||||
if (!api.isEmpty()) {
|
||||
const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "plasma/runners/" + runnerDescription.pluginName() + '/');
|
||||
prepScripting(path, api);
|
||||
if (!script) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Could not create a(n)" << api << "ScriptEngine for the" << runnerDescription.name() << "Runner.";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractRunnerPrivate::init(const QString &path)
|
||||
{
|
||||
runnerDescription = KPluginInfo(path + "/metadata.desktop");
|
||||
const QString api = runnerDescription.property("X-Plasma-API").toString();
|
||||
prepScripting(path, api);
|
||||
}
|
||||
|
||||
void AbstractRunnerPrivate::prepScripting(const QString &path, const QString &api)
|
||||
{
|
||||
if (script) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete package;
|
||||
package = 0;
|
||||
|
||||
if (api.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
package = new Package(PluginLoader::self()->loadPackage("Plasma/Runner", api));
|
||||
package->setPath(path);
|
||||
|
||||
if (!package->isValid()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Invalid Runner package at" << path;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
script = Plasma::loadScriptEngine(api, runner);
|
||||
if (!script) {
|
||||
delete package;
|
||||
package = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// put all setup routines for script here. at this point we can assume that
|
||||
// package exists and that we have a script engine
|
||||
void AbstractRunnerPrivate::setupScriptSupport()
|
||||
{
|
||||
if (!package) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "setting up script support, package is in" << package->path()
|
||||
<< ", main script is" << package->filePath("mainscript");
|
||||
#endif
|
||||
|
||||
const QString translationsPath = package->filePath("translations");
|
||||
if (!translationsPath.isEmpty()) {
|
||||
KGlobal::dirs()->addResourceDir("locale", translationsPath);
|
||||
KLocalizedString::insertCatalog(runnerDescription.pluginName());
|
||||
}
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
#include "moc_abstractrunner.cpp"
|
474
plasma/abstractrunner.h
Normal file
474
plasma/abstractrunner.h
Normal file
@ -0,0 +1,474 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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.
|
||||
*/
|
||||
|
||||
#ifndef PLASMA_ABSTRACTRUNNER_H
|
||||
#define PLASMA_ABSTRACTRUNNER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QMutex>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QIcon>
|
||||
|
||||
#include <kconfiggroup.h>
|
||||
#include <kservice.h>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
#include <plasma/querymatch.h>
|
||||
#include <plasma/runnercontext.h>
|
||||
#include <plasma/runnersyntax.h>
|
||||
#include <plasma/version.h>
|
||||
|
||||
class QAction;
|
||||
class QMimeData;
|
||||
|
||||
class KCompletion;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataEngine;
|
||||
class Package;
|
||||
class RunnerScript;
|
||||
class QueryMatch;
|
||||
class AbstractRunnerPrivate;
|
||||
|
||||
/**
|
||||
* @class AbstractRunner plasma/abstractrunner.h <Plasma/AbstractRunner>
|
||||
*
|
||||
* @short An abstract base class for Plasma Runner plugins.
|
||||
*
|
||||
* Be aware that runners have to be thread-safe. This is due to the fact that
|
||||
* each runner is executed in its own thread for each new term. Thus, a runner
|
||||
* may be executed more than once at the same time. See match() for details.
|
||||
* To let krunner expose a global shortcut for the single runner query mode, the runner
|
||||
* must set the "X-Plasma-AdvertiseSingleRunnerMode" key to true in the .desktop file
|
||||
* and set a default syntax. See setDefaultSyntax() for details.
|
||||
*
|
||||
*/
|
||||
class PLASMA_EXPORT AbstractRunner : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool matchingSuspended READ isMatchingSuspended WRITE suspendMatching NOTIFY matchingSuspended)
|
||||
Q_PROPERTY(QString id READ id)
|
||||
Q_PROPERTY(QString description READ description)
|
||||
Q_PROPERTY(QString name READ name)
|
||||
Q_PROPERTY(QIcon icon READ icon)
|
||||
public:
|
||||
/** Specifies a nominal speed for the runner */
|
||||
enum Speed {
|
||||
SlowSpeed,
|
||||
NormalSpeed
|
||||
};
|
||||
|
||||
/** Specifies a priority for the runner */
|
||||
enum Priority {
|
||||
LowestPriority = 0,
|
||||
LowPriority,
|
||||
NormalPriority,
|
||||
HighPriority,
|
||||
HighestPriority
|
||||
};
|
||||
|
||||
/** An ordered list of runners */
|
||||
typedef QList<AbstractRunner*> List;
|
||||
|
||||
virtual ~AbstractRunner();
|
||||
|
||||
/**
|
||||
* This is the main query method. It should trigger creation of
|
||||
* QueryMatch instances through RunnerContext::addMatch and
|
||||
* RunnerContext::addMatches. It is called internally by performMatch().
|
||||
*
|
||||
* If the runner can run precisely the requested term (RunnerContext::query()),
|
||||
* it should create an exact match by setting the type to RunnerContext::ExactMatch.
|
||||
* The first runner that creates a QueryMatch will be the
|
||||
* default runner. Other runner's matches will be suggested in the
|
||||
* interface. Non-exact matches should be offered via RunnerContext::PossibleMatch.
|
||||
*
|
||||
* The match will be activated via run() if the user selects it.
|
||||
*
|
||||
* Each runner is executed in its own thread. Whenever the user input changes this
|
||||
* method is called again. Thus, it needs to be thread-safe. Also, all matches need
|
||||
* to be reported once this method returns. Asynchronous runners therefore need
|
||||
* to make use of a local event loop to wait for all matches.
|
||||
*
|
||||
* It is recommended to use local status data in async runners. The simplest way is
|
||||
* to have a separate class doing all the work like so:
|
||||
*
|
||||
* \code
|
||||
* void MyFancyAsyncRunner::match( RunnerContext& context )
|
||||
* {
|
||||
* QEventLoop loop;
|
||||
* MyAsyncWorker worker( context );
|
||||
* connect( &worker, SIGNAL(finished()),
|
||||
* &loop, SLOT(quit()) );
|
||||
* worker.work();
|
||||
* loop.exec();
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Here MyAsyncWorker creates all the matches and calls RunnerContext::addMatch
|
||||
* in some internal slot. It emits the finished() signal once done which will
|
||||
* quit the loop and make the match() method return. The local status is kept
|
||||
* entirely in MyAsyncWorker which makes match() trivially thread-safe.
|
||||
*
|
||||
* If a particular match supports multiple actions, set up the corresponding
|
||||
* actions in the actionsForMatch method. Do not call any of the action methods
|
||||
* within this method!
|
||||
*
|
||||
* Execution of the correct action should be handled in the run method.
|
||||
* @caution This method needs to be thread-safe since KRunner will simply
|
||||
* start a new thread for each new term.
|
||||
*
|
||||
* @warning Returning from this method means to end execution of the runner.
|
||||
*
|
||||
* @sa run(), RunnerContext::addMatch, RunnerContext::addMatches, QueryMatch
|
||||
*/
|
||||
virtual void match(Plasma::RunnerContext &context);
|
||||
|
||||
/**
|
||||
* Triggers a call to match. This will call match() internally.
|
||||
*
|
||||
* @param context the search context used in executing this match.
|
||||
*/
|
||||
void performMatch(Plasma::RunnerContext &context);
|
||||
|
||||
/**
|
||||
* If the runner has options that the user can interact with to modify
|
||||
* what happens when run or one of the actions created in match
|
||||
* is called, the runner should return true
|
||||
*/
|
||||
bool hasRunOptions();
|
||||
|
||||
/**
|
||||
* If hasRunOptions() returns true, this method may be called to get
|
||||
* a widget displaying the options the user can interact with to modify
|
||||
* the behaviour of what happens when a given match is selected.
|
||||
*
|
||||
* @param widget the parent of the options widgets.
|
||||
*/
|
||||
virtual void createRunOptions(QWidget *widget);
|
||||
|
||||
/**
|
||||
* Called whenever an exact or possible match associated with this
|
||||
* runner is triggered.
|
||||
*
|
||||
* @param context The context in which the match is triggered, i.e. for which
|
||||
* the match was created.
|
||||
* @param match The actual match to run/execute.
|
||||
*/
|
||||
virtual void run(const Plasma::RunnerContext &context, const Plasma::QueryMatch &match);
|
||||
|
||||
/**
|
||||
* The nominal speed of the runner.
|
||||
* @see setSpeed
|
||||
*/
|
||||
Speed speed() const;
|
||||
|
||||
/**
|
||||
* The priority of the runner.
|
||||
* @see setPriority
|
||||
*/
|
||||
Priority priority() const;
|
||||
|
||||
/**
|
||||
* Returns the OR'ed value of all the Information types (as defined in RunnerContext::Type)
|
||||
* this runner is not interested in.
|
||||
* @return OR'ed value of black listed types
|
||||
*/
|
||||
RunnerContext::Types ignoredTypes() const;
|
||||
|
||||
/**
|
||||
* Sets the types this runner will ignore
|
||||
* @param types OR'ed listed of ignored types
|
||||
*/
|
||||
void setIgnoredTypes(RunnerContext::Types types);
|
||||
|
||||
/**
|
||||
* @return the user visible engine name for the Runner
|
||||
*/
|
||||
QString name() const;
|
||||
|
||||
/**
|
||||
* @return an id string for the Runner
|
||||
*/
|
||||
QString id() const;
|
||||
|
||||
/**
|
||||
* @return the description of this Runner
|
||||
*/
|
||||
QString description() const;
|
||||
|
||||
/**
|
||||
* @return the icon for this Runner
|
||||
*/
|
||||
QIcon icon() const;
|
||||
|
||||
/**
|
||||
* Accessor for the associated Package object if any.
|
||||
*
|
||||
* Note that the returned pointer is only valid for the lifetime of
|
||||
* the runner.
|
||||
*
|
||||
* @return the Package object, which may be invalid
|
||||
**/
|
||||
Package package() const;
|
||||
|
||||
/**
|
||||
* Signal runner to reload its configuration.
|
||||
*/
|
||||
virtual void reloadConfiguration();
|
||||
|
||||
/**
|
||||
* @return the syntaxes the runner has registered that it accepts and understands
|
||||
* @since 4.3
|
||||
*/
|
||||
QList<RunnerSyntax> syntaxes() const;
|
||||
|
||||
/**
|
||||
* @return the default syntax for the runner or 0 if no default syntax has been defined
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
RunnerSyntax *defaultSyntax() const;
|
||||
|
||||
/**
|
||||
* @return true if the runner is currently busy with non-interuptable work, signaling that
|
||||
* new threads should not be created for it at this time
|
||||
* @since 4.6
|
||||
*/
|
||||
bool isMatchingSuspended() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal is emitted when matching is about to commence, giving runners
|
||||
* an opportunity to prepare themselves, e.g. loading data sets or preparing
|
||||
* IPC or network connections. This method should be fast so as not to cause
|
||||
* slow downs. Things that take longer or which should be loaded once and
|
||||
* remain extant for the lifespan of the AbstractRunner should be done in init().
|
||||
* @see init()
|
||||
* @since 4.4
|
||||
*/
|
||||
void prepare();
|
||||
|
||||
/**
|
||||
* This signal is emitted when a session of matches is complete, giving runners
|
||||
* the opportunity to tear down anything set up as a result of the prepare()
|
||||
* method.
|
||||
* @since 4.4
|
||||
*/
|
||||
void teardown();
|
||||
|
||||
/**
|
||||
* Emitted when the runner enters or exits match suspension
|
||||
* @see matchingSuspended
|
||||
* @since 4.6
|
||||
*/
|
||||
void matchingSuspended(bool suspended);
|
||||
|
||||
protected:
|
||||
friend class RunnerManager;
|
||||
friend class RunnerManagerPrivate;
|
||||
|
||||
explicit AbstractRunner(QObject *parent = 0, const QString &path = QString());
|
||||
explicit AbstractRunner(const KService::Ptr service, QObject *parent = 0);
|
||||
|
||||
AbstractRunner(QObject *parent, const QVariantList &args);
|
||||
|
||||
/**
|
||||
* Sets whether or not the runner is available for match requests. Useful to
|
||||
* prevent more thread spawning when the thread is in a busy state.
|
||||
*/
|
||||
void suspendMatching(bool suspend);
|
||||
|
||||
/**
|
||||
* Provides access to the runner's configuration object.
|
||||
*/
|
||||
KConfigGroup config() const;
|
||||
|
||||
/**
|
||||
* Sets whether or not the runner has options for matches
|
||||
*/
|
||||
void setHasRunOptions(bool hasRunOptions);
|
||||
|
||||
/**
|
||||
* Sets the nominal speed of the runner. Only slow runners need
|
||||
* to call this within their constructor because the default
|
||||
* speed is NormalSpeed. Runners that use DBUS should call
|
||||
* this within their constructors.
|
||||
*/
|
||||
void setSpeed(Speed newSpeed);
|
||||
|
||||
/**
|
||||
* Sets the priority of the runner. Lower priority runners are executed
|
||||
* only after higher priority runners.
|
||||
*/
|
||||
void setPriority(Priority newPriority);
|
||||
|
||||
/**
|
||||
* A given match can have more than action that can be performed on it.
|
||||
* For example, a song match returned by a music player runner can be queued,
|
||||
* added to the playlist, or played.
|
||||
*
|
||||
* Call this method to add actions that can be performed by the runner.
|
||||
* Actions must first be added to the runner's action registry.
|
||||
* Note: execution of correct action is left up to the runner.
|
||||
*/
|
||||
virtual QList<QAction*> actionsForMatch(const Plasma::QueryMatch &match);
|
||||
|
||||
/**
|
||||
* Creates and then adds an action to the action registry.
|
||||
* AbstractRunner assumes ownership of the created action.
|
||||
*
|
||||
* @param id A unique identifier string
|
||||
* @param icon The icon to display
|
||||
* @param text The text to display
|
||||
* @return the created QAction
|
||||
*/
|
||||
QAction* addAction(const QString &id, const QIcon &icon, const QString &text);
|
||||
|
||||
/**
|
||||
* Adds an action to the runner's action registry.
|
||||
*
|
||||
* The QAction must be created within the GUI thread;
|
||||
* do not create it within the match method of AbstractRunner.
|
||||
*
|
||||
* @param id A unique identifier string
|
||||
* @param action The QAction to be stored
|
||||
*/
|
||||
void addAction(const QString &id, QAction *action);
|
||||
|
||||
/**
|
||||
* Removes the action from the action registry.
|
||||
* AbstractRunner deletes the action once removed.
|
||||
*
|
||||
* @param id The id of the action to be removed
|
||||
*/
|
||||
void removeAction(const QString &id);
|
||||
|
||||
/**
|
||||
* Returns the action associated with the id
|
||||
*/
|
||||
QAction* action(const QString &id) const;
|
||||
|
||||
/**
|
||||
* Returns all registered actions
|
||||
*/
|
||||
QHash<QString, QAction*> actions() const;
|
||||
|
||||
/**
|
||||
* Clears the action registry.
|
||||
* The action pool deletes the actions.
|
||||
*/
|
||||
void clearActions();
|
||||
|
||||
/**
|
||||
* Adds a registered syntax that this runner understands. This is used to
|
||||
* display to the user what this runner can understand and how it can be
|
||||
* used.
|
||||
*
|
||||
* @param syntax the syntax to register
|
||||
* @since 4.3
|
||||
*/
|
||||
void addSyntax(const RunnerSyntax &syntax);
|
||||
|
||||
/**
|
||||
* Set @p syntax as the default syntax for the runner; the default syntax will be
|
||||
* substituted to the empty query in single runner mode. This is also used to
|
||||
* display to the user what this runner can understand and how it can be
|
||||
* used.
|
||||
* The default syntax is automatically added to the list of registered syntaxes, there
|
||||
* is no need to add it using addSyntax.
|
||||
* Note that there can be only one default syntax; if called more than once, the last
|
||||
* call will determine the default syntax.
|
||||
* A default syntax (even trivial) is required to advertise single runner mode
|
||||
*
|
||||
* @param syntax the syntax to register and to set as default
|
||||
* @since 4.4
|
||||
**/
|
||||
void setDefaultSyntax(const RunnerSyntax &syntax);
|
||||
|
||||
/**
|
||||
* Sets the list of syntaxes; passing in an empty list effectively clears
|
||||
* the syntaxes.
|
||||
*
|
||||
* @param the syntaxes to register for this runner
|
||||
* @since 4.3
|
||||
*/
|
||||
void setSyntaxes(const QList<RunnerSyntax> &syns);
|
||||
|
||||
/**
|
||||
* Loads the given DataEngine
|
||||
*
|
||||
* Tries to load the data engine given by @p name. Each engine is
|
||||
* only loaded once, and that instance is re-used on all subsequent
|
||||
* requests.
|
||||
*
|
||||
* If the data engine was not found, an invalid data engine is returned
|
||||
* (see DataEngine::isValid()).
|
||||
*
|
||||
* Note that you should <em>not</em> delete the returned engine.
|
||||
*
|
||||
* @param name Name of the data engine to load
|
||||
* @return pointer to the data engine if it was loaded,
|
||||
* or an invalid data engine if the requested engine
|
||||
* could not be loaded
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
Q_INVOKABLE DataEngine *dataEngine(const QString &name) const;
|
||||
|
||||
/**
|
||||
* Reimplement this slot to run any initialization routines on first load.
|
||||
* By default, it calls reloadConfiguration(); for scripted Runners this
|
||||
* method also sets up the ScriptEngine.
|
||||
*/
|
||||
virtual void init();
|
||||
|
||||
/**
|
||||
* Reimplement this slot if you want your runner
|
||||
* to support serialization and drag and drop
|
||||
* @since 4.5
|
||||
*/
|
||||
virtual QMimeData *mimeDataForMatch(const Plasma::QueryMatch &match);
|
||||
|
||||
private:
|
||||
friend class RunnerScript;
|
||||
|
||||
AbstractRunnerPrivate *const d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#define K_EXPORT_PLASMA_RUNNER( libname, classname ) \
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
|
||||
K_EXPORT_PLUGIN(factory("plasma_runner_" #libname)) \
|
||||
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
|
||||
|
||||
/**
|
||||
* These plugins are Used by the plugin selector dialog to show
|
||||
* configuration options specific to this runner. These options
|
||||
* must be runner global and not pertain to a specific match.
|
||||
*/
|
||||
#define K_EXPORT_RUNNER_CONFIG( name, classname ) \
|
||||
K_PLUGIN_FACTORY(ConfigFactory, registerPlugin<classname>();) \
|
||||
K_EXPORT_PLUGIN(ConfigFactory("kcm_krunner_" #name)) \
|
||||
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
|
||||
|
||||
#endif
|
1268
plasma/applet.cpp
Normal file
1268
plasma/applet.cpp
Normal file
File diff suppressed because it is too large
Load Diff
900
plasma/applet.h
Normal file
900
plasma/applet.h
Normal file
@ -0,0 +1,900 @@
|
||||
/*
|
||||
* Copyright 2006-2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
|
||||
* 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 PLASMA_APPLET_H
|
||||
#define PLASMA_APPLET_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QIcon>
|
||||
|
||||
#include <kconfiggroup.h>
|
||||
#include <kplugininfo.h>
|
||||
#include <kshortcut.h>
|
||||
#include <kurl.h>
|
||||
|
||||
#include <plasma/configloader.h>
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/version.h>
|
||||
#include <plasma/framesvg.h>
|
||||
|
||||
class QWidget;
|
||||
|
||||
class KConfigDialog;
|
||||
class KActionCollection;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AppletPrivate;
|
||||
class Containment;
|
||||
class DataEngine;
|
||||
class Package;
|
||||
|
||||
|
||||
/**
|
||||
* @class Applet plasma/applet.h <Plasma/Applet>
|
||||
*
|
||||
* @short The base Applet class
|
||||
*
|
||||
* Applet provides several important roles for add-ons widgets in Plasma.
|
||||
*
|
||||
* First, it is the base class for the plugin system and therefore is the
|
||||
* interface to applets for host applications. It also handles the life time
|
||||
* management of data engines (e.g. all data engines accessed via
|
||||
* Applet::dataEngine(const QString&) are properly deref'd on Applet
|
||||
* destruction), background painting (allowing for consistent and complex
|
||||
* look and feel in just one line of code for applets), loading and starting
|
||||
* of scripting support for each applet, providing access to the associated
|
||||
* plasmoid package (if any) and access to configuration data.
|
||||
*
|
||||
* See techbase.kde.org for tutorials on writing Applets using this class.
|
||||
*/
|
||||
class PLASMA_EXPORT Applet : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool hasConfigurationInterface READ hasConfigurationInterface)
|
||||
Q_PROPERTY(QString name READ name WRITE setName)
|
||||
Q_PROPERTY(QString pluginName READ pluginName)
|
||||
Q_PROPERTY(QString category READ category)
|
||||
Q_PROPERTY(ImmutabilityType immutability READ immutability WRITE setImmutability)
|
||||
Q_PROPERTY(bool hasFailedToLaunch READ hasFailedToLaunch WRITE setFailedToLaunch)
|
||||
Q_PROPERTY(bool busy READ isBusy WRITE setBusy)
|
||||
Q_PROPERTY(bool configurationRequired READ configurationRequired WRITE setConfigurationRequired)
|
||||
Q_PROPERTY(bool shouldConserveResources READ shouldConserveResources)
|
||||
Q_PROPERTY(uint id READ id)
|
||||
Q_PROPERTY(BackgroundHints backgroundHints READ backgroundHints WRITE setBackgroundHints)
|
||||
Q_PROPERTY(bool userConfiguring READ isUserConfiguring)
|
||||
|
||||
public:
|
||||
typedef QList<Applet*> List;
|
||||
typedef QHash<QString, Applet*> Dict;
|
||||
|
||||
~Applet();
|
||||
|
||||
/**
|
||||
* @return the id of this applet
|
||||
*/
|
||||
uint id() const;
|
||||
|
||||
/**
|
||||
* Returns the KConfigGroup to access the applets configuration.
|
||||
*
|
||||
* This config object will write to an instance
|
||||
* specific config file named \<appletname\>\<instanceid\>rc
|
||||
* in the Plasma appdata directory.
|
||||
**/
|
||||
KConfigGroup config() const;
|
||||
|
||||
/**
|
||||
* Saves state information about this applet that will
|
||||
* be accessed when next instantiated in the restore(KConfigGroup&) method.
|
||||
*
|
||||
* This method does not need to be reimplmented by Applet
|
||||
* subclasses, but can be useful for Applet specializations
|
||||
* (such as Containment) to do so.
|
||||
*
|
||||
* Applet subclasses may instead want to reimplement saveState().
|
||||
**/
|
||||
virtual void save(KConfigGroup &group) const;
|
||||
|
||||
/**
|
||||
* Restores state information about this applet saved previously
|
||||
* in save(KConfigGroup&).
|
||||
*
|
||||
* This method does not need to be reimplmented by Applet
|
||||
* subclasses, but can be useful for Applet specializations
|
||||
* (such as Containment) to do so.
|
||||
**/
|
||||
virtual void restore(KConfigGroup &group);
|
||||
|
||||
/**
|
||||
* Returns a KConfigGroup object to be shared by all applets of this
|
||||
* type.
|
||||
*
|
||||
* This config object will write to an applet-specific config object
|
||||
* named plasma_\<appletname\>rc in the local config directory.
|
||||
*/
|
||||
KConfigGroup globalConfig() const;
|
||||
|
||||
/**
|
||||
* Returns the config skeleton object from this applet's package,
|
||||
* if any.
|
||||
*
|
||||
* @return config skeleton object, or 0 if none
|
||||
**/
|
||||
ConfigLoader *configScheme() const;
|
||||
|
||||
/**
|
||||
* Loads the given DataEngine
|
||||
*
|
||||
* Tries to load the data engine given by @p name. Each engine is
|
||||
* only loaded once, and that instance is re-used on all subsequent
|
||||
* requests.
|
||||
*
|
||||
* If the data engine was not found, an invalid data engine is returned
|
||||
* (see DataEngine::isValid()).
|
||||
*
|
||||
* Note that you should <em>not</em> delete the returned engine.
|
||||
*
|
||||
* @param name Name of the data engine to load
|
||||
* @return pointer to the data engine if it was loaded,
|
||||
* or an invalid data engine if the requested engine
|
||||
* could not be loaded
|
||||
*/
|
||||
Q_INVOKABLE DataEngine *dataEngine(const QString &name) const;
|
||||
|
||||
/**
|
||||
* Accessor for the associated Package object if any.
|
||||
* Generally, only Plasmoids come in a Package.
|
||||
*
|
||||
* @return the Package object, or 0 if none
|
||||
**/
|
||||
Package package() const;
|
||||
|
||||
/**
|
||||
* Reccomended position for a popup window like a menu or a tooltip
|
||||
* given its size
|
||||
* @param s size of the popup
|
||||
* @returns reccomended position
|
||||
*/
|
||||
QPoint popupPosition(const QSize &s) const;
|
||||
|
||||
/**
|
||||
* @since 4.4
|
||||
* Reccomended position for a popup window like a menu or a tooltip
|
||||
* given its size
|
||||
* @param s size of the popup
|
||||
* @param alignment alignment of the popup, valid flags are Qt::AlignLeft, Qt::AlignRight and Qt::AlignCenter
|
||||
* @returns reccomended position
|
||||
*/
|
||||
QPoint popupPosition(const QSize &s, Qt::AlignmentFlag alignment) const;
|
||||
|
||||
/**
|
||||
* Called when any of the geometry constraints have been updated.
|
||||
* This method calls constraintsEvent, which may be reimplemented,
|
||||
* once the Applet has been prepared for updating the constraints.
|
||||
*
|
||||
* @param constraints the type of constraints that were updated
|
||||
*/
|
||||
void updateConstraints(Plasma::Constraints constraints = Plasma::AllConstraints);
|
||||
|
||||
/**
|
||||
* Returns the current form factor the applet is being displayed in.
|
||||
*
|
||||
* @see Plasma::FormFactor
|
||||
*/
|
||||
virtual FormFactor formFactor() const;
|
||||
|
||||
/**
|
||||
* Returns the location of the scene which is displaying applet.
|
||||
*
|
||||
* @see Plasma::Location
|
||||
*/
|
||||
virtual Location location() const;
|
||||
|
||||
/**
|
||||
* @return the preferred aspect ratio mode for placement and resizing
|
||||
*/
|
||||
Plasma::AspectRatioMode aspectRatioMode() const;
|
||||
|
||||
/**
|
||||
* Sets the preferred aspect ratio mode for placement and resizing
|
||||
*/
|
||||
void setAspectRatioMode(Plasma::AspectRatioMode);
|
||||
|
||||
/**
|
||||
* Returns a list of all known applets.
|
||||
* This may skip applets based on security settings and ExcludeCategories in the application's config.
|
||||
*
|
||||
* @param category Only applets matchin this category will be returned.
|
||||
* Useful in conjunction with knownCategories.
|
||||
* If "Misc" is passed in, then applets without a
|
||||
* Categories= entry are also returned.
|
||||
* If an empty string is passed in, all applets are
|
||||
* returned.
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of applets
|
||||
**/
|
||||
static KPluginInfo::List listAppletInfo(const QString &category = QString(),
|
||||
const QString &parentApp = QString());
|
||||
|
||||
/**
|
||||
* Returns a list of all known applets associated with a certain mimetype.
|
||||
*
|
||||
* @return list of applets
|
||||
**/
|
||||
static KPluginInfo::List listAppletInfoForMimeType(const QString &mimetype);
|
||||
|
||||
/**
|
||||
* Returns a list of all known applets associated with a certain URL.
|
||||
*
|
||||
* @since 4.4
|
||||
* @return list of applets
|
||||
**/
|
||||
static KPluginInfo::List listAppletInfoForUrl(const QUrl &url);
|
||||
|
||||
/**
|
||||
* Returns a list of all the categories used by installed applets.
|
||||
*
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of categories
|
||||
* @param visibleOnly true if it should only return applets that are marked as visible
|
||||
*/
|
||||
static QStringList listCategories(const QString &parentApp = QString(),
|
||||
bool visibleOnly = true);
|
||||
|
||||
/**
|
||||
* Sets the list of custom categories that are used in addition to the default
|
||||
* set of categories known to libplasma for Applets.
|
||||
* @param categories a list of categories
|
||||
* @since 4.3
|
||||
*/
|
||||
void setCustomCategories(const QStringList &categories);
|
||||
|
||||
/**
|
||||
* @return the list of custom categories known to libplasma
|
||||
* @since 4.3
|
||||
*/
|
||||
QStringList customCategories();
|
||||
|
||||
/**
|
||||
* Attempts to load an applet from a package
|
||||
*
|
||||
* Returns a pointer to the applet if successful.
|
||||
* The caller takes responsibility for the applet, including
|
||||
* deleting it when no longer needed.
|
||||
*
|
||||
* @param path the path to the package
|
||||
* @param appletId unique ID to assign the applet, or zero to have one
|
||||
* assigned automatically.
|
||||
* @param args to send the applet extra arguments
|
||||
* @return a pointer to the loaded applet, or 0 on load failure
|
||||
* @since 4.3
|
||||
**/
|
||||
static Applet *loadPlasmoid(const QString &path, uint appletId = 0,
|
||||
const QVariantList &args = QVariantList());
|
||||
|
||||
/**
|
||||
* Get the category of the given applet
|
||||
*
|
||||
* @param applet a KPluginInfo object for the applet
|
||||
*/
|
||||
static QString category(const KPluginInfo &applet);
|
||||
|
||||
/**
|
||||
* Get the category of the given applet
|
||||
*
|
||||
* @param appletName the name of the applet
|
||||
*/
|
||||
static QString category(const QString &appletName);
|
||||
|
||||
/**
|
||||
* Returns the user-visible name for the applet, as specified in the
|
||||
* .desktop file. Can be changed with @see setName
|
||||
*
|
||||
* @return the user-visible name for the applet.
|
||||
**/
|
||||
QString name() const;
|
||||
|
||||
/**
|
||||
* Sets a custom name for this instance of the applet. E.g. a clock might
|
||||
* use the timezone as its name rather than the .desktop file
|
||||
*/
|
||||
void setName(const QString &name) const;
|
||||
|
||||
/**
|
||||
* @return the font currently set for this widget
|
||||
**/
|
||||
QFont font() const;
|
||||
|
||||
/**
|
||||
* Returns the plugin name for the applet
|
||||
*/
|
||||
QString pluginName() const;
|
||||
|
||||
/**
|
||||
* Whether the applet should conserve resources. If true, try to avoid doing stuff which
|
||||
* is computationally heavy. Try to conserve power and resources.
|
||||
*
|
||||
* @return true if it should conserve resources, false if it does not.
|
||||
*/
|
||||
bool shouldConserveResources() const;
|
||||
|
||||
/**
|
||||
* Returns the icon related to this applet
|
||||
**/
|
||||
QString icon() const;
|
||||
|
||||
/**
|
||||
* Returns the category the applet is in, as specified in the
|
||||
* .desktop file.
|
||||
*/
|
||||
QString category() const;
|
||||
|
||||
/**
|
||||
* @return The type of immutability of this applet
|
||||
*/
|
||||
ImmutabilityType immutability() const;
|
||||
|
||||
/**
|
||||
* If for some reason, the applet fails to get up on its feet (the
|
||||
* library couldn't be loaded, necessary hardware support wasn't found,
|
||||
* etc..) this method returns true
|
||||
**/
|
||||
bool hasFailedToLaunch() const;
|
||||
|
||||
/**
|
||||
* @return true if the applet is busy and is showing an indicator widget for that
|
||||
*/
|
||||
bool isBusy() const;
|
||||
|
||||
/**
|
||||
* @return true if the applet currently needs to be configured,
|
||||
* otherwise, false
|
||||
*/
|
||||
bool configurationRequired() const;
|
||||
|
||||
/**
|
||||
* @return true if this plasmoid provides a GUI configuration
|
||||
**/
|
||||
bool hasConfigurationInterface() const;
|
||||
|
||||
/**
|
||||
* Returns a list of context-related QAction instances.
|
||||
*
|
||||
* This is used e.g. within the \a DesktopView to display a
|
||||
* contextmenu.
|
||||
*
|
||||
* @return A list of actions. The default implementation returns an
|
||||
* empty list.
|
||||
**/
|
||||
virtual QList<QAction*> contextualActions();
|
||||
|
||||
/**
|
||||
* Returns the QAction with the given name from our collection
|
||||
*/
|
||||
Q_INVOKABLE QAction *action(QString name) const;
|
||||
|
||||
/**
|
||||
* Adds the action to our collection under the given name
|
||||
*/
|
||||
void addAction(QString name, QAction *action);
|
||||
|
||||
/**
|
||||
* Sets the BackgroundHints for this applet @see BackgroundHint
|
||||
*
|
||||
* @param hints the BackgroundHint combination for this applet
|
||||
*/
|
||||
void setBackgroundHints(const Plasma::BackgroundHints hint);
|
||||
|
||||
/**
|
||||
* @return BackgroundHints flags combination telling if the standard background is shown
|
||||
* and if it has a drop shadow
|
||||
*/
|
||||
Plasma::BackgroundHints backgroundHints() const;
|
||||
|
||||
/**
|
||||
* @return true if this Applet is currently being used as a Containment, false otherwise
|
||||
*/
|
||||
bool isContainment() const;
|
||||
|
||||
/**
|
||||
* @return the Containment, if any, this applet belongs to
|
||||
**/
|
||||
Containment *containment() const;
|
||||
|
||||
/**
|
||||
* Sets the global shorcut to associate with this widget.
|
||||
*/
|
||||
void setGlobalShortcut(const KShortcut &shortcut);
|
||||
|
||||
/**
|
||||
* @return the global shortcut associated with this wiget, or
|
||||
* an empty shortcut if no global shortcut is associated.
|
||||
*/
|
||||
KShortcut globalShortcut() const;
|
||||
|
||||
/**
|
||||
* @return true is there is a popup assoiated with this Applet
|
||||
* showing, such as the dialog of a PopupApplet. May be reimplemented
|
||||
* for custom popup implementations.
|
||||
*/
|
||||
virtual bool isPopupShowing() const;
|
||||
|
||||
/**
|
||||
* associate actions with this widget, including ones added after this call.
|
||||
* needed to make keyboard shortcuts work.
|
||||
*/
|
||||
virtual void addAssociatedWidget(QWidget *widget);
|
||||
|
||||
/**
|
||||
* un-associate actions from this widget, including ones added after this call.
|
||||
* needed to make keyboard shortcuts work.
|
||||
*/
|
||||
virtual void removeAssociatedWidget(QWidget *widget);
|
||||
|
||||
/**
|
||||
* @param parent the QObject this applet is parented to
|
||||
* @param serviceId the name of the .desktop file containing the
|
||||
* information about the widget
|
||||
* @param appletId a unique id used to differentiate between multiple
|
||||
* instances of the same Applet type
|
||||
*/
|
||||
explicit Applet(QObject *parent = 0, const QString &serviceId = QString(), uint appletId = 0);
|
||||
|
||||
/**
|
||||
* @param parent the QObject this applet is parented to
|
||||
* @param info the plugin information object for this Applet
|
||||
* @param appletId a unique id used to differentiate between multiple
|
||||
* instances of the same Applet type
|
||||
* @since 4.6
|
||||
*/
|
||||
explicit Applet(const KPluginInfo &info, QObject *parent = 0, uint appletId = 0);
|
||||
|
||||
/**
|
||||
* @param parent the QObject this applet is parented to
|
||||
* @param serviceId the name of the .desktop file containing the
|
||||
* information about the widget
|
||||
* @param appletId a unique id used to differentiate between multiple
|
||||
* instances of the same Applet type
|
||||
* @param args a list of strings containing two entries: the service id
|
||||
* and the applet id
|
||||
* @since 4.3
|
||||
*/
|
||||
explicit Applet(QObject *parent, const QString &serviceId, uint appletId, const QVariantList &args);
|
||||
|
||||
|
||||
/**
|
||||
* @return true if destroy() was called; useful for Applets which should avoid
|
||||
* certain tasks if they are about to be deleted permanently
|
||||
*/
|
||||
bool destroyed() const;
|
||||
|
||||
/**
|
||||
* Reimplement this method so provide a configuration interface,
|
||||
* parented to the supplied widget. Ownership of the widgets is passed
|
||||
* to the parent widget.
|
||||
*
|
||||
* Typically one would add custom pages to the config dialog @p parent
|
||||
* and then connect to the applyClicked() and okClicked() signals
|
||||
* or @p parent to react on config changes:
|
||||
*
|
||||
* @code
|
||||
* connect(parent, SIGNAL(applyClicked()), this, SLOT(myConfigAccepted()));
|
||||
* connect(parent, SIGNAL(okClicked()), this, SLOT(myConfigAccepted()));
|
||||
* @endcode
|
||||
*
|
||||
* With this approach it makes sense to store the custom pages in member
|
||||
* variables to make their fields accessible from the myConfigAccepted()
|
||||
* slot.
|
||||
*
|
||||
* Use config() to store your configuration.
|
||||
*
|
||||
* @param parent the dialog which is the parent of the configuration
|
||||
* widgets
|
||||
*/
|
||||
virtual void createConfigurationInterface(KConfigDialog *parent);
|
||||
|
||||
/**
|
||||
* Returns true if the applet is allowed to perform functions covered by the given constraint
|
||||
* eg. hasAuthorization("FileDialog") returns true if applets are allowed to show filedialogs.
|
||||
* @since 4.3
|
||||
*/
|
||||
bool hasAuthorization(const QString &constraint) const;
|
||||
|
||||
/**
|
||||
* Sets an application associated to this applet, that will be
|
||||
* regarded as a full view of what is represented in the applet
|
||||
*
|
||||
* @param string the name of the application. it can be
|
||||
* \li a name understood by KService::serviceByDesktopName
|
||||
* (e.g. "konqueror")
|
||||
* \li a command in $PATH
|
||||
* \li or an absolute path to an executable
|
||||
* @since 4.4
|
||||
*/
|
||||
void setAssociatedApplication(const QString &string);
|
||||
|
||||
/**
|
||||
* Sets a list of urls associated to this application,
|
||||
* they will be used as parameters for the associated application
|
||||
* @see setAssociatedApplication()
|
||||
*
|
||||
* @param urls
|
||||
*/
|
||||
void setAssociatedApplicationUrls(const QList<QUrl> &urls);
|
||||
|
||||
/**
|
||||
* @return the application associated to this applet
|
||||
* @since 4.4
|
||||
*/
|
||||
QString associatedApplication() const;
|
||||
|
||||
/**
|
||||
* @return the urls associated to this applet
|
||||
* @since 4.4
|
||||
*/
|
||||
QList<QUrl> associatedApplicationUrls() const;
|
||||
|
||||
/**
|
||||
* @return true if the applet has a valid associated application or urls
|
||||
* @since 4.4
|
||||
*/
|
||||
bool hasValidAssociatedApplication() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal indicates that an application launch, window
|
||||
* creation or window focus event was triggered. This is used, for instance,
|
||||
* to ensure that the Dashboard view in Plasma Desktop hides when such an event is
|
||||
* triggered by an item it is displaying.
|
||||
*/
|
||||
void releaseVisualFocus();
|
||||
|
||||
/**
|
||||
* Emitted when the user completes a transformation of the applet.
|
||||
*/
|
||||
void appletTransformedByUser();
|
||||
|
||||
/**
|
||||
* Emitted when the applet changes its own geometry or transform.
|
||||
*/
|
||||
void appletTransformedItself();
|
||||
|
||||
/**
|
||||
* Emitted when an applet has changed values in its configuration
|
||||
* and wishes for them to be saved at the next save point. As this implies
|
||||
* disk activity, this signal should be used with care.
|
||||
*
|
||||
* @note This does not need to be emitted from saveState by individual
|
||||
* applets.
|
||||
*/
|
||||
void configNeedsSaving();
|
||||
|
||||
/**
|
||||
* Emitted when activation is requested due to, for example, a global
|
||||
* keyboard shortcut. By default the wiget is given focus.
|
||||
*/
|
||||
void activate();
|
||||
|
||||
/**
|
||||
* Emitted when the user clicked on a button of the message overlay
|
||||
*
|
||||
* @see showMessage
|
||||
* @see Plasma::MessageButton
|
||||
* @since 4.3
|
||||
*/
|
||||
void messageButtonPressed(const Plasma::MessageButton button);
|
||||
|
||||
/**
|
||||
* Emitted when the applet is deleted
|
||||
*/
|
||||
void appletDeleted(Plasma::Applet *applet);
|
||||
|
||||
/**
|
||||
* Emitted when the applet status changes
|
||||
* @since 4.4
|
||||
*/
|
||||
void newStatus(Plasma::ItemStatus status);
|
||||
|
||||
/**
|
||||
* Emitted when the immutability changes
|
||||
* @since 4.4
|
||||
*/
|
||||
void immutabilityChanged(Plasma::ImmutabilityType immutable);
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Sets the immutability type for this applet (not immutable,
|
||||
* user immutable or system immutable)
|
||||
* @param immutable the new immutability type of this applet
|
||||
*/
|
||||
void setImmutability(const ImmutabilityType immutable);
|
||||
|
||||
/**
|
||||
* Destroys the applet; it will be removed nicely and deleted.
|
||||
* Its configuration will also be deleted.
|
||||
*/
|
||||
virtual void destroy();
|
||||
|
||||
/**
|
||||
* Lets the user interact with the plasmoid options.
|
||||
* Called when the user selects the configure entry
|
||||
* from the context menu.
|
||||
*
|
||||
* Unless there is good reason for overriding this method,
|
||||
* Applet subclasses should actually override createConfigurationInterface
|
||||
* instead. A good example of when this isn't plausible is
|
||||
* when using a dialog prepared by another library, such
|
||||
* as KPropertiesDialog from libkfile.
|
||||
* You probably want to call showConfigurationInterface(QWidget*)
|
||||
* with the custom widget you created to actually show your interface
|
||||
*/
|
||||
virtual void showConfigurationInterface();
|
||||
|
||||
/**
|
||||
* Actually show your custom configuration interface
|
||||
* Use this only if you reimplemented showConfigurationInterface()
|
||||
*
|
||||
* @param widget the widget representing your configuration interface
|
||||
*
|
||||
* @since 4.5
|
||||
*/
|
||||
void showConfigurationInterface(QWidget *widget);
|
||||
|
||||
/**
|
||||
* @return true when the configuration interface is being shown
|
||||
* @since 4.5
|
||||
*/
|
||||
bool isUserConfiguring() const;
|
||||
|
||||
/**
|
||||
* Sends all pending contraints updates to the applet. Will usually
|
||||
* be called automatically, but can also be called manually if needed.
|
||||
*/
|
||||
void flushPendingConstraintsEvents();
|
||||
|
||||
/**
|
||||
* This method is called once the applet is loaded and added to a Corona.
|
||||
* If the applet requires a Scene or has an particularly intensive
|
||||
* set of initialization routines to go through, consider implementing it
|
||||
* in this method instead of the constructor.
|
||||
*
|
||||
* Note: paintInterface may get called before init() depending on initialization
|
||||
* order. Painting is managed by the canvas (QGraphisScene), and may schedule a
|
||||
* paint event prior to init() being called.
|
||||
**/
|
||||
virtual void init();
|
||||
|
||||
/**
|
||||
* Called when applet configuration values have changed.
|
||||
*/
|
||||
virtual void configChanged();
|
||||
|
||||
/**
|
||||
* Shows a busy indicator that overlays the applet
|
||||
* @param busy show or hide the busy indicator
|
||||
*/
|
||||
void setBusy(bool busy);
|
||||
|
||||
/**
|
||||
* @return the list of arguments which the applet was called with
|
||||
* @since KDE4.3
|
||||
*/
|
||||
QVariantList startupArguments() const;
|
||||
|
||||
/**
|
||||
* @return the status of the applet
|
||||
* @since 4.4
|
||||
*/
|
||||
ItemStatus status() const;
|
||||
|
||||
/**
|
||||
* sets the status for this applet
|
||||
* @since 4.4
|
||||
*/
|
||||
void setStatus(const ItemStatus stat);
|
||||
|
||||
/**
|
||||
* Publishes and optionally announces this applet on the network for remote access.
|
||||
* @param methods the methods to use for announcing this applet.
|
||||
* @param resourceName the name under which this applet will be published (has to be unique
|
||||
* for each machine)
|
||||
*/
|
||||
void publish(Plasma::AnnouncementMethods methods, const QString &resourceName);
|
||||
|
||||
void unpublish();
|
||||
|
||||
bool isPublished() const;
|
||||
|
||||
/**
|
||||
* Open the application associated to this applet, if it's not set
|
||||
* but some urls are, open those urls with the proper application
|
||||
* for their mimetype
|
||||
* @see setAssociatedApplication()
|
||||
* @see setAssociatedApplicationUrls()
|
||||
* @since 4.4
|
||||
*/
|
||||
void runAssociatedApplication();
|
||||
|
||||
bool hasFocus() const;
|
||||
void setFocus(Qt::FocusReason);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This constructor is to be used with the plugin loading systems
|
||||
* found in KPluginInfo and KService. The argument list is expected
|
||||
* to have two elements: the KService service ID for the desktop entry
|
||||
* and an applet ID which must be a base 10 number.
|
||||
*
|
||||
* @param parent a QObject parent; you probably want to pass in 0
|
||||
* @param args a list of strings containing two entries: the service id
|
||||
* and the applet id
|
||||
*/
|
||||
Applet(QObject *parent, const QVariantList &args);
|
||||
|
||||
/**
|
||||
* Call this method when the applet fails to launch properly. An
|
||||
* optional reason can be provided.
|
||||
*
|
||||
* Not that all children items will be deleted when this method is
|
||||
* called. If you have pointers to these items, you will need to
|
||||
* reset them after calling this method.
|
||||
*
|
||||
* @param failed true when the applet failed, false when it succeeded
|
||||
* @param reason an optional reason to show the user why the applet
|
||||
* failed to launch
|
||||
**/
|
||||
void setFailedToLaunch(bool failed, const QString &reason = QString());
|
||||
|
||||
/**
|
||||
* When called, the Applet should write any information needed as part
|
||||
* of the Applet's running state to the configuration object in config()
|
||||
* and/or globalConfig().
|
||||
*
|
||||
* Applets that always sync their settings/state with the config
|
||||
* objects when these settings/states change do not need to reimplement
|
||||
* this method.
|
||||
**/
|
||||
virtual void saveState(KConfigGroup &config) const;
|
||||
|
||||
/**
|
||||
* Sets whether or not this applet provides a user interface for
|
||||
* configuring the applet.
|
||||
*
|
||||
* It defaults to false, and if true is passed in you should
|
||||
* also reimplement createConfigurationInterface()
|
||||
*
|
||||
* @param hasInterface whether or not there is a user interface available
|
||||
**/
|
||||
void setHasConfigurationInterface(bool hasInterface);
|
||||
|
||||
/**
|
||||
* When the applet needs to be configured before being usable, this
|
||||
* method can be called to show a standard interface prompting the user
|
||||
* to configure the applet
|
||||
*
|
||||
* @param needsConfiguring true if the applet needs to be configured,
|
||||
* or false if it doesn't
|
||||
* @param reason a translated message for the user explaining that the
|
||||
* applet needs configuring; this should note what needs
|
||||
* to be configured
|
||||
*/
|
||||
void setConfigurationRequired(bool needsConfiguring, const QString &reason = QString());
|
||||
|
||||
/**
|
||||
* Shows a message as an overlay of the applet: the message has an
|
||||
* icon, text and (optional) buttons
|
||||
*
|
||||
* @param icon the icon that will be shown
|
||||
* @param message the message string that will be shown.
|
||||
* If the message is empty nothng will be shown
|
||||
* and if there was a message already it will be hidden
|
||||
* @param buttons an OR combination of all the buttons needed
|
||||
*
|
||||
* @see Plasma::MessageButtons
|
||||
* @see messageButtonPressed
|
||||
* @since 4.3
|
||||
*/
|
||||
void showMessage(const QIcon &icon, const QString &message, const Plasma::MessageButtons buttons);
|
||||
|
||||
/**
|
||||
* Called when any of the constraints for the applet have been updated. These constraints
|
||||
* range from notifying when the applet has officially "started up" to when geometry changes
|
||||
* to when the form factor changes.
|
||||
*
|
||||
* Each constraint that has been changed is passed in the constraints flag.
|
||||
* All of the constraints and how they work is documented in the @see Plasma::Constraints
|
||||
* enumeration.
|
||||
*
|
||||
* On applet creation, this is always called prior to painting and can be used as an
|
||||
* opportunity to layout the widget, calculate sizings, etc.
|
||||
*
|
||||
* Do not call update() from this method; an update() will be triggered
|
||||
* at the appropriate time for the applet.
|
||||
*
|
||||
* @param constraints the type of constraints that were updated
|
||||
* @property constraint
|
||||
*/
|
||||
virtual void constraintsEvent(Plasma::Constraints constraints);
|
||||
|
||||
|
||||
/**
|
||||
* Reimplemented from QObject
|
||||
*/
|
||||
void timerEvent (QTimerEvent *event);
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* @internal This constructor is to be used with the Package loading system.
|
||||
*
|
||||
* @param parent a QObject parent; you probably want to pass in 0
|
||||
* @param args a list of strings containing two entries: the service id
|
||||
* and the applet id
|
||||
* @since 4.3
|
||||
*/
|
||||
Applet(const QString &packagePath, uint appletId, const QVariantList &args);
|
||||
|
||||
Q_PRIVATE_SLOT(d, void cleanUpAndDelete())
|
||||
Q_PRIVATE_SLOT(d, void configDialogFinished())
|
||||
Q_PRIVATE_SLOT(d, void updateShortcuts())
|
||||
Q_PRIVATE_SLOT(d, void publishCheckboxStateChanged(int state))
|
||||
Q_PRIVATE_SLOT(d, void globalShortcutChanged())
|
||||
Q_PRIVATE_SLOT(d, void propagateConfigChanged())
|
||||
|
||||
AppletPrivate *const d;
|
||||
|
||||
//Corona needs to access setFailedToLaunch and init
|
||||
friend class Corona;
|
||||
friend class CoronaPrivate;
|
||||
friend class Containment;
|
||||
friend class ContainmentPrivate;
|
||||
friend class AppletScript;
|
||||
friend class AppletHandle;
|
||||
friend class AppletPrivate;
|
||||
friend class AccessAppletJobPrivate;
|
||||
friend class GraphicsViewAppletPrivate;
|
||||
friend class PluginLoader;
|
||||
friend class PopupApplet;
|
||||
friend class PopupAppletPrivate;
|
||||
friend class AssociatedApplicationManager;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
/**
|
||||
* Register an applet when it is contained in a loadable module
|
||||
*/
|
||||
#define K_EXPORT_PLASMA_APPLET(libname, classname) \
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
|
||||
K_EXPORT_PLUGIN(factory("plasma_applet_" #libname)) \
|
||||
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
|
||||
|
||||
#endif // multiple inclusion guard
|
12
plasma/config-plasma.h.cmake
Normal file
12
plasma/config-plasma.h.cmake
Normal file
@ -0,0 +1,12 @@
|
||||
#cmakedefine01 ENABLE_REMOTE_WIDGETS
|
||||
|
||||
#cmakedefine01 PLASMA_NO_KDEWEBKIT
|
||||
#cmakedefine01 PLASMA_NO_SOLID
|
||||
#cmakedefine01 PLASMA_NO_KIO
|
||||
#cmakedefine01 PLASMA_NO_KUTILS
|
||||
#cmakedefine01 PLASMA_NO_GLOBAL_SHORTCUTS
|
||||
#cmakedefine01 HAVE_X11
|
||||
|
||||
/*FIXME: Only used in CMakeLists.txt, to be removed ?*/
|
||||
#cmakedefine01 PLASMA_NO_KNEWSTUFF
|
||||
#cmakedefine01 QCA2_FOUND
|
433
plasma/configloader.cpp
Normal file
433
plasma/configloader.cpp
Normal file
@ -0,0 +1,433 @@
|
||||
/*
|
||||
* Copyright 2007 Aaron Seigo <aseigo@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 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 "configloader.h"
|
||||
#include "private/configloader_p.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QFont>
|
||||
#include <QHash>
|
||||
#include <QXmlContentHandler>
|
||||
#include <QXmlInputSource>
|
||||
#include <QXmlSimpleReader>
|
||||
#include <QUrl>
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
class ConfigLoaderHandler : public QXmlDefaultHandler
|
||||
{
|
||||
public:
|
||||
ConfigLoaderHandler(ConfigLoader *config, ConfigLoaderPrivate *d);
|
||||
bool startElement(const QString &namespaceURI, const QString &localName,
|
||||
const QString &qName, const QXmlAttributes &atts);
|
||||
bool endElement(const QString &namespaceURI, const QString &localName,
|
||||
const QString &qName);
|
||||
bool characters(const QString &ch);
|
||||
|
||||
private:
|
||||
void addItem();
|
||||
void resetState();
|
||||
|
||||
ConfigLoader *m_config;
|
||||
ConfigLoaderPrivate *d;
|
||||
int m_min;
|
||||
int m_max;
|
||||
QString m_name;
|
||||
QString m_key;
|
||||
QString m_type;
|
||||
QString m_label;
|
||||
QString m_default;
|
||||
QString m_cdata;
|
||||
QString m_whatsThis;
|
||||
KConfigSkeleton::ItemEnum::Choice m_choice;
|
||||
QList<KConfigSkeleton::ItemEnum::Choice> m_enumChoices;
|
||||
bool m_haveMin;
|
||||
bool m_haveMax;
|
||||
bool m_inChoice;
|
||||
};
|
||||
|
||||
void ConfigLoaderPrivate::parse(ConfigLoader *loader, QIODevice *xml)
|
||||
{
|
||||
QXmlInputSource source(xml);
|
||||
QXmlSimpleReader reader;
|
||||
ConfigLoaderHandler handler(loader, this);
|
||||
reader.setContentHandler(&handler);
|
||||
reader.parse(&source, false);
|
||||
}
|
||||
|
||||
ConfigLoaderHandler::ConfigLoaderHandler(ConfigLoader *config, ConfigLoaderPrivate *d)
|
||||
: QXmlDefaultHandler(),
|
||||
m_config(config),
|
||||
d(d)
|
||||
{
|
||||
resetState();
|
||||
}
|
||||
|
||||
bool ConfigLoaderHandler::startElement(const QString &namespaceURI, const QString &localName,
|
||||
const QString &qName, const QXmlAttributes &attrs)
|
||||
{
|
||||
Q_UNUSED(namespaceURI)
|
||||
Q_UNUSED(qName)
|
||||
|
||||
// kDebug() << "ConfigLoaderHandler::startElement(" << localName << qName;
|
||||
int numAttrs = attrs.count();
|
||||
QString tag = localName.toLower();
|
||||
if (tag == "group") {
|
||||
QString group;
|
||||
for (int i = 0; i < numAttrs; ++i) {
|
||||
QString name = attrs.localName(i).toLower();
|
||||
if (name == "name") {
|
||||
//kDebug() << "set group to" << attrs.value(i);
|
||||
group = attrs.value(i);
|
||||
}
|
||||
}
|
||||
if (group.isEmpty()) {
|
||||
group = d->baseGroup;
|
||||
} else {
|
||||
d->groups.append(group);
|
||||
if (!d->baseGroup.isEmpty()) {
|
||||
group = d->baseGroup + '\x1d' + group;
|
||||
}
|
||||
}
|
||||
m_config->setCurrentGroup(group);
|
||||
} else if (tag == "entry") {
|
||||
for (int i = 0; i < numAttrs; ++i) {
|
||||
QString name = attrs.localName(i).toLower();
|
||||
if (name == "name") {
|
||||
m_name = attrs.value(i).trimmed();
|
||||
} else if (name == "type") {
|
||||
m_type = attrs.value(i).toLower();
|
||||
} else if (name == "key") {
|
||||
m_key = attrs.value(i).trimmed();
|
||||
}
|
||||
}
|
||||
} else if (tag == "choice") {
|
||||
m_choice.name.clear();
|
||||
m_choice.label.clear();
|
||||
m_choice.whatsThis.clear();
|
||||
for (int i = 0; i < numAttrs; ++i) {
|
||||
QString name = attrs.localName(i).toLower();
|
||||
if (name == "name") {
|
||||
m_choice.name = attrs.value(i);
|
||||
}
|
||||
}
|
||||
m_inChoice = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigLoaderHandler::characters(const QString &ch)
|
||||
{
|
||||
m_cdata.append(ch);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigLoaderHandler::endElement(const QString &namespaceURI,
|
||||
const QString &localName, const QString &qName)
|
||||
{
|
||||
Q_UNUSED(namespaceURI)
|
||||
Q_UNUSED(qName)
|
||||
|
||||
// kDebug() << "ConfigLoaderHandler::endElement(" << localName << qName;
|
||||
const QString tag = localName.toLower();
|
||||
if (tag == "entry") {
|
||||
addItem();
|
||||
resetState();
|
||||
} else if (tag == "label") {
|
||||
if (m_inChoice) {
|
||||
m_choice.label = m_cdata.trimmed();
|
||||
} else {
|
||||
m_label = m_cdata.trimmed();
|
||||
}
|
||||
} else if (tag == "whatsthis") {
|
||||
if (m_inChoice) {
|
||||
m_choice.whatsThis = m_cdata.trimmed();
|
||||
} else {
|
||||
m_whatsThis = m_cdata.trimmed();
|
||||
}
|
||||
} else if (tag == "default") {
|
||||
m_default = m_cdata.trimmed();
|
||||
} else if (tag == "min") {
|
||||
m_min = m_cdata.toInt(&m_haveMin);
|
||||
} else if (tag == "max") {
|
||||
m_max = m_cdata.toInt(&m_haveMax);
|
||||
} else if (tag == "choice") {
|
||||
m_enumChoices.append(m_choice);
|
||||
m_inChoice = false;
|
||||
}
|
||||
|
||||
m_cdata.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfigLoaderHandler::addItem()
|
||||
{
|
||||
if (m_name.isEmpty()) {
|
||||
if (m_key.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_name = m_key;
|
||||
}
|
||||
|
||||
m_name.remove(' ');
|
||||
|
||||
KConfigSkeletonItem *item = 0;
|
||||
|
||||
if (m_type == "bool") {
|
||||
bool defaultValue = m_default.toLower() == "true";
|
||||
item = m_config->addItemBool(m_name, *d->newBool(), defaultValue, m_key);
|
||||
} else if (m_type == "color") {
|
||||
item = m_config->addItemColor(m_name, *d->newColor(), QColor(m_default), m_key);
|
||||
} else if (m_type == "datetime") {
|
||||
item = m_config->addItemDateTime(m_name, *d->newDateTime(),
|
||||
QDateTime::fromString(m_default), m_key);
|
||||
} else if (m_type == "enum") {
|
||||
m_key = (m_key.isEmpty()) ? m_name : m_key;
|
||||
KConfigSkeleton::ItemEnum *enumItem =
|
||||
new KConfigSkeleton::ItemEnum(m_config->currentGroup(),
|
||||
m_key, *d->newInt(),
|
||||
m_enumChoices,
|
||||
m_default.toUInt());
|
||||
m_config->addItem(enumItem, m_name);
|
||||
item = enumItem;
|
||||
} else if (m_type == "font") {
|
||||
item = m_config->addItemFont(m_name, *d->newFont(), QFont(m_default), m_key);
|
||||
} else if (m_type == "int") {
|
||||
KConfigSkeleton::ItemInt *intItem = m_config->addItemInt(m_name, *d->newInt(),
|
||||
m_default.toInt(), m_key);
|
||||
|
||||
if (m_haveMin) {
|
||||
intItem->setMinValue(m_min);
|
||||
}
|
||||
|
||||
if (m_haveMax) {
|
||||
intItem->setMaxValue(m_max);
|
||||
}
|
||||
|
||||
item = intItem;
|
||||
} else if (m_type == "password") {
|
||||
item = m_config->addItemPassword(m_name, *d->newString(), m_default, m_key);
|
||||
} else if (m_type == "path") {
|
||||
item = m_config->addItemPath(m_name, *d->newString(), m_default, m_key);
|
||||
} else if (m_type == "string") {
|
||||
item = m_config->addItemString(m_name, *d->newString(), m_default, m_key);
|
||||
} else if (m_type == "stringlist") {
|
||||
//FIXME: the split() is naive and will break on lists with ,'s in them
|
||||
item = m_config->addItemStringList(m_name, *d->newStringList(),
|
||||
m_default.split(','), m_key);
|
||||
} else if (m_type == "uint") {
|
||||
KConfigSkeleton::ItemUInt *uintItem =
|
||||
m_config->addItemUInt(m_name, *d->newUint(), m_default.toUInt(), m_key);
|
||||
if (m_haveMin) {
|
||||
uintItem->setMinValue(m_min);
|
||||
}
|
||||
if (m_haveMax) {
|
||||
uintItem->setMaxValue(m_max);
|
||||
}
|
||||
item = uintItem;
|
||||
} else if (m_type == "url") {
|
||||
m_key = (m_key.isEmpty()) ? m_name : m_key;
|
||||
KConfigSkeleton::ItemUrl *urlItem =
|
||||
new KConfigSkeleton::ItemUrl(m_config->currentGroup(),
|
||||
m_key, *d->newUrl(),
|
||||
QUrl::fromUserInput(m_default));
|
||||
m_config->addItem(urlItem, m_name);
|
||||
item = urlItem;
|
||||
} else if (m_type == "double") {
|
||||
KConfigSkeleton::ItemDouble *doubleItem = m_config->addItemDouble(m_name,
|
||||
*d->newDouble(), m_default.toDouble(), m_key);
|
||||
if (m_haveMin) {
|
||||
doubleItem->setMinValue(m_min);
|
||||
}
|
||||
if (m_haveMax) {
|
||||
doubleItem->setMaxValue(m_max);
|
||||
}
|
||||
item = doubleItem;
|
||||
} else if (m_type == "intlist") {
|
||||
QStringList tmpList = m_default.split(',');
|
||||
QList<int> defaultList;
|
||||
foreach (const QString &tmp, tmpList) {
|
||||
defaultList.append(tmp.toInt());
|
||||
}
|
||||
item = m_config->addItemIntList(m_name, *d->newIntList(), defaultList, m_key);
|
||||
} else if (m_type == "longlong") {
|
||||
KConfigSkeleton::ItemLongLong *longlongItem = m_config->addItemLongLong(m_name,
|
||||
*d->newLongLong(), m_default.toLongLong(), m_key);
|
||||
if (m_haveMin) {
|
||||
longlongItem->setMinValue(m_min);
|
||||
}
|
||||
if (m_haveMax) {
|
||||
longlongItem->setMaxValue(m_max);
|
||||
}
|
||||
item = longlongItem;
|
||||
/* No addItemPathList in KConfigSkeleton ?
|
||||
} else if (m_type == "PathList") {
|
||||
//FIXME: the split() is naive and will break on lists with ,'s in them
|
||||
item = m_config->addItemPathList(m_name, *d->newStringList(), m_default.split(","), m_key);
|
||||
*/
|
||||
} else if (m_type == "point") {
|
||||
QPoint defaultPoint;
|
||||
QStringList tmpList = m_default.split(',');
|
||||
if (tmpList.size() >= 2) {
|
||||
defaultPoint.setX(tmpList[0].toInt());
|
||||
defaultPoint.setY(tmpList[1].toInt());
|
||||
}
|
||||
item = m_config->addItemPoint(m_name, *d->newPoint(), defaultPoint, m_key);
|
||||
} else if (m_type == "rect") {
|
||||
QRect defaultRect;
|
||||
QStringList tmpList = m_default.split(',');
|
||||
if (tmpList.size() >= 4) {
|
||||
defaultRect.setCoords(tmpList[0].toInt(), tmpList[1].toInt(),
|
||||
tmpList[2].toInt(), tmpList[3].toInt());
|
||||
}
|
||||
item = m_config->addItemRect(m_name, *d->newRect(), defaultRect, m_key);
|
||||
} else if (m_type == "size") {
|
||||
QSize defaultSize;
|
||||
QStringList tmpList = m_default.split(',');
|
||||
if (tmpList.size() >= 2) {
|
||||
defaultSize.setWidth(tmpList[0].toInt());
|
||||
defaultSize.setHeight(tmpList[1].toInt());
|
||||
}
|
||||
item = m_config->addItemSize(m_name, *d->newSize(), defaultSize, m_key);
|
||||
} else if (m_type == "ulonglong") {
|
||||
KConfigSkeleton::ItemULongLong *ulonglongItem =
|
||||
m_config->addItemULongLong(m_name, *d->newULongLong(), m_default.toULongLong(), m_key);
|
||||
if (m_haveMin) {
|
||||
ulonglongItem->setMinValue(m_min);
|
||||
}
|
||||
if (m_haveMax) {
|
||||
ulonglongItem->setMaxValue(m_max);
|
||||
}
|
||||
item = ulonglongItem;
|
||||
/* No addItemUrlList in KConfigSkeleton ?
|
||||
} else if (m_type == "urllist") {
|
||||
//FIXME: the split() is naive and will break on lists with ,'s in them
|
||||
QStringList tmpList = m_default.split(",");
|
||||
QList<QUrl> defaultList;
|
||||
foreach (const QString& tmp, tmpList) {
|
||||
defaultList.append(KUrl(tmp));
|
||||
}
|
||||
item = m_config->addItemUrlList(m_name, *d->newUrlList(), defaultList, m_key);*/
|
||||
}
|
||||
|
||||
if (item) {
|
||||
item->setLabel(m_label);
|
||||
item->setWhatsThis(m_whatsThis);
|
||||
d->keysToNames.insert(item->group() + item->key(), item->name());
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigLoaderHandler::resetState()
|
||||
{
|
||||
m_haveMin = false;
|
||||
m_min = 0;
|
||||
m_haveMax = false;
|
||||
m_max = 0;
|
||||
m_name.clear();
|
||||
m_type.clear();
|
||||
m_label.clear();
|
||||
m_default.clear();
|
||||
m_key.clear();
|
||||
m_whatsThis.clear();
|
||||
m_enumChoices.clear();
|
||||
m_inChoice = false;
|
||||
}
|
||||
|
||||
ConfigLoader::ConfigLoader(const QString &configFile, QIODevice *xml, QObject *parent)
|
||||
: KConfigSkeleton(configFile, parent),
|
||||
d(new ConfigLoaderPrivate)
|
||||
{
|
||||
d->parse(this, xml);
|
||||
}
|
||||
|
||||
ConfigLoader::ConfigLoader(KSharedConfigPtr config, QIODevice *xml, QObject *parent)
|
||||
: KConfigSkeleton(config, parent),
|
||||
d(new ConfigLoaderPrivate)
|
||||
{
|
||||
d->parse(this, xml);
|
||||
}
|
||||
|
||||
//FIXME: obviously this is broken and should be using the group as the root,
|
||||
// but KConfigSkeleton does not currently support this. it will eventually though,
|
||||
// at which point this can be addressed properly
|
||||
ConfigLoader::ConfigLoader(const KConfigGroup *config, QIODevice *xml, QObject *parent)
|
||||
: KConfigSkeleton(KSharedConfig::openConfig(config->config()->name()), parent),
|
||||
d(new ConfigLoaderPrivate)
|
||||
{
|
||||
KConfigGroup group = config->parent();
|
||||
d->baseGroup = config->name();
|
||||
while (group.isValid() && group.name() != "<default>") {
|
||||
d->baseGroup = group.name() + '\x1d' + d->baseGroup;
|
||||
group = group.parent();
|
||||
}
|
||||
d->parse(this, xml);
|
||||
}
|
||||
|
||||
ConfigLoader::~ConfigLoader()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
KConfigSkeletonItem *ConfigLoader::findItem(const QString &group, const QString &key)
|
||||
{
|
||||
return KConfigSkeleton::findItem(d->keysToNames[group + key]);
|
||||
}
|
||||
|
||||
KConfigSkeletonItem *ConfigLoader::findItemByName(const QString &name)
|
||||
{
|
||||
return KConfigSkeleton::findItem(name);
|
||||
}
|
||||
|
||||
QVariant ConfigLoader::property(const QString &name)
|
||||
{
|
||||
KConfigSkeletonItem *item = KConfigSkeleton::findItem(name);
|
||||
|
||||
if (item) {
|
||||
return item->property();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ConfigLoader::hasGroup(const QString &group) const
|
||||
{
|
||||
return d->groups.contains(group);
|
||||
}
|
||||
|
||||
QStringList ConfigLoader::groupList() const
|
||||
{
|
||||
return d->groups;
|
||||
}
|
||||
|
||||
void ConfigLoader::usrWriteConfig()
|
||||
{
|
||||
if (d->saveDefaults) {
|
||||
KConfigSkeletonItem::List itemList = items();
|
||||
for(int i = 0; i < itemList.size(); i++) {
|
||||
KConfigGroup cg(config(), itemList.at(i)->group());
|
||||
cg.writeEntry(itemList.at(i)->key(), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
154
plasma/configloader.h
Normal file
154
plasma/configloader.h
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2007 Aaron Seigo <aseigo@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 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 PLASMA_CONFIGLOADER_H
|
||||
#define PLASMA_CONFIGLOADER_H
|
||||
|
||||
#include <kconfiggroup.h>
|
||||
#include <kconfigskeleton.h>
|
||||
#include <ksharedconfig.h>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
/**
|
||||
* @class ConfigLoader plasma/configloader.h <Plasma/ConfigLoader>
|
||||
*
|
||||
* @short A KConfigSkeleton that populates itself based on KConfigXT XML
|
||||
*
|
||||
* This class allows one to ship an XML file and reconstitute it into a
|
||||
* KConfigSkeleton object at runtime. Common usage might look like this:
|
||||
*
|
||||
* \code
|
||||
* QFile file(xmlFilePath);
|
||||
* Plasma::ConfigLoader appletConfig(configFilePath, &file);
|
||||
* \endcode
|
||||
*
|
||||
* Alternatively, any QIODevice may be used in place of QFile in the
|
||||
* example above.
|
||||
*
|
||||
* Currently the following data types are supported:
|
||||
*
|
||||
* @li bools
|
||||
* @li colors
|
||||
* @li datetimes
|
||||
* @li enumerations
|
||||
* @li fonts
|
||||
* @li ints
|
||||
* @li passwords
|
||||
* @li paths
|
||||
* @li strings
|
||||
* @li stringlists
|
||||
* @li uints
|
||||
* @li urls
|
||||
* @li doubles
|
||||
* @li int lists
|
||||
* @li longlongs
|
||||
* @li path lists
|
||||
* @li points
|
||||
* @li rects
|
||||
* @li sizes
|
||||
* @li ulonglongs
|
||||
* @li url lists
|
||||
**/
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ConfigLoaderPrivate;
|
||||
|
||||
class PLASMA_EXPORT ConfigLoader : public KConfigSkeleton
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Creates a KConfigSkeleton populated using the definition found in
|
||||
* the XML data passed in.
|
||||
*
|
||||
* @param configFile path to the configuration file to use
|
||||
* @param xml the xml data; must be valid KConfigXT data
|
||||
* @param parent optional QObject parent
|
||||
**/
|
||||
ConfigLoader(const QString &configFile, QIODevice *xml, QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* Creates a KConfigSkeleton populated using the definition found in
|
||||
* the XML data passed in.
|
||||
*
|
||||
* @param config the configuration object to use
|
||||
* @param xml the xml data; must be valid KConfigXT data
|
||||
* @param parent optional QObject parent
|
||||
**/
|
||||
ConfigLoader(KSharedConfigPtr config, QIODevice *xml, QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* Creates a KConfigSkeleton populated using the definition found in
|
||||
* the XML data passed in.
|
||||
*
|
||||
* @param config the group to use as the root for configuration items
|
||||
* @param xml the xml data; must be valid KConfigXT data
|
||||
* @param parent optional QObject parent
|
||||
**/
|
||||
ConfigLoader(const KConfigGroup *config, QIODevice *xml, QObject *parent = 0);
|
||||
~ConfigLoader();
|
||||
|
||||
/**
|
||||
* Finds the item for the given group and key.
|
||||
*
|
||||
* @param group the group in the config file to look in
|
||||
* @param key the configuration key to find
|
||||
* @return the associated KConfigSkeletonItem, or 0 if none
|
||||
*/
|
||||
KConfigSkeletonItem *findItem(const QString &group, const QString &key);
|
||||
|
||||
/**
|
||||
* Finds an item by its name
|
||||
*/
|
||||
KConfigSkeletonItem *findItemByName(const QString &name);
|
||||
|
||||
/**
|
||||
* Returns the property (variantized value) of the named item
|
||||
*/
|
||||
QVariant property(const QString &name);
|
||||
|
||||
/**
|
||||
* Check to see if a group exists
|
||||
*
|
||||
* @param group the name of the group to check for
|
||||
* @return true if the group exists, or false if it does not
|
||||
*/
|
||||
bool hasGroup(const QString &group) const;
|
||||
|
||||
/**
|
||||
* @return the list of groups defined by the XML
|
||||
*/
|
||||
QStringList groupList() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Hack used to force writing when no default exists in config file.
|
||||
*/
|
||||
void usrWriteConfig();
|
||||
|
||||
private:
|
||||
friend class Service;
|
||||
ConfigLoaderPrivate * const d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif //multiple inclusion guard
|
932
plasma/containment.cpp
Normal file
932
plasma/containment.cpp
Normal file
@ -0,0 +1,932 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
* Copyright 2009 Chani Armitage <chani@kde.org>
|
||||
* Copyright 2012 Marco Martin <notmart@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 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 "containment.h"
|
||||
#include "private/containment_p.h"
|
||||
|
||||
#include "config-plasma.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QFile>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QMimeData>
|
||||
#include <QPainter>
|
||||
#include <QStyleOptionGraphicsItem>
|
||||
#include <qtemporaryfile.h>
|
||||
|
||||
#include <kaction.h>
|
||||
#include <kcoreauthorized.h>
|
||||
#include <kmenu.h>
|
||||
#include <kmessagebox.h>
|
||||
#include <qmimedatabase.h>
|
||||
#include <kservicetypetrader.h>
|
||||
|
||||
#include <kwindowsystem.h>
|
||||
|
||||
#if !PLASMA_NO_KIO
|
||||
#include "kio/jobclasses.h" // for KIO::JobFlags
|
||||
#include "kio/job.h"
|
||||
#include "kio/scheduler.h"
|
||||
#endif
|
||||
|
||||
#include "containmentactions.h"
|
||||
#include "containmentactionspluginsconfig.h"
|
||||
#include "corona.h"
|
||||
#include "pluginloader.h"
|
||||
#include "svg.h"
|
||||
|
||||
#include "remote/accessappletjob.h"
|
||||
#include "remote/accessmanager.h"
|
||||
|
||||
#include "private/applet_p.h"
|
||||
#include "private/containmentactionspluginsconfig_p.h"
|
||||
|
||||
#include "plasma/plasma.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
Containment::Containment(QObject *parent,
|
||||
const QString &serviceId,
|
||||
uint containmentId)
|
||||
: Applet(parent, serviceId, containmentId),
|
||||
d(new ContainmentPrivate(this))
|
||||
{
|
||||
// WARNING: do not access config() OR globalConfig() in this method!
|
||||
// that requires a scene, which is not available at this point
|
||||
setBackgroundHints(NoBackground);
|
||||
setContainmentType(CustomContainment);
|
||||
setHasConfigurationInterface(false);
|
||||
}
|
||||
|
||||
Containment::Containment(QObject *parent, const QVariantList &args)
|
||||
: Applet(parent, args),
|
||||
d(new ContainmentPrivate(this))
|
||||
{
|
||||
// WARNING: do not access config() OR globalConfig() in this method!
|
||||
// that requires a scene, which is not available at this point
|
||||
setBackgroundHints(NoBackground);
|
||||
setHasConfigurationInterface(false);
|
||||
}
|
||||
|
||||
Containment::Containment(const QString &packagePath, uint appletId, const QVariantList &args)
|
||||
: Applet(packagePath, appletId, args),
|
||||
d(new ContainmentPrivate(this))
|
||||
{
|
||||
// WARNING: do not access config() OR globalConfig() in this method!
|
||||
// that requires a scene, which is not available at this point
|
||||
setBackgroundHints(NoBackground);
|
||||
setHasConfigurationInterface(false);
|
||||
}
|
||||
|
||||
Containment::~Containment()
|
||||
{
|
||||
// Applet touches our dptr if we are a containment and is the superclass (think of dtors)
|
||||
// so we reset this as we exit the building
|
||||
Applet::d->isContainment = false;
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Containment::init()
|
||||
{
|
||||
Applet::init();
|
||||
if (!isContainment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->type == NoContainmentType) {
|
||||
setContainmentType(DesktopContainment);
|
||||
}
|
||||
|
||||
//connect actions
|
||||
ContainmentPrivate::addDefaultActions(d->actions(), this);
|
||||
bool unlocked = immutability() == Mutable;
|
||||
|
||||
//fix the text of the actions that need name()
|
||||
//btw, do we really want to use name() when it's a desktopcontainment?
|
||||
QAction *closeApplet = action("remove");
|
||||
if (closeApplet) {
|
||||
closeApplet->setText(i18nc("%1 is the name of the applet", "Remove this %1", name()));
|
||||
}
|
||||
|
||||
QAction *configAction = action("configure");
|
||||
if (configAction) {
|
||||
configAction->setText(i18nc("%1 is the name of the applet", "%1 Settings", name()));
|
||||
}
|
||||
|
||||
QAction *appletBrowserAction = action("add widgets");
|
||||
if (appletBrowserAction) {
|
||||
appletBrowserAction->setVisible(unlocked);
|
||||
appletBrowserAction->setEnabled(unlocked);
|
||||
connect(appletBrowserAction, SIGNAL(triggered()), this, SLOT(triggerShowAddWidgets()));
|
||||
}
|
||||
|
||||
QAction *act = action("next applet");
|
||||
if (act) {
|
||||
connect(act, SIGNAL(triggered()), this, SLOT(focusNextApplet()));
|
||||
}
|
||||
|
||||
act = action("previous applet");
|
||||
if (act) {
|
||||
connect(act, SIGNAL(triggered()), this, SLOT(focusPreviousApplet()));
|
||||
}
|
||||
|
||||
if (immutability() != SystemImmutable && corona()) {
|
||||
QAction *lockDesktopAction = corona()->action("lock widgets");
|
||||
//keep a pointer so nobody notices it moved to corona
|
||||
if (lockDesktopAction) {
|
||||
d->actions()->addAction("lock widgets", lockDesktopAction);
|
||||
}
|
||||
}
|
||||
if (d->type != PanelContainment && d->type != CustomPanelContainment) {
|
||||
if (corona()) {
|
||||
//FIXME this is just here because of the darn keyboard shortcut :/
|
||||
act = corona()->action("manage activities");
|
||||
if (act) {
|
||||
d->actions()->addAction("manage activities", act);
|
||||
}
|
||||
//a stupid hack to make this one's keyboard shortcut work
|
||||
act = corona()->action("configure shortcuts");
|
||||
if (act) {
|
||||
d->actions()->addAction("configure shortcuts", act);
|
||||
}
|
||||
}
|
||||
|
||||
if (d->type == DesktopContainment) {
|
||||
addToolBoxAction(action("add widgets"));
|
||||
|
||||
//TODO: do we need some way to allow this be overridden?
|
||||
// it's always available because shells rely on this
|
||||
// to offer their own custom configuration as well
|
||||
QAction *configureContainment = action("configure");
|
||||
if (configureContainment) {
|
||||
addToolBoxAction(configureContainment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// helper function for sorting the list of applets
|
||||
bool appletConfigLessThan(const KConfigGroup &c1, const KConfigGroup &c2)
|
||||
{
|
||||
QPointF p1 = c1.readEntry("geometry", QRectF()).topLeft();
|
||||
QPointF p2 = c2.readEntry("geometry", QRectF()).topLeft();
|
||||
|
||||
if (!qFuzzyCompare(p1.x(), p2.x())) {
|
||||
if (QApplication::layoutDirection() == Qt::RightToLeft) {
|
||||
return p1.x() > p2.x();
|
||||
}
|
||||
|
||||
return p1.x() < p2.x();
|
||||
}
|
||||
|
||||
return qFuzzyCompare(p1.y(), p2.y()) || p1.y() < p2.y();
|
||||
}
|
||||
|
||||
void Containment::restore(KConfigGroup &group)
|
||||
{
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "!!!!!!!!!!!!initConstraints" << group.name() << d->type;
|
||||
kDebug() << " location:" << group.readEntry("location", (int)d->location);
|
||||
kDebug() << " geom:" << group.readEntry("geometry", geometry());
|
||||
kDebug() << " formfactor:" << group.readEntry("formfactor", (int)d->formFactor);
|
||||
kDebug() << " screen:" << group.readEntry("screen", d->screen);
|
||||
#endif
|
||||
*/
|
||||
if (!isContainment()) {
|
||||
Applet::restore(group);
|
||||
return;
|
||||
}
|
||||
|
||||
setLocation((Plasma::Location)group.readEntry("location", (int)d->location));
|
||||
setFormFactor((Plasma::FormFactor)group.readEntry("formfactor", (int)d->formFactor));
|
||||
//kDebug() << "setScreen from restore";
|
||||
d->lastScreen = group.readEntry("lastScreen", d->lastScreen);
|
||||
d->lastDesktop = group.readEntry("lastDesktop", d->lastDesktop);
|
||||
d->setScreen(group.readEntry("screen", d->screen), group.readEntry("desktop", d->desktop), false);
|
||||
d->activityId = group.readEntry("activityId", QString());
|
||||
|
||||
flushPendingConstraintsEvents();
|
||||
restoreContents(group);
|
||||
setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
|
||||
|
||||
setWallpaper(group.readEntry("wallpaperplugin", ContainmentPrivate::defaultWallpaper),
|
||||
group.readEntry("wallpaperpluginmode", ContainmentPrivate::defaultWallpaperMode));
|
||||
|
||||
KConfigGroup cfg;
|
||||
if (containmentType() == PanelContainment || containmentType() == CustomPanelContainment) {
|
||||
//don't let global desktop actions conflict with panels
|
||||
//this also prevents panels from sharing config with each other
|
||||
//but the panels aren't configurable anyways, and I doubt that'll change.
|
||||
d->containmentActionsSource = ContainmentPrivate::Local;
|
||||
cfg = KConfigGroup(&group, "ActionPlugins");
|
||||
} else {
|
||||
const QString source = group.readEntry("ActionPluginsSource", QString());
|
||||
if (source == "Global") {
|
||||
cfg = KConfigGroup(corona()->config(), "ActionPlugins");
|
||||
d->containmentActionsSource = ContainmentPrivate::Global;
|
||||
} else if (source == "Activity") {
|
||||
cfg = KConfigGroup(corona()->config(), "Activities");
|
||||
cfg = KConfigGroup(&cfg, d->activityId);
|
||||
cfg = KConfigGroup(&cfg, "ActionPlugins");
|
||||
d->containmentActionsSource = ContainmentPrivate::Activity;
|
||||
} else if (source == "Local") {
|
||||
cfg = group;
|
||||
d->containmentActionsSource = ContainmentPrivate::Local;
|
||||
} else {
|
||||
//default to global
|
||||
//but, if there is no global config, try copying it from local.
|
||||
cfg = KConfigGroup(corona()->config(), "ActionPlugins");
|
||||
if (!cfg.exists()) {
|
||||
cfg = KConfigGroup(&group, "ActionPlugins");
|
||||
}
|
||||
d->containmentActionsSource = ContainmentPrivate::Global;
|
||||
group.writeEntry("ActionPluginsSource", "Global");
|
||||
}
|
||||
}
|
||||
|
||||
//kDebug() << cfg.keyList();
|
||||
if (cfg.exists()) {
|
||||
foreach (const QString &key, cfg.keyList()) {
|
||||
//kDebug() << "loading" << key;
|
||||
setContainmentActions(key, cfg.readEntry(key, QString()));
|
||||
}
|
||||
} else { //shell defaults
|
||||
ContainmentActionsPluginsConfig conf = corona()->containmentActionsDefaults(d->type);
|
||||
//steal the data directly, for efficiency
|
||||
QHash<QString,QString> defaults = conf.d->plugins;
|
||||
for (QHash<QString,QString>::const_iterator it = defaults.constBegin(),
|
||||
end = defaults.constEnd(); it != end; ++it) {
|
||||
setContainmentActions(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Containment" << id() <<
|
||||
#endif
|
||||
"screen" << screen() <<
|
||||
"geometry is" << geometry() <<
|
||||
"wallpaper" << ((d->wallpaper) ? d->wallpaper->pluginName() : QString()) <<
|
||||
"wallpaper mode" << wallpaperMode() <<
|
||||
"config entries" << group.entryMap();
|
||||
*/
|
||||
}
|
||||
|
||||
void Containment::save(KConfigGroup &g) const
|
||||
{
|
||||
if (Applet::d->transient) {
|
||||
return;
|
||||
}
|
||||
|
||||
KConfigGroup group = g;
|
||||
if (!group.isValid()) {
|
||||
group = config();
|
||||
}
|
||||
|
||||
// locking is saved in Applet::save
|
||||
Applet::save(group);
|
||||
|
||||
if (!isContainment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
group.writeEntry("screen", d->screen);
|
||||
group.writeEntry("lastScreen", d->lastScreen);
|
||||
group.writeEntry("desktop", d->desktop);
|
||||
group.writeEntry("lastDesktop", d->lastDesktop);
|
||||
group.writeEntry("formfactor", (int)d->formFactor);
|
||||
group.writeEntry("location", (int)d->location);
|
||||
group.writeEntry("activityId", d->activityId);
|
||||
|
||||
|
||||
group.writeEntry("wallpaperplugin", d->wallpaper);
|
||||
group.writeEntry("wallpaperpluginmode", d->wallpaperMode);
|
||||
|
||||
//TODO: the wallpaper implementation must know it has to save at this point
|
||||
|
||||
saveContents(group);
|
||||
}
|
||||
|
||||
void Containment::saveContents(KConfigGroup &group) const
|
||||
{
|
||||
KConfigGroup applets(&group, "Applets");
|
||||
foreach (const Applet *applet, d->applets) {
|
||||
KConfigGroup appletConfig(&applets, QString::number(applet->id()));
|
||||
applet->save(appletConfig);
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::restoreContents(KConfigGroup &group)
|
||||
{
|
||||
KConfigGroup applets(&group, "Applets");
|
||||
|
||||
// Sort the applet configs in order of geometry to ensure that applets
|
||||
// are added from left to right or top to bottom for a panel containment
|
||||
QList<KConfigGroup> appletConfigs;
|
||||
foreach (const QString &appletGroup, applets.groupList()) {
|
||||
//kDebug() << "reading from applet group" << appletGroup;
|
||||
KConfigGroup appletConfig(&applets, appletGroup);
|
||||
appletConfigs.append(appletConfig);
|
||||
}
|
||||
qStableSort(appletConfigs.begin(), appletConfigs.end(), appletConfigLessThan);
|
||||
|
||||
QMutableListIterator<KConfigGroup> it(appletConfigs);
|
||||
while (it.hasNext()) {
|
||||
KConfigGroup &appletConfig = it.next();
|
||||
int appId = appletConfig.name().toUInt();
|
||||
QString plugin = appletConfig.readEntry("plugin", QString());
|
||||
|
||||
if (plugin.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
d->addApplet(plugin, QVariantList(), appletConfig.readEntry("geometry", QRectF()), appId, true);
|
||||
}
|
||||
}
|
||||
|
||||
Containment::Type Containment::containmentType() const
|
||||
{
|
||||
return d->type;
|
||||
}
|
||||
|
||||
void Containment::setContainmentType(Containment::Type type)
|
||||
{
|
||||
if (d->type == type) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->type = type;
|
||||
d->checkContainmentFurniture();
|
||||
}
|
||||
|
||||
Corona *Containment::corona() const
|
||||
{
|
||||
return qobject_cast<Corona*>(parent());
|
||||
}
|
||||
|
||||
void Containment::showDropZone(const QPoint pos)
|
||||
{
|
||||
Q_UNUSED(pos)
|
||||
//Base implementation does nothing, don't put code here
|
||||
}
|
||||
|
||||
void Containment::showContextMenu(const QPointF &containmentPos, const QPoint &screenPos)
|
||||
{
|
||||
//kDebug() << containmentPos << screenPos;
|
||||
QContextMenuEvent gvevent(QContextMenuEvent::Mouse, screenPos);
|
||||
|
||||
//FIXME: do we need views here?
|
||||
//gvevent.setWidget(view());
|
||||
contextMenuEvent(&gvevent);
|
||||
}
|
||||
|
||||
void Containment::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
if (!isContainment() || !KAuthorized::authorizeKAction("plasma/containment_context_menu")) {
|
||||
return;
|
||||
}
|
||||
|
||||
KMenu desktopMenu;
|
||||
//TODO: port to the new containmentactions architecture
|
||||
Applet *applet = 0;//d->appletAt(event->pos());
|
||||
//kDebug() << "context menu event " << (QObject*)applet;
|
||||
|
||||
if (applet) {
|
||||
d->addAppletActions(desktopMenu, applet, event);
|
||||
} else {
|
||||
d->addContainmentActions(desktopMenu, event);
|
||||
}
|
||||
|
||||
//kDebug() << "executing at" << screenPos;
|
||||
QMenu *menu = &desktopMenu;
|
||||
//kDebug() << "showing menu, actions" << desktopMenu.actions().size() << desktopMenu.actions().first()->menu();
|
||||
if (desktopMenu.actions().size() == 1 && desktopMenu.actions().first()->menu()) {
|
||||
// we have a menu with a single top level menu; just show that top level menu instad.
|
||||
menu = desktopMenu.actions().first()->menu();
|
||||
}
|
||||
|
||||
if (!menu->isEmpty()) {
|
||||
QPoint pos = event->globalPos();
|
||||
if (applet && d->isPanelContainment()) {
|
||||
menu->adjustSize();
|
||||
pos = applet->popupPosition(menu->size());
|
||||
if (event->reason() == QContextMenuEvent::Mouse) {
|
||||
// if the menu pops up way away from the mouse press, then move it
|
||||
// to the mouse press
|
||||
if (d->formFactor == Vertical) {
|
||||
if (pos.y() + menu->height() < event->globalPos().y()) {
|
||||
pos.setY(event->globalPos().y());
|
||||
}
|
||||
} else if (d->formFactor == Horizontal) {
|
||||
if (pos.x() + menu->width() < event->globalPos().x()) {
|
||||
pos.setX(event->globalPos().x());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menu->exec(pos);
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::setFormFactor(FormFactor formFactor)
|
||||
{
|
||||
if (d->formFactor == formFactor) {
|
||||
return;
|
||||
}
|
||||
|
||||
//kDebug() << "switching FF to " << formFactor;
|
||||
d->formFactor = formFactor;
|
||||
|
||||
updateConstraints(Plasma::FormFactorConstraint);
|
||||
|
||||
KConfigGroup c = config();
|
||||
c.writeEntry("formfactor", (int)formFactor);
|
||||
emit configNeedsSaving();
|
||||
}
|
||||
|
||||
void Containment::setLocation(Location location)
|
||||
{
|
||||
if (d->location == location) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->location = location;
|
||||
|
||||
foreach (Applet *applet, d->applets) {
|
||||
applet->updateConstraints(Plasma::LocationConstraint);
|
||||
}
|
||||
|
||||
updateConstraints(Plasma::LocationConstraint);
|
||||
|
||||
KConfigGroup c = config();
|
||||
c.writeEntry("location", (int)location);
|
||||
emit configNeedsSaving();
|
||||
}
|
||||
|
||||
void Containment::addSiblingContainment()
|
||||
{
|
||||
emit addSiblingContainment(this);
|
||||
}
|
||||
|
||||
void Containment::clearApplets()
|
||||
{
|
||||
foreach (Applet *applet, d->applets) {
|
||||
applet->d->cleanUpAndDelete();
|
||||
}
|
||||
|
||||
d->applets.clear();
|
||||
}
|
||||
|
||||
Applet *Containment::addApplet(const QString &name, const QVariantList &args,
|
||||
const QRectF &appletGeometry)
|
||||
{
|
||||
return d->addApplet(name, args, appletGeometry);
|
||||
}
|
||||
|
||||
void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit)
|
||||
{
|
||||
if (!isContainment() || (!delayInit && immutability() != Mutable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!applet) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "adding null applet!?!";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->applets.contains(applet)) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "already have this applet!";
|
||||
#endif
|
||||
}
|
||||
|
||||
Containment *currentContainment = applet->containment();
|
||||
|
||||
if (d->type == PanelContainment) {
|
||||
//panels don't want backgrounds, which is important when setting geometry
|
||||
setBackgroundHints(NoBackground);
|
||||
}
|
||||
|
||||
if (currentContainment && currentContainment != this) {
|
||||
emit currentContainment->appletRemoved(applet);
|
||||
|
||||
disconnect(applet, 0, currentContainment, 0);
|
||||
KConfigGroup oldConfig = applet->config();
|
||||
currentContainment->d->applets.removeAll(applet);
|
||||
applet->setParent(this);
|
||||
|
||||
// now move the old config to the new location
|
||||
//FIXME: this doesn't seem to get the actual main config group containing plugin=, etc
|
||||
KConfigGroup c = config().group("Applets").group(QString::number(applet->id()));
|
||||
oldConfig.reparent(&c);
|
||||
applet->d->resetConfigurationObject();
|
||||
|
||||
disconnect(applet, SIGNAL(activate()), currentContainment, SIGNAL(activate()));
|
||||
} else {
|
||||
applet->setParent(this);
|
||||
}
|
||||
|
||||
d->applets << applet;
|
||||
|
||||
connect(applet, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
|
||||
connect(applet, SIGNAL(releaseVisualFocus()), this, SIGNAL(releaseVisualFocus()));
|
||||
connect(applet, SIGNAL(appletDeleted(Plasma::Applet*)), this, SLOT(appletDestroyed(Plasma::Applet*)));
|
||||
connect(applet, SIGNAL(newStatus(Plasma::ItemStatus)), this, SLOT(checkStatus(Plasma::ItemStatus)));
|
||||
connect(applet, SIGNAL(activate()), this, SIGNAL(activate()));
|
||||
|
||||
if (!delayInit && !currentContainment) {
|
||||
applet->restore(*applet->d->mainConfigGroup());
|
||||
applet->init();
|
||||
//FIXME: an on-appear animation would be nice to have again
|
||||
d->appletAppeared(applet);
|
||||
}
|
||||
|
||||
applet->updateConstraints(Plasma::AllConstraints);
|
||||
if (!delayInit) {
|
||||
applet->flushPendingConstraintsEvents();
|
||||
}
|
||||
emit appletAdded(applet, pos);
|
||||
|
||||
if (!currentContainment) {
|
||||
applet->updateConstraints(Plasma::StartupCompletedConstraint);
|
||||
if (!delayInit) {
|
||||
applet->flushPendingConstraintsEvents();
|
||||
}
|
||||
}
|
||||
|
||||
if (!delayInit) {
|
||||
applet->d->scheduleModificationNotification();
|
||||
}
|
||||
}
|
||||
|
||||
Applet::List Containment::applets() const
|
||||
{
|
||||
return d->applets;
|
||||
}
|
||||
|
||||
void Containment::setScreen(int newScreen, int newDesktop)
|
||||
{
|
||||
d->setScreen(newScreen, newDesktop);
|
||||
}
|
||||
|
||||
int Containment::screen() const
|
||||
{
|
||||
return d->screen;
|
||||
}
|
||||
|
||||
int Containment::lastScreen() const
|
||||
{
|
||||
return d->lastScreen;
|
||||
}
|
||||
|
||||
int Containment::desktop() const
|
||||
{
|
||||
return d->desktop;
|
||||
}
|
||||
|
||||
int Containment::lastDesktop() const
|
||||
{
|
||||
return d->lastDesktop;
|
||||
}
|
||||
|
||||
KPluginInfo::List Containment::listContainments(const QString &category,
|
||||
const QString &parentApp)
|
||||
{
|
||||
return listContainmentsOfType(QString(), category, parentApp);
|
||||
}
|
||||
|
||||
|
||||
KPluginInfo::List Containment::listContainmentsOfType(const QString &type,
|
||||
const QString &category,
|
||||
const QString &parentApp)
|
||||
{
|
||||
QString constraint;
|
||||
|
||||
if (parentApp.isEmpty()) {
|
||||
constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')");
|
||||
} else {
|
||||
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
|
||||
}
|
||||
|
||||
if (!type.isEmpty()) {
|
||||
if (!constraint.isEmpty()) {
|
||||
constraint.append(" and ");
|
||||
}
|
||||
|
||||
constraint.append("'").append(type).append("' ~in [X-Plasma-ContainmentCategories]");
|
||||
}
|
||||
|
||||
if (!category.isEmpty()) {
|
||||
if (!constraint.isEmpty()) {
|
||||
constraint.append(" and ");
|
||||
}
|
||||
|
||||
constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
|
||||
if (category == "Miscellaneous") {
|
||||
constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
|
||||
}
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
|
||||
//kDebug() << "constraint was" << constraint << "which got us" << offers.count() << "matches";
|
||||
return KPluginInfo::fromServices(offers);
|
||||
}
|
||||
|
||||
KPluginInfo::List Containment::listContainmentsForMimeType(const QString &mimeType)
|
||||
{
|
||||
const QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimeType);
|
||||
//kDebug() << mimeType << constraint;
|
||||
const KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
|
||||
return KPluginInfo::fromServices(offers);
|
||||
}
|
||||
|
||||
QStringList Containment::listContainmentTypes()
|
||||
{
|
||||
KPluginInfo::List containmentInfos = listContainments();
|
||||
QSet<QString> types;
|
||||
|
||||
foreach (const KPluginInfo &containmentInfo, containmentInfos) {
|
||||
QStringList theseTypes = containmentInfo.service()->property("X-Plasma-ContainmentCategories").toStringList();
|
||||
foreach (const QString &type, theseTypes) {
|
||||
types.insert(type);
|
||||
}
|
||||
}
|
||||
|
||||
return types.toList();
|
||||
}
|
||||
|
||||
void Containment::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
//kDebug() << "keyPressEvent with" << event->key()
|
||||
// << "and hoping and wishing for a" << Qt::Key_Tab;
|
||||
if (event->key() == Qt::Key_Tab) { // && event->modifiers() == 0) {
|
||||
if (!d->applets.isEmpty()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "let's give focus to...." << (QObject*)d->applets.first();
|
||||
#endif
|
||||
d->applets.first()->setFocus(Qt::TabFocusReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
|
||||
QString trigger = ContainmentActions::eventToString(event);
|
||||
|
||||
if (d->prepareContainmentActions(trigger, event->globalPos())) {
|
||||
if (event->delta() > 0) {
|
||||
d->actionPlugins()->value(trigger)->performNext();
|
||||
} else {
|
||||
d->actionPlugins()->value(trigger)->performPrevious();
|
||||
}
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::enableAction(const QString &name, bool enable)
|
||||
{
|
||||
QAction *action = this->action(name);
|
||||
if (action) {
|
||||
action->setEnabled(enable);
|
||||
action->setVisible(enable);
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::addToolBoxAction(QAction *action)
|
||||
{
|
||||
d->toolBoxActions << action;
|
||||
}
|
||||
|
||||
void Containment::removeToolBoxAction(QAction *action)
|
||||
{
|
||||
d->toolBoxActions.removeAll(action);
|
||||
}
|
||||
|
||||
void Containment::addAssociatedWidget(QWidget *widget)
|
||||
{
|
||||
//TODO: move this whole method in the c++ part of the QML implementation
|
||||
Applet::addAssociatedWidget(widget);
|
||||
|
||||
/*if (d->focusedApplet) {
|
||||
d->focusedApplet->addAssociatedWidget(widget);
|
||||
}*/
|
||||
|
||||
foreach (const Applet *applet, d->applets) {
|
||||
if (applet->d->activationAction) {
|
||||
widget->addAction(applet->d->activationAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::removeAssociatedWidget(QWidget *widget)
|
||||
{
|
||||
//TODO: move this whole method in the c++ part of the QML implementation
|
||||
Applet::removeAssociatedWidget(widget);
|
||||
/*if (d->focusedApplet) {
|
||||
d->focusedApplet->removeAssociatedWidget(widget);
|
||||
}*/
|
||||
|
||||
foreach (const Applet *applet, d->applets) {
|
||||
if (applet->d->activationAction) {
|
||||
widget->removeAction(applet->d->activationAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Containment::setDrawWallpaper(bool drawWallpaper)
|
||||
{
|
||||
d->drawWallpaper = drawWallpaper;
|
||||
}
|
||||
|
||||
bool Containment::drawWallpaper()
|
||||
{
|
||||
return d->drawWallpaper;
|
||||
}
|
||||
|
||||
void Containment::setWallpaper(const QString &pluginName, const QString &mode)
|
||||
{
|
||||
KConfigGroup cfg = config();
|
||||
bool newPlugin = pluginName != d->wallpaper;
|
||||
bool newMode = mode != d->wallpaperMode;
|
||||
|
||||
|
||||
if (newPlugin || newMode) {
|
||||
d->wallpaper = pluginName;
|
||||
d->wallpaperMode = mode;
|
||||
|
||||
if (newMode) {
|
||||
cfg.writeEntry("wallpaperpluginmode", mode);
|
||||
}
|
||||
if (newPlugin) {
|
||||
cfg.writeEntry("wallpaperplugin", pluginName);
|
||||
}
|
||||
emit configNeedsSaving();
|
||||
}
|
||||
}
|
||||
|
||||
QString Containment::wallpaper() const
|
||||
{
|
||||
return d->wallpaper;
|
||||
}
|
||||
|
||||
QString Containment::wallpaperMode() const
|
||||
{
|
||||
return d->wallpaperMode;
|
||||
}
|
||||
|
||||
void Containment::setContainmentActions(const QString &trigger, const QString &pluginName)
|
||||
{
|
||||
KConfigGroup cfg = containmentActionsConfig();
|
||||
ContainmentActions *plugin = 0;
|
||||
|
||||
if (d->actionPlugins()->contains(trigger)) {
|
||||
plugin = d->actionPlugins()->value(trigger);
|
||||
if (plugin->pluginName() != pluginName) {
|
||||
d->actionPlugins()->remove(trigger);
|
||||
delete plugin;
|
||||
plugin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginName.isEmpty()) {
|
||||
cfg.deleteEntry(trigger);
|
||||
} else if (plugin) {
|
||||
// it already existed, reset the containment so it wil reload config on next show
|
||||
plugin->setContainment(0);
|
||||
} else {
|
||||
switch (d->containmentActionsSource) {
|
||||
case ContainmentPrivate::Activity:
|
||||
//FIXME
|
||||
case ContainmentPrivate::Local:
|
||||
plugin = PluginLoader::self()->loadContainmentActions(this, pluginName);
|
||||
break;
|
||||
default:
|
||||
plugin = PluginLoader::self()->loadContainmentActions(0, pluginName);
|
||||
}
|
||||
|
||||
if (plugin) {
|
||||
cfg.writeEntry(trigger, pluginName);
|
||||
d->actionPlugins()->insert(trigger, plugin);
|
||||
} else {
|
||||
//bad plugin... gets removed. is this a feature or a bug?
|
||||
cfg.deleteEntry(trigger);
|
||||
}
|
||||
}
|
||||
|
||||
emit configNeedsSaving();
|
||||
}
|
||||
|
||||
QStringList Containment::containmentActionsTriggers()
|
||||
{
|
||||
return d->actionPlugins()->keys();
|
||||
}
|
||||
|
||||
QString Containment::containmentActions(const QString &trigger)
|
||||
{
|
||||
ContainmentActions *c = d->actionPlugins()->value(trigger);
|
||||
return c ? c->pluginName() : QString();
|
||||
}
|
||||
|
||||
void Containment::setActivity(const QString &activityId)
|
||||
{
|
||||
if (activityId.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->activityId = activityId;
|
||||
KConfigGroup c = config();
|
||||
c.writeEntry("activityId", activityId);
|
||||
|
||||
emit configNeedsSaving();
|
||||
}
|
||||
|
||||
QString Containment::activity() const
|
||||
{
|
||||
return d->activityId;
|
||||
}
|
||||
|
||||
void Containment::destroy()
|
||||
{
|
||||
destroy(true);
|
||||
}
|
||||
|
||||
void Containment::showConfigurationInterface()
|
||||
{
|
||||
Applet::showConfigurationInterface();
|
||||
}
|
||||
|
||||
void Containment::destroy(bool confirm)
|
||||
{
|
||||
if (immutability() != Mutable || Applet::d->transient) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isContainment() && confirm) {
|
||||
//FIXME: should not be blocking
|
||||
const QString title = i18nc("@title:window %1 is the name of the containment", "Remove %1", name());
|
||||
KGuiItem remove = KStandardGuiItem::remove();
|
||||
remove.setText(title);
|
||||
//FIXME: make the view accessible?
|
||||
if (KMessageBox::warningContinueCancel(0/*view()*/,
|
||||
i18nc("%1 is the name of the containment", "Do you really want to remove this %1?", name()),
|
||||
title, remove) != KMessageBox::Continue) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Applet::destroy();
|
||||
}
|
||||
|
||||
KConfigGroup Containment::containmentActionsConfig()
|
||||
{
|
||||
KConfigGroup cfg;
|
||||
switch (d->containmentActionsSource) {
|
||||
case ContainmentPrivate::Local:
|
||||
cfg = config();
|
||||
cfg = KConfigGroup(&cfg, "ActionPlugins");
|
||||
break;
|
||||
case ContainmentPrivate::Activity:
|
||||
cfg = KConfigGroup(corona()->config(), "Activities");
|
||||
cfg = KConfigGroup(&cfg, d->activityId);
|
||||
cfg = KConfigGroup(&cfg, "ActionPlugins");
|
||||
break;
|
||||
default:
|
||||
cfg = KConfigGroup(corona()->config(), "ActionPlugins");
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
|
||||
#include "moc_containment.cpp"
|
540
plasma/containment.h
Normal file
540
plasma/containment.h
Normal file
@ -0,0 +1,540 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 PLASMA_CONTAINMENT_H
|
||||
#define PLASMA_CONTAINMENT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
#include <ksharedconfig.h>
|
||||
|
||||
#include <plasma/applet.h>
|
||||
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AccessAppletJob;
|
||||
class AppletHandle;
|
||||
class DataEngine;
|
||||
class Package;
|
||||
class Corona;
|
||||
class View;
|
||||
class Wallpaper;
|
||||
class ContainmentActions;
|
||||
class ContainmentPrivate;
|
||||
class AbstractToolBox;
|
||||
|
||||
/**
|
||||
* @class Containment plasma/containment.h <Plasma/Containment>
|
||||
*
|
||||
* @short The base class for plugins that provide backgrounds and applet grouping containers
|
||||
*
|
||||
* Containment objects provide the means to group applets into functional sets.
|
||||
* They also provide the following:
|
||||
*
|
||||
* creation of focussing event
|
||||
* - drawing of the background image (which can be interactive)
|
||||
* - form factors (e.g. panel, desktop, full screen, etc)
|
||||
* - applet layout management
|
||||
*
|
||||
* Since containment is actually just a Plasma::Applet, all the techniques used
|
||||
* for writing the visual presentation of Applets is applicable to Containtments.
|
||||
* Containments are differentiated from Applets by being marked with the ServiceType
|
||||
* of Plasma/Containment. Plugins registered with both the Applet and the Containment
|
||||
* ServiceTypes can be loaded for us in either situation.
|
||||
*
|
||||
* See techbase.kde.org for a tutorial on writing Containments using this class.
|
||||
*/
|
||||
class PLASMA_EXPORT Containment : public Applet
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum Type {
|
||||
NoContainmentType = -1, /**< @internal */
|
||||
DesktopContainment = 0, /**< A desktop containment */
|
||||
PanelContainment, /**< A desktop panel */
|
||||
CustomContainment = 127, /**< A containment that is neither a desktop nor a panel
|
||||
but something application specific */
|
||||
CustomPanelContainment = 128 /**< A customized desktop panel */
|
||||
};
|
||||
|
||||
enum ToolType {
|
||||
AddTool = 0,
|
||||
ConfigureTool = 100,
|
||||
ControlTool = 200,
|
||||
MiscTool = 300,
|
||||
DestructiveTool = 400,
|
||||
UserToolType = DestructiveTool + 1000
|
||||
};
|
||||
Q_ENUMS(ToolType)
|
||||
|
||||
/**
|
||||
* @param parent the QObject this applet is parented to
|
||||
* @param serviceId the name of the .desktop file containing the
|
||||
* information about the widget
|
||||
* @param containmentId a unique id used to differentiate between multiple
|
||||
* instances of the same Applet type
|
||||
*/
|
||||
explicit Containment(QObject *parent = 0,
|
||||
const QString &serviceId = QString(),
|
||||
uint containmentId = 0);
|
||||
|
||||
/**
|
||||
* This constructor is to be used with the plugin loading systems
|
||||
* found in KPluginInfo and KService. The argument list is expected
|
||||
* to have two elements: the KService service ID for the desktop entry
|
||||
* and an applet ID which must be a base 10 number.
|
||||
*
|
||||
* @param parent a QObject parent; you probably want to pass in 0
|
||||
* @param args a list of strings containing two entries: the service id
|
||||
* and the applet id
|
||||
*/
|
||||
Containment(QObject *parent, const QVariantList &args);
|
||||
|
||||
~Containment();
|
||||
|
||||
/**
|
||||
* Reimplemented from Applet
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Returns the type of containment
|
||||
*/
|
||||
Type containmentType() const;
|
||||
|
||||
/**
|
||||
* Returns the Corona (if any) that this Containment is hosted by
|
||||
*/
|
||||
Corona *corona() const;
|
||||
|
||||
/**
|
||||
* Returns a list of all known containments.
|
||||
*
|
||||
* @param category Only containments matching this category will be returned.
|
||||
* Useful in conjunction with knownCategories.
|
||||
* If "Miscellaneous" is passed in, then applets without a
|
||||
* Categories= entry are also returned.
|
||||
* If an empty string is passed in, all applets are
|
||||
* returned.
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of applets
|
||||
**/
|
||||
static KPluginInfo::List listContainments(const QString &category = QString(),
|
||||
const QString &parentApp = QString());
|
||||
|
||||
/**
|
||||
* Returns a list of all known Containments that match the parameters.
|
||||
*
|
||||
* @param type Only Containments with this string in X-Plasma-ContainmentCategories
|
||||
* in their .desktop files will be returned. Common values are panel and
|
||||
* desktop
|
||||
* @param category Only applets matchin this category will be returned.
|
||||
* Useful in conjunction with knownCategories.
|
||||
* If "Miscellaneous" is passed in, then applets without a
|
||||
* Categories= entry are also returned.
|
||||
* If an empty string is passed in, all applets are
|
||||
* returned.
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of applets
|
||||
**/
|
||||
static KPluginInfo::List listContainmentsOfType(const QString &type,
|
||||
const QString &category = QString(),
|
||||
const QString &parentApp = QString());
|
||||
|
||||
/**
|
||||
* @return a list of all known types of Containments on this system
|
||||
*/
|
||||
static QStringList listContainmentTypes();
|
||||
|
||||
/**
|
||||
* Returns a list of all known applets associated with a certain MimeType
|
||||
*
|
||||
* @return list of applets
|
||||
**/
|
||||
static KPluginInfo::List listContainmentsForMimeType(const QString &mimeType);
|
||||
|
||||
/**
|
||||
* Adds an applet to this Containment
|
||||
*
|
||||
* @param name the plugin name for the applet, as given by
|
||||
* KPluginInfo::pluginName()
|
||||
* @param args argument list to pass to the plasmoid
|
||||
* @param geometry where to place the applet, or to auto-place it if an invalid
|
||||
* is provided
|
||||
*
|
||||
* @return a pointer to the applet on success, or 0 on failure
|
||||
*/
|
||||
Applet *addApplet(const QString &name, const QVariantList &args = QVariantList(),
|
||||
const QRectF &geometry = QRectF(-1, -1, -1, -1));
|
||||
|
||||
/**
|
||||
* Add an existing applet to this Containment
|
||||
*
|
||||
* If dontInit is true, the pending constraints are not flushed either.
|
||||
* So it is your responsibility to call both init() and
|
||||
* flushPendingConstraints() on the applet.
|
||||
*
|
||||
* @param applet the applet that should be added
|
||||
* @param pos the containment-relative position
|
||||
* @param dontInit if true, init() will not be called on the applet
|
||||
*/
|
||||
void addApplet(Applet *applet, const QPointF &pos = QPointF(-1, -1), bool dontInit = true);
|
||||
|
||||
/**
|
||||
* @return the applets currently in this Containment
|
||||
*/
|
||||
Applet::List applets() const;
|
||||
|
||||
/**
|
||||
* Removes all applets from this Containment
|
||||
*/
|
||||
void clearApplets();
|
||||
|
||||
/**
|
||||
* Sets the physical screen this Containment is associated with.
|
||||
*
|
||||
* @param screen the screen number this containment is the desktop for, or -1
|
||||
* if it is not serving as the desktop for any screen
|
||||
* @param desktop the virtual desktop to also associate this this screen with
|
||||
*/
|
||||
void setScreen(int screen, int desktop = -1);
|
||||
|
||||
/**
|
||||
* @return the screen number this containment is serving as the desktop for
|
||||
* or -1 if none
|
||||
*/
|
||||
int screen() const;
|
||||
|
||||
/**
|
||||
* @return the last screen number this containment had
|
||||
* only returns -1 if it's never ever been on a screen
|
||||
* @since 4.5
|
||||
*/
|
||||
int lastScreen() const;
|
||||
|
||||
/**
|
||||
* @return the viewport (e.g. virtual desktop) this Containment is associated with.
|
||||
*/
|
||||
int desktop() const;
|
||||
|
||||
/**
|
||||
* @return the viewport (e.g. virtual desktop) this Containment was associated with
|
||||
* last time it had a screen
|
||||
* @since 4.5
|
||||
*/
|
||||
int lastDesktop() const;
|
||||
|
||||
/**
|
||||
* @reimp
|
||||
* @sa Applet::save(KConfigGroup &)
|
||||
*/
|
||||
void save(KConfigGroup &group) const;
|
||||
|
||||
/**
|
||||
* @reimp
|
||||
* @sa Applet::restore(KConfigGroup &)
|
||||
*/
|
||||
void restore(KConfigGroup &group);
|
||||
|
||||
/**
|
||||
* convenience function - enables or disables an action by name
|
||||
*
|
||||
* @param name the name of the action in our collection
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
void enableAction(const QString &name, bool enable);
|
||||
|
||||
/**
|
||||
* Add an action to the toolbox
|
||||
*/
|
||||
void addToolBoxAction(QAction *action);
|
||||
|
||||
/**
|
||||
* Remove an action from the toolbox
|
||||
*/
|
||||
void removeToolBoxAction(QAction *action);
|
||||
|
||||
/**
|
||||
* associate actions with this widget, including ones added after this call.
|
||||
* needed to make keyboard shortcuts work.
|
||||
*/
|
||||
void addAssociatedWidget(QWidget *widget);
|
||||
|
||||
/**
|
||||
* un-associate actions from this widget, including ones added after this call.
|
||||
* needed to make keyboard shortcuts work.
|
||||
*/
|
||||
void removeAssociatedWidget(QWidget *widget);
|
||||
|
||||
/**
|
||||
* Return whether wallpaper is painted or not.
|
||||
*/
|
||||
bool drawWallpaper();
|
||||
|
||||
/**
|
||||
* Sets wallpaper plugin.
|
||||
*
|
||||
* @param pluginName the name of the wallpaper to attempt to load
|
||||
* @param mode optional mode or the wallpaper plugin (e.g. "Slideshow").
|
||||
* These values are pugin specific and enumerated in the plugin's
|
||||
* .desktop file.
|
||||
*/
|
||||
void setWallpaper(const QString &pluginName, const QString &mode = QString());
|
||||
|
||||
/**
|
||||
* Return wallpaper plugin.
|
||||
*/
|
||||
QString wallpaper() const;
|
||||
|
||||
/**
|
||||
* Return wallpaper rendering mode.
|
||||
*/
|
||||
QString wallpaperMode() const;
|
||||
|
||||
/**
|
||||
* Sets the current activity by id
|
||||
*
|
||||
* @param activity the id of the activity
|
||||
*/
|
||||
void setActivity(const QString &activityId);
|
||||
|
||||
/**
|
||||
* @return the current activity id associated with this containment
|
||||
*/
|
||||
QString activity() const;
|
||||
|
||||
/**
|
||||
* Shows the context menu for the containment directly, bypassing Applets
|
||||
* altogether.
|
||||
*/
|
||||
void showContextMenu(const QPointF &containmentPos, const QPoint &screenPos);
|
||||
|
||||
/**
|
||||
* Shows a visual clue for drag and drop
|
||||
* The default implementation does nothing,
|
||||
* reimplement in containments that need it
|
||||
*
|
||||
* @param pos point where to show the drop target; if an invalid point is passed in
|
||||
* the drop zone should not be shown
|
||||
*/
|
||||
virtual void showDropZone(const QPoint pos);
|
||||
|
||||
/**
|
||||
* Sets a containmentactions plugin.
|
||||
*
|
||||
* @param trigger the mouse button (and optional modifier) to associate the plugin with
|
||||
* @param pluginName the name of the plugin to attempt to load. blank = set no plugin.
|
||||
* @since 4.4
|
||||
*/
|
||||
void setContainmentActions(const QString &trigger, const QString &pluginName);
|
||||
|
||||
/**
|
||||
* @return a list of all triggers that have a containmentactions plugin associated
|
||||
* @since 4.4
|
||||
*/
|
||||
QStringList containmentActionsTriggers();
|
||||
|
||||
/**
|
||||
* @return the plugin name for the given trigger
|
||||
* @since 4.4
|
||||
*/
|
||||
QString containmentActions(const QString &trigger);
|
||||
|
||||
/**
|
||||
* @return the config group that containmentactions plugins go in
|
||||
* @since 4.6
|
||||
*/
|
||||
KConfigGroup containmentActionsConfig();
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal is emitted when a new applet is created by the containment
|
||||
*/
|
||||
void appletAdded(Plasma::Applet *applet, const QPointF &pos);
|
||||
|
||||
/**
|
||||
* This signal is emitted when an applet is destroyed
|
||||
*/
|
||||
void appletRemoved(Plasma::Applet *applet);
|
||||
|
||||
/**
|
||||
* Emitted when the user clicks on the toolbox
|
||||
*/
|
||||
void toolBoxToggled();
|
||||
|
||||
/**
|
||||
* Emitted when the toolbox is hidden or shown
|
||||
* @since 4.3
|
||||
*/
|
||||
void toolBoxVisibilityChanged(bool);
|
||||
|
||||
/**
|
||||
* Emitted when the containment wants a new containment to be created.
|
||||
* Usually only used for desktop containments.
|
||||
*/
|
||||
void addSiblingContainment(Plasma::Containment *);
|
||||
|
||||
/**
|
||||
* Emitted when the containment requests an add widgets dialog is shown.
|
||||
* Usually only used for desktop containments.
|
||||
*
|
||||
* @param pos where in the containment this request was made from, or
|
||||
* an invalid position (QPointF()) is not location specific
|
||||
*/
|
||||
void showAddWidgetsInterface(const QPointF &pos);
|
||||
|
||||
/**
|
||||
* This signal indicates that a containment has been newly
|
||||
* associated (or dissociated) with a physical screen.
|
||||
*
|
||||
* @param wasScreen the screen it was associated with
|
||||
* @param isScreen the screen it is now associated with
|
||||
* @param containment the containment switching screens
|
||||
*/
|
||||
void screenChanged(int wasScreen, int isScreen, Plasma::Containment *containment);
|
||||
|
||||
/**
|
||||
* Emitted when the user wants to configure/change containment.
|
||||
*/
|
||||
void configureRequested(Plasma::Containment *containment);
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Informs the Corona as to what position it is in. This is informational
|
||||
* only, as the Corona doesn't change its actual location. This is,
|
||||
* however, passed on to Applets that may be managed by this Corona.
|
||||
*
|
||||
* @param location the new location of this Corona
|
||||
*/
|
||||
void setLocation(Plasma::Location location);
|
||||
|
||||
/**
|
||||
* Sets the form factor for this Containment. This may cause changes in both
|
||||
* the arrangement of Applets as well as the display choices of individual
|
||||
* Applets.
|
||||
*/
|
||||
void setFormFactor(Plasma::FormFactor formFactor);
|
||||
|
||||
/**
|
||||
* Tells the corona to create a new desktop containment
|
||||
*/
|
||||
void addSiblingContainment();
|
||||
|
||||
/**
|
||||
* Destroys this containment and all its applets (after a confirmation dialog);
|
||||
* it will be removed nicely and deleted.
|
||||
* Its configuration will also be deleted.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Destroys this containment and all its applets (after a confirmation dialog);
|
||||
* it will be removed nicely and deleted.
|
||||
* Its configuration will also be deleted.
|
||||
*
|
||||
* @param confirm whether or not confirmation from the user should be requested
|
||||
*/
|
||||
void destroy(bool confirm);
|
||||
|
||||
/**
|
||||
* @reimp
|
||||
* @sa Applet::showConfigurationInterface()
|
||||
*/
|
||||
void showConfigurationInterface();
|
||||
|
||||
/**
|
||||
* Sets the type of this containment.
|
||||
*/
|
||||
void setContainmentType(Containment::Type type);
|
||||
|
||||
/**
|
||||
* Sets whether wallpaper is painted or not.
|
||||
*/
|
||||
void setDrawWallpaper(bool drawWallpaper);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Called when the contents of the containment should be saved. By default this saves
|
||||
* all loaded Applets
|
||||
*
|
||||
* @param group the KConfigGroup to save settings under
|
||||
*/
|
||||
virtual void saveContents(KConfigGroup &group) const;
|
||||
|
||||
/**
|
||||
* Called when the contents of the containment should be loaded. By default this loads
|
||||
* all previously saved Applets
|
||||
*
|
||||
* @param group the KConfigGroup to save settings under
|
||||
*/
|
||||
virtual void restoreContents(KConfigGroup &group);
|
||||
|
||||
//FIXME: events should go away
|
||||
void contextMenuEvent(QContextMenuEvent *event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* @internal This constructor is to be used with the Package loading system.
|
||||
*
|
||||
* @param parent a QObject parent; you probably want to pass in 0
|
||||
* @param args a list of strings containing two entries: the service id
|
||||
* and the applet id
|
||||
* @since 4.3
|
||||
*/
|
||||
Containment(const QString &packagePath, uint appletId, const QVariantList &args);
|
||||
|
||||
Q_PRIVATE_SLOT(d, void appletDeleted(Plasma::Applet*))
|
||||
Q_PRIVATE_SLOT(d, void triggerShowAddWidgets())
|
||||
Q_PRIVATE_SLOT(d, void requestConfiguration())
|
||||
Q_PRIVATE_SLOT(d, void checkStatus(Plasma::ItemStatus))
|
||||
|
||||
friend class Applet;
|
||||
friend class AppletPrivate;
|
||||
friend class CoronaPrivate;
|
||||
friend class CoronaBasePrivate;
|
||||
friend class ContainmentPrivate;
|
||||
friend class ContainmentActions;
|
||||
friend class PopupApplet;
|
||||
friend class View;
|
||||
ContainmentPrivate *const d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif // multiple inclusion guard
|
221
plasma/containmentactions.cpp
Normal file
221
plasma/containmentactions.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 "containmentactions.h"
|
||||
#include "containment.h"
|
||||
|
||||
#include "private/packages_p.h"
|
||||
#include "private/containmentactions_p.h"
|
||||
#include "private/containment_p.h"
|
||||
|
||||
#include <QMetaEnum>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <klocalizedstring.h>
|
||||
#include <kservicetypetrader.h>
|
||||
|
||||
#include "dataengineconsumer.h"
|
||||
#include "version.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
ContainmentActions::ContainmentActions(QObject * parentObject)
|
||||
: d(new ContainmentActionsPrivate(KService::serviceByStorageId(QString()), this))
|
||||
{
|
||||
setParent(parentObject);
|
||||
}
|
||||
|
||||
ContainmentActions::ContainmentActions(QObject *parentObject, const QVariantList &args)
|
||||
: d(new ContainmentActionsPrivate(KService::serviceByStorageId(args.count() > 0 ?
|
||||
args[0].toString() : QString()), this))
|
||||
{
|
||||
// now remove first item since those are managed by Wallpaper and subclasses shouldn't
|
||||
// need to worry about them. yes, it violates the constness of this var, but it lets us add
|
||||
// or remove items later while applets can just pretend that their args always start at 0
|
||||
QVariantList &mutableArgs = const_cast<QVariantList &>(args);
|
||||
if (!mutableArgs.isEmpty()) {
|
||||
mutableArgs.removeFirst();
|
||||
}
|
||||
|
||||
setParent(parentObject);
|
||||
}
|
||||
|
||||
ContainmentActions::~ContainmentActions()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
Containment *ContainmentActions::containment()
|
||||
{
|
||||
if (d->containment) {
|
||||
return d->containment;
|
||||
}
|
||||
return qobject_cast<Containment*>(parent());
|
||||
}
|
||||
|
||||
QString ContainmentActions::name() const
|
||||
{
|
||||
if (!d->containmentActionsDescription.isValid()) {
|
||||
return i18n("Unknown ContainmentActions");
|
||||
}
|
||||
|
||||
return d->containmentActionsDescription.name();
|
||||
}
|
||||
|
||||
QString ContainmentActions::icon() const
|
||||
{
|
||||
if (!d->containmentActionsDescription.isValid()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return d->containmentActionsDescription.icon();
|
||||
}
|
||||
|
||||
QString ContainmentActions::pluginName() const
|
||||
{
|
||||
if (!d->containmentActionsDescription.isValid()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return d->containmentActionsDescription.pluginName();
|
||||
}
|
||||
|
||||
void ContainmentActions::restore(const KConfigGroup &config)
|
||||
{
|
||||
init(config);
|
||||
}
|
||||
|
||||
void ContainmentActions::init(const KConfigGroup &config)
|
||||
{
|
||||
Q_UNUSED(config);
|
||||
}
|
||||
|
||||
void ContainmentActions::save(KConfigGroup &config)
|
||||
{
|
||||
Q_UNUSED(config);
|
||||
}
|
||||
|
||||
QWidget *ContainmentActions::createConfigurationInterface(QWidget *parent)
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ContainmentActions::configurationAccepted()
|
||||
{
|
||||
//do nothing by default
|
||||
}
|
||||
|
||||
QAction *ContainmentActions::triggerableContextAction()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ContainmentActions::performNext()
|
||||
{
|
||||
}
|
||||
|
||||
void ContainmentActions::performPrevious()
|
||||
{
|
||||
}
|
||||
|
||||
QList<QAction*> ContainmentActions::contextualActions()
|
||||
{
|
||||
return QList<QAction*>();
|
||||
}
|
||||
|
||||
DataEngine *ContainmentActions::dataEngine(const QString &name) const
|
||||
{
|
||||
return d->dataEngine(name);
|
||||
}
|
||||
|
||||
bool ContainmentActions::configurationRequired() const
|
||||
{
|
||||
return d->needsConfig;
|
||||
}
|
||||
|
||||
void ContainmentActions::setConfigurationRequired(bool needsConfig)
|
||||
{
|
||||
if (d->needsConfig != needsConfig) {
|
||||
d->needsConfig = needsConfig;
|
||||
emit configurationRequiredChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QString ContainmentActions::eventToString(QEvent *event)
|
||||
{
|
||||
QString trigger;
|
||||
Qt::KeyboardModifiers modifiers;
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::MouseButtonDblClick:
|
||||
{
|
||||
QMouseEvent *e = static_cast<QMouseEvent*>(event);
|
||||
int m = QObject::staticQtMetaObject.indexOfEnumerator("MouseButtons");
|
||||
QMetaEnum mouse = QObject::staticQtMetaObject.enumerator(m);
|
||||
trigger += mouse.valueToKey(e->button());
|
||||
modifiers = e->modifiers();
|
||||
break;
|
||||
}
|
||||
case QEvent::Wheel:
|
||||
{
|
||||
QWheelEvent *e = static_cast<QWheelEvent*>(event);
|
||||
int o = QObject::staticQtMetaObject.indexOfEnumerator("Orientations");
|
||||
QMetaEnum orient = QObject::staticQtMetaObject.enumerator(o);
|
||||
trigger = "wheel:";
|
||||
trigger += orient.valueToKey(e->orientation());
|
||||
modifiers = e->modifiers();
|
||||
break;
|
||||
}
|
||||
case QEvent::ContextMenu:
|
||||
{
|
||||
int m = QObject::staticQtMetaObject.indexOfEnumerator("MouseButtons");
|
||||
QMetaEnum mouse = QObject::staticQtMetaObject.enumerator(m);
|
||||
trigger = mouse.valueToKey(Qt::RightButton);
|
||||
modifiers = Qt::NoModifier;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
|
||||
int k = QObject::staticQtMetaObject.indexOfEnumerator("KeyboardModifiers");
|
||||
QMetaEnum kbd = QObject::staticQtMetaObject.enumerator(k);
|
||||
trigger += ';';
|
||||
trigger += kbd.valueToKeys(modifiers);
|
||||
|
||||
return trigger;
|
||||
}
|
||||
|
||||
void ContainmentActions::setContainment(Containment *newContainment) {
|
||||
d->containment = newContainment;
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
#include "moc_containmentactions.cpp"
|
234
plasma/containmentactions.h
Normal file
234
plasma/containmentactions.h
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 PLASMA_CONTAINMENTACTIONS_H
|
||||
#define PLASMA_CONTAINMENTACTIONS_H
|
||||
|
||||
#include <QList>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/version.h>
|
||||
|
||||
class QAction;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataEngine;
|
||||
class Containment;
|
||||
class ContainmentActionsPrivate;
|
||||
|
||||
/**
|
||||
* @class ContainmentActions plasma/containmentactions.h <Plasma/ContainmentActions>
|
||||
*
|
||||
* @short The base ContainmentActions class
|
||||
*
|
||||
* "ContainmentActions" are components that provide actions (usually displaying a contextmenu) in
|
||||
* response to an event with a position (usually a mouse event).
|
||||
*
|
||||
* ContainmentActions plugins are registered using .desktop files. These files should be
|
||||
* named using the following naming scheme:
|
||||
*
|
||||
* plasma-containmentactions-\<pluginname\>.desktop
|
||||
*
|
||||
*/
|
||||
|
||||
class PLASMA_EXPORT ContainmentActions : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QString pluginName READ pluginName CONSTANT)
|
||||
Q_PROPERTY(QString icon READ icon CONSTANT)
|
||||
Q_PROPERTY(bool configurationRequired READ configurationRequired NOTIFY configurationRequiredChanged)
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor for an empty or null containmentactions
|
||||
*/
|
||||
explicit ContainmentActions(QObject * parent = 0);
|
||||
|
||||
~ContainmentActions();
|
||||
|
||||
/**
|
||||
* Returns the user-visible name for the containmentactions, as specified in the
|
||||
* .desktop file.
|
||||
*
|
||||
* @return the user-visible name for the containmentactions.
|
||||
**/
|
||||
QString name() const;
|
||||
|
||||
/**
|
||||
* Returns the plugin name for the containmentactions
|
||||
*/
|
||||
QString pluginName() const;
|
||||
|
||||
/**
|
||||
* Returns the icon related to this containmentactions
|
||||
**/
|
||||
QString icon() const;
|
||||
|
||||
/**
|
||||
* This method should be called once the plugin is loaded or settings are changed.
|
||||
* @param config Config group to load settings
|
||||
* @see init
|
||||
**/
|
||||
void restore(const KConfigGroup &config);
|
||||
|
||||
/**
|
||||
* This method is called when settings need to be saved.
|
||||
* @param config Config group to save settings
|
||||
**/
|
||||
virtual void save(KConfigGroup &config);
|
||||
|
||||
/**
|
||||
* Returns the widget used in the configuration dialog.
|
||||
* Add the configuration interface of the containmentactions to this widget.
|
||||
*/
|
||||
virtual QWidget *createConfigurationInterface(QWidget *parent);
|
||||
|
||||
/**
|
||||
* This method is called when the user's configuration changes are accepted
|
||||
*/
|
||||
virtual void configurationAccepted();
|
||||
|
||||
/**
|
||||
* @return the action that is to be immediately triggered when this plugin is
|
||||
* activated for a context action, or NULL if there is no such action
|
||||
* @see contextualActions
|
||||
*/
|
||||
virtual QAction *triggerableContextAction();
|
||||
|
||||
/**
|
||||
* Called when a "next" action is triggered (e.g. by mouse wheel scroll). This
|
||||
* can be used to scroll through a list of items this plugin manages such as
|
||||
* windows, virtual desktops, activities, etc.
|
||||
* @see performPrevious
|
||||
*/
|
||||
virtual void performNext();
|
||||
|
||||
/**
|
||||
* Called when a "previous" action is triggered (e.g. by mouse wheel scroll). This
|
||||
* can be used to scroll through a list of items this plugin manages such as
|
||||
* windows, virtual desktops, activities, etc.
|
||||
* @see performNext
|
||||
*/
|
||||
virtual void performPrevious();
|
||||
|
||||
/**
|
||||
* Implement this to provide a list of actions that can be added to another menu
|
||||
* for example, when right-clicking an applet, the "Activity Options" submenu is populated
|
||||
* with this.
|
||||
*/
|
||||
Q_INVOKABLE virtual QList<QAction*> contextualActions();
|
||||
|
||||
/**
|
||||
* Loads the given DataEngine
|
||||
*
|
||||
* Tries to load the data engine given by @p name. Each engine is
|
||||
* only loaded once, and that instance is re-used on all subsequent
|
||||
* requests.
|
||||
*
|
||||
* If the data engine was not found, an invalid data engine is returned
|
||||
* (see DataEngine::isValid()).
|
||||
*
|
||||
* Note that you should <em>not</em> delete the returned engine.
|
||||
*
|
||||
* @param name Name of the data engine to load
|
||||
* @return pointer to the data engine if it was loaded,
|
||||
* or an invalid data engine if the requested engine
|
||||
* could not be loaded
|
||||
*
|
||||
*/
|
||||
DataEngine *dataEngine(const QString &name) const;
|
||||
|
||||
/**
|
||||
* @return true if the containmentactions currently needs to be configured,
|
||||
* otherwise, false
|
||||
*/
|
||||
bool configurationRequired() const;
|
||||
|
||||
/**
|
||||
* Turns a mouse or wheel event into a string suitable for a ContainmentActions
|
||||
* @return the string representation of the event
|
||||
*/
|
||||
static QString eventToString(QEvent *event);
|
||||
|
||||
/**
|
||||
* @p newContainment the containment the plugin should be associated with.
|
||||
* @since 4.6
|
||||
*/
|
||||
void setContainment(Containment *newContainment);
|
||||
|
||||
/**
|
||||
* @return the containment the plugin is associated with.
|
||||
*/
|
||||
Containment *containment();
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emitted when @see configurationRequired() changes
|
||||
*/
|
||||
void configurationRequiredChanged();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This constructor is to be used with the plugin loading systems
|
||||
* found in KPluginInfo and KService. The argument list is expected
|
||||
* to have one element: the KService service ID for the desktop entry.
|
||||
*
|
||||
* @param parent a QObject parent; you probably want to pass in 0
|
||||
* @param args a list of strings containing one entry: the service id
|
||||
*/
|
||||
ContainmentActions(QObject *parent, const QVariantList &args);
|
||||
|
||||
/**
|
||||
* This method is called once the containmentactions is loaded or settings are changed.
|
||||
*
|
||||
* @param config Config group to load settings
|
||||
**/
|
||||
virtual void init(const KConfigGroup &config);
|
||||
|
||||
/**
|
||||
* When the containmentactions needs to be configured before being usable, this
|
||||
* method can be called to denote that action is required
|
||||
*
|
||||
* @param needsConfiguring true if the applet needs to be configured,
|
||||
* or false if it doesn't
|
||||
*/
|
||||
void setConfigurationRequired(bool needsConfiguring = true);
|
||||
|
||||
private:
|
||||
friend class ContainmentActionsPackage;
|
||||
friend class ContainmentActionsPrivate;
|
||||
ContainmentActionsPrivate *const d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
/**
|
||||
* Register a containmentactions when it is contained in a loadable module
|
||||
*/
|
||||
#define K_EXPORT_PLASMA_CONTAINMENTACTIONS(libname, classname) \
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
|
||||
K_EXPORT_PLUGIN(factory("plasma_containmentactions_" #libname)) \
|
||||
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
|
||||
|
||||
#endif // PLASMA_CONTAINMENTACTIONS_H
|
93
plasma/containmentactionspluginsconfig.cpp
Normal file
93
plasma/containmentactionspluginsconfig.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 "containmentactionspluginsconfig.h"
|
||||
#include "private/containmentactionspluginsconfig_p.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QString>
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
#include "containmentactions.h"
|
||||
|
||||
using namespace Plasma;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
ContainmentActionsPluginsConfig::ContainmentActionsPluginsConfig()
|
||||
: d(new ContainmentActionsPluginsConfigPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
ContainmentActionsPluginsConfig::ContainmentActionsPluginsConfig(const ContainmentActionsPluginsConfig &other)
|
||||
: d(new ContainmentActionsPluginsConfigPrivate(this))
|
||||
{
|
||||
d->plugins = other.d->plugins;
|
||||
}
|
||||
|
||||
ContainmentActionsPluginsConfig& ContainmentActionsPluginsConfig::operator=(const ContainmentActionsPluginsConfig &other)
|
||||
{
|
||||
d->plugins = other.d->plugins;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ContainmentActionsPluginsConfig::~ContainmentActionsPluginsConfig()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ContainmentActionsPluginsConfig::clear()
|
||||
{
|
||||
d->plugins.clear();
|
||||
}
|
||||
|
||||
void ContainmentActionsPluginsConfig::remove(QEvent *trigger)
|
||||
{
|
||||
QString s = ContainmentActions::eventToString(trigger);
|
||||
d->plugins.remove(s);
|
||||
}
|
||||
|
||||
void ContainmentActionsPluginsConfig::addPlugin(QEvent *trigger, const QString &name)
|
||||
{
|
||||
QString s = ContainmentActions::eventToString(trigger);
|
||||
d->plugins.insert(s, name);
|
||||
}
|
||||
|
||||
void ContainmentActionsPluginsConfig::addPlugin(Qt::KeyboardModifiers modifiers, Qt::MouseButton button, const QString &name)
|
||||
{
|
||||
QMouseEvent event(QEvent::MouseButtonPress, QPoint(), button, button, modifiers);
|
||||
QString s = ContainmentActions::eventToString(&event);
|
||||
d->plugins.insert(s, name);
|
||||
}
|
||||
|
||||
void ContainmentActionsPluginsConfig::addPlugin(Qt::KeyboardModifiers modifiers, Qt::Orientation wheelDirection, const QString &name)
|
||||
{
|
||||
//most of those parameters are just fillers
|
||||
QWheelEvent event(QPoint(0,0), 0, Qt::NoButton, modifiers, wheelDirection);
|
||||
QString s = ContainmentActions::eventToString(&event);
|
||||
d->plugins.insert(s, name);
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
90
plasma/containmentactionspluginsconfig.h
Normal file
90
plasma/containmentactionspluginsconfig.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 PLASMA_CONTAINMENTACTIONSPLUGINSCONFIG_H
|
||||
#define PLASMA_CONTAINMENTACTIONSPLUGINSCONFIG_H
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
#include <Qt>
|
||||
|
||||
class QString;
|
||||
class QEvent;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ContainmentActionsPluginsConfigPrivate;
|
||||
|
||||
/**
|
||||
* @class ContainmentActionsPluginsConfig plasma/containmentactionspluginsconfig.h <Plasma/ContainmentActionsPluginsConfig>
|
||||
*
|
||||
* @short A class that holds a map of triggers to plugin names
|
||||
* @since 4.4
|
||||
*/
|
||||
class PLASMA_EXPORT ContainmentActionsPluginsConfig
|
||||
{
|
||||
|
||||
public:
|
||||
ContainmentActionsPluginsConfig();
|
||||
ContainmentActionsPluginsConfig(const ContainmentActionsPluginsConfig &other);
|
||||
~ContainmentActionsPluginsConfig();
|
||||
ContainmentActionsPluginsConfig& operator=(const ContainmentActionsPluginsConfig &other);
|
||||
|
||||
/**
|
||||
* clears everything
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* removes @p trigger
|
||||
* @see addPlugin for an explanation of the @p trigger
|
||||
*/
|
||||
void remove(QEvent *trigger);
|
||||
|
||||
/**
|
||||
* Sets @p trigger to plugin @p name
|
||||
* if you're passing the trigger as an event, the following events are currently understood:
|
||||
* -mouse press and release events: button and modifiers
|
||||
* -mouse wheel events: direction and modifiers
|
||||
* both traditional and graphicsscene events are supported.
|
||||
*/
|
||||
void addPlugin(QEvent *trigger, const QString &name);
|
||||
|
||||
/**
|
||||
* Sets trigger described by @p modifiers and @p button to plugin @p name
|
||||
*/
|
||||
void addPlugin(Qt::KeyboardModifiers modifiers, Qt::MouseButton button, const QString &name);
|
||||
|
||||
/**
|
||||
* Sets trigger described by @p modifiers and @p wheelDirection to plugin @p name
|
||||
*/
|
||||
void addPlugin(Qt::KeyboardModifiers modifiers, Qt::Orientation wheelDirection, const QString &name);
|
||||
|
||||
private:
|
||||
ContainmentActionsPluginsConfigPrivate *const d;
|
||||
|
||||
friend class ContainmentActionsPluginsConfigPrivate;
|
||||
friend class Containment;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
742
plasma/corona.cpp
Normal file
742
plasma/corona.cpp
Normal file
@ -0,0 +1,742 @@
|
||||
/*
|
||||
* Copyright 2007 Matt Broadstone <mbroadst@gmail.com>
|
||||
* Copyright 2007-2011 Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2007 Riccardo Iaconelli <riccardo@kde.org>
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 "corona.h"
|
||||
#include "private/corona_p.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QGraphicsGridLayout>
|
||||
#include <QMimeData>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <kaction.h>
|
||||
#include <kdebug.h>
|
||||
#include <kiconloader.h>
|
||||
#include <klocalizedstring.h>
|
||||
#include <kshortcutsdialog.h>
|
||||
#include <kwindowsystem.h>
|
||||
|
||||
#include "abstractdialogmanager.h"
|
||||
#include "containment.h"
|
||||
#include "containmentactionspluginsconfig.h"
|
||||
#include "pluginloader.h"
|
||||
#include "private/applet_p.h"
|
||||
#include "private/containment_p.h"
|
||||
|
||||
using namespace Plasma;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
bool CoronaPrivate::s_positioningContainments = false;
|
||||
|
||||
Corona::Corona(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new CoronaPrivate(this))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Corona ctor start";
|
||||
#endif
|
||||
d->init();
|
||||
//setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel)));
|
||||
}
|
||||
|
||||
Corona::~Corona()
|
||||
{
|
||||
KConfigGroup trans(KSharedConfig::openConfig(), "PlasmaTransientsConfig");
|
||||
trans.deleteGroup();
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Corona::setAppletMimeType(const QString &type)
|
||||
{
|
||||
d->mimetype = type;
|
||||
}
|
||||
|
||||
QString Corona::appletMimeType()
|
||||
{
|
||||
return d->mimetype;
|
||||
}
|
||||
|
||||
void Corona::setDefaultContainmentPlugin(const QString &name)
|
||||
{
|
||||
// we could check if it is in:
|
||||
// Containment::listContainments().contains(name) ||
|
||||
// Containment::listContainments(QString(), QCoreApplication::instance()->applicationName()).contains(name)
|
||||
// but that seems like overkill
|
||||
d->defaultContainmentPlugin = name;
|
||||
}
|
||||
|
||||
QString Corona::defaultContainmentPlugin() const
|
||||
{
|
||||
return d->defaultContainmentPlugin;
|
||||
}
|
||||
|
||||
void Corona::saveLayout(const QString &configName) const
|
||||
{
|
||||
KSharedConfigPtr c;
|
||||
|
||||
if (configName.isEmpty() || configName == d->configName) {
|
||||
c = config();
|
||||
} else {
|
||||
c = KSharedConfig::openConfig(configName, KConfig::SimpleConfig);
|
||||
}
|
||||
|
||||
d->saveLayout(c);
|
||||
}
|
||||
|
||||
void Corona::exportLayout(KConfigGroup &config, QList<Containment*> containments)
|
||||
{
|
||||
foreach (const QString &group, config.groupList()) {
|
||||
KConfigGroup cg(&config, group);
|
||||
cg.deleteGroup();
|
||||
}
|
||||
|
||||
//temporarily unlock so that removal works
|
||||
ImmutabilityType oldImm = immutability();
|
||||
d->immutability = Mutable;
|
||||
|
||||
KConfigGroup dest(&config, "Containments");
|
||||
KConfigGroup dummy;
|
||||
foreach (Plasma::Containment *c, containments) {
|
||||
c->save(dummy);
|
||||
c->config().reparent(&dest);
|
||||
|
||||
//ensure the containment is unlocked
|
||||
//this is done directly because we have to bypass any SystemImmutable checks
|
||||
c->Applet::d->immutability = Mutable;
|
||||
foreach (Applet *a, c->applets()) {
|
||||
a->d->immutability = Mutable;
|
||||
}
|
||||
|
||||
c->destroy(false);
|
||||
}
|
||||
|
||||
//restore immutability
|
||||
d->immutability = oldImm;
|
||||
|
||||
config.sync();
|
||||
}
|
||||
|
||||
void Corona::requestConfigSync()
|
||||
{
|
||||
// constant controlling how long between requesting a configuration sync
|
||||
// and one happening should occur. currently 10 seconds
|
||||
static const int CONFIG_SYNC_TIMEOUT = 10000;
|
||||
|
||||
// TODO: should we check into our immutability before doing this?
|
||||
|
||||
//NOTE: this is a pretty simplistic model: we simply save no more than CONFIG_SYNC_TIMEOUT
|
||||
// after the first time this is called. not much of a heuristic for save points, but
|
||||
// it should at least compress these activities a bit and provide a way for applet
|
||||
// authors to ween themselves from the sync() disease. A more interesting/dynamic
|
||||
// algorithm for determining when to actually sync() to disk might be better, though.
|
||||
if (!d->configSyncTimer->isActive()) {
|
||||
d->configSyncTimer->start(CONFIG_SYNC_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
void Corona::requireConfigSync()
|
||||
{
|
||||
d->syncConfig();
|
||||
}
|
||||
|
||||
void Corona::initializeLayout(const QString &configName)
|
||||
{
|
||||
clearContainments();
|
||||
loadLayout(configName);
|
||||
|
||||
if (d->containments.isEmpty()) {
|
||||
loadDefaultLayout();
|
||||
if (!d->containments.isEmpty()) {
|
||||
requestConfigSync();
|
||||
}
|
||||
}
|
||||
|
||||
if (config()->isImmutable()) {
|
||||
setImmutability(SystemImmutable);
|
||||
} else {
|
||||
KConfigGroup coronaConfig(config(), "General");
|
||||
setImmutability((ImmutabilityType)coronaConfig.readEntry("immutability", (int)Mutable));
|
||||
}
|
||||
}
|
||||
|
||||
void Corona::loadLayout(const QString &configName)
|
||||
{
|
||||
if (!configName.isEmpty() && configName != d->configName) {
|
||||
// if we have a new config name passed in, then use that as the config file for this Corona
|
||||
d->config = 0;
|
||||
d->configName = configName;
|
||||
}
|
||||
|
||||
KConfigGroup conf(config(), QString());
|
||||
d->importLayout(conf, false);
|
||||
}
|
||||
|
||||
QList<Plasma::Containment *> Corona::importLayout(const KConfigGroup &conf)
|
||||
{
|
||||
return d->importLayout(conf, true);
|
||||
}
|
||||
|
||||
Containment *Corona::containmentForScreen(int screen, int desktop) const
|
||||
{
|
||||
foreach (Containment *containment, d->containments) {
|
||||
if (containment->screen() == screen &&
|
||||
(desktop < 0 || containment->desktop() == desktop) &&
|
||||
(containment->containmentType() == Containment::DesktopContainment ||
|
||||
containment->containmentType() == Containment::CustomContainment)) {
|
||||
return containment;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Containment *Corona::containmentForScreen(int screen, int desktop,
|
||||
const QString &defaultPluginIfNonExistent, const QVariantList &defaultArgs)
|
||||
{
|
||||
Containment *containment = containmentForScreen(screen, desktop);
|
||||
if (!containment && !defaultPluginIfNonExistent.isEmpty()) {
|
||||
// screen requests are allowed to bypass immutability
|
||||
if (screen >= 0 && screen < numScreens() &&
|
||||
desktop >= -1 && desktop < KWindowSystem::numberOfDesktops()) {
|
||||
containment = d->addContainment(defaultPluginIfNonExistent, defaultArgs, 0);
|
||||
if (containment) {
|
||||
containment->setScreen(screen, desktop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return containment;
|
||||
}
|
||||
|
||||
QList<Containment*> Corona::containments() const
|
||||
{
|
||||
return d->containments;
|
||||
}
|
||||
|
||||
void Corona::clearContainments()
|
||||
{
|
||||
foreach (Containment *containment, d->containments) {
|
||||
containment->clearApplets();
|
||||
}
|
||||
}
|
||||
|
||||
KSharedConfigPtr Corona::config() const
|
||||
{
|
||||
if (!d->config) {
|
||||
d->config = KSharedConfig::openConfig(d->configName, KConfig::SimpleConfig);
|
||||
}
|
||||
|
||||
return d->config;
|
||||
}
|
||||
|
||||
Containment *Corona::addContainment(const QString &name, const QVariantList &args)
|
||||
{
|
||||
if (d->immutability == Mutable) {
|
||||
return d->addContainment(name, args, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Corona::numScreens() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
QRect Corona::screenGeometry(int id) const
|
||||
{
|
||||
return qApp->desktop()->screenGeometry(id);
|
||||
}
|
||||
|
||||
QRegion Corona::availableScreenRegion(int id) const
|
||||
{
|
||||
return QRegion(screenGeometry(id));
|
||||
}
|
||||
|
||||
void Corona::loadDefaultLayout()
|
||||
{
|
||||
}
|
||||
|
||||
void Corona::setPreferredToolBoxPlugin(const Containment::Type type, const QString &plugin)
|
||||
{
|
||||
d->toolBoxPlugins[type] = plugin;
|
||||
}
|
||||
|
||||
QString Corona::preferredToolBoxPlugin(const Containment::Type type) const
|
||||
{
|
||||
return d->toolBoxPlugins.value(type);
|
||||
}
|
||||
|
||||
ImmutabilityType Corona::immutability() const
|
||||
{
|
||||
return d->immutability;
|
||||
}
|
||||
|
||||
void Corona::setImmutability(const ImmutabilityType immutable)
|
||||
{
|
||||
if (d->immutability == immutable || d->immutability == SystemImmutable) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "setting immutability to" << immutable;
|
||||
#endif
|
||||
d->immutability = immutable;
|
||||
d->updateContainmentImmutability();
|
||||
//tell non-containments that might care (like plasmaapp or a custom corona)
|
||||
emit immutabilityChanged(immutable);
|
||||
|
||||
//update our actions
|
||||
QAction *action = d->actions.action("lock widgets");
|
||||
if (action) {
|
||||
if (d->immutability == SystemImmutable) {
|
||||
action->setEnabled(false);
|
||||
action->setVisible(false);
|
||||
} else {
|
||||
bool unlocked = d->immutability == Mutable;
|
||||
action->setText(unlocked ? i18n("Lock Widgets") : i18n("Unlock Widgets"));
|
||||
action->setIcon(KDE::icon(unlocked ? "object-locked" : "object-unlocked"));
|
||||
action->setEnabled(true);
|
||||
action->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (d->immutability != SystemImmutable) {
|
||||
KConfigGroup cg(config(), "General");
|
||||
|
||||
// we call the dptr member directly for locked since isImmutable()
|
||||
// also checks kiosk and parent containers
|
||||
cg.writeEntry("immutability", (int)d->immutability);
|
||||
requestConfigSync();
|
||||
}
|
||||
}
|
||||
|
||||
QList<Plasma::Location> Corona::freeEdges(int screen) const
|
||||
{
|
||||
QList<Plasma::Location> freeEdges;
|
||||
freeEdges << Plasma::TopEdge << Plasma::BottomEdge
|
||||
<< Plasma::LeftEdge << Plasma::RightEdge;
|
||||
|
||||
foreach (Containment *containment, containments()) {
|
||||
if (containment->screen() == screen &&
|
||||
freeEdges.contains(containment->location())) {
|
||||
freeEdges.removeAll(containment->location());
|
||||
}
|
||||
}
|
||||
|
||||
return freeEdges;
|
||||
}
|
||||
|
||||
QAction *Corona::action(QString name) const
|
||||
{
|
||||
return d->actions.action(name);
|
||||
}
|
||||
|
||||
void Corona::addAction(QString name, QAction *action)
|
||||
{
|
||||
d->actions.addAction(name, action);
|
||||
}
|
||||
|
||||
KAction* Corona::addAction(QString name)
|
||||
{
|
||||
return d->actions.addAction(name);
|
||||
}
|
||||
|
||||
QList<QAction*> Corona::actions() const
|
||||
{
|
||||
return d->actions.actions();
|
||||
}
|
||||
|
||||
void Corona::enableAction(const QString &name, bool enable)
|
||||
{
|
||||
QAction *action = d->actions.action(name);
|
||||
if (action) {
|
||||
action->setEnabled(enable);
|
||||
action->setVisible(enable);
|
||||
}
|
||||
}
|
||||
|
||||
void Corona::updateShortcuts()
|
||||
{
|
||||
QMutableListIterator<QWeakPointer<KActionCollection> > it(d->actionCollections);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
KActionCollection *collection = it.value().data();
|
||||
if (!collection) {
|
||||
// get rid of KActionCollections that have been deleted behind our backs
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
collection->readSettings();
|
||||
if (d->shortcutsDlg) {
|
||||
d->shortcutsDlg.data()->addCollection(collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Corona::addShortcuts(KActionCollection *newShortcuts)
|
||||
{
|
||||
d->actionCollections << newShortcuts;
|
||||
if (d->shortcutsDlg) {
|
||||
d->shortcutsDlg.data()->addCollection(newShortcuts);
|
||||
}
|
||||
}
|
||||
|
||||
void Corona::setContainmentActionsDefaults(Containment::Type containmentType, const ContainmentActionsPluginsConfig &config)
|
||||
{
|
||||
d->containmentActionsDefaults.insert(containmentType, config);
|
||||
}
|
||||
|
||||
ContainmentActionsPluginsConfig Corona::containmentActionsDefaults(Containment::Type containmentType)
|
||||
{
|
||||
return d->containmentActionsDefaults.value(containmentType);
|
||||
}
|
||||
|
||||
void Corona::setDialogManager(AbstractDialogManager *dialogManager)
|
||||
{
|
||||
d->dialogManager = dialogManager;
|
||||
}
|
||||
|
||||
AbstractDialogManager *Corona::dialogManager()
|
||||
{
|
||||
return d->dialogManager.data();
|
||||
}
|
||||
|
||||
CoronaPrivate::CoronaPrivate(Corona *corona)
|
||||
: q(corona),
|
||||
immutability(Mutable),
|
||||
mimetype("text/x-plasmoidservicename"),
|
||||
defaultContainmentPlugin("desktop"),
|
||||
config(0),
|
||||
configSyncTimer(new QTimer(corona)),
|
||||
delayedInitTimer(new QTimer(corona)),
|
||||
actions(corona)
|
||||
{
|
||||
if (QCoreApplication::instance()) {
|
||||
configName = QCoreApplication::instance()->applicationName() + "-appletsrc";
|
||||
} else {
|
||||
configName = "plasma-appletsrc";
|
||||
}
|
||||
}
|
||||
|
||||
CoronaPrivate::~CoronaPrivate()
|
||||
{
|
||||
qDeleteAll(containments);
|
||||
}
|
||||
|
||||
void CoronaPrivate::init()
|
||||
{
|
||||
delayedInitTimer->setInterval(100);
|
||||
delayedInitTimer->setSingleShot(true);
|
||||
QObject::connect(delayedInitTimer, SIGNAL(timeout()), q, SLOT(delayedContainmentInit()));
|
||||
configSyncTimer->setSingleShot(true);
|
||||
QObject::connect(configSyncTimer, SIGNAL(timeout()), q, SLOT(syncConfig()));
|
||||
|
||||
//some common actions
|
||||
actions.setConfigGroup("Shortcuts");
|
||||
|
||||
KAction *lockAction = actions.addAction("lock widgets");
|
||||
QObject::connect(lockAction, SIGNAL(triggered(bool)), q, SLOT(toggleImmutability()));
|
||||
lockAction->setText(i18n("Lock Widgets"));
|
||||
lockAction->setAutoRepeat(true);
|
||||
lockAction->setIcon(KDE::icon("object-locked"));
|
||||
lockAction->setData(Containment::ControlTool);
|
||||
lockAction->setShortcut(KShortcut("alt+d, l"));
|
||||
lockAction->setShortcutContext(Qt::ApplicationShortcut);
|
||||
|
||||
//FIXME this doesn't really belong here. desktop KCM maybe?
|
||||
//but should the shortcuts be per-app or really-global?
|
||||
//I don't know how to make kactioncollections use plasmarc
|
||||
KAction *action = actions.addAction("configure shortcuts");
|
||||
QObject::connect(action, SIGNAL(triggered()), q, SLOT(showShortcutConfig()));
|
||||
action->setText(i18n("Shortcut Settings"));
|
||||
action->setIcon(KDE::icon("configure-shortcuts"));
|
||||
action->setAutoRepeat(false);
|
||||
action->setData(Containment::ConfigureTool);
|
||||
//action->setShortcut(KShortcut("ctrl+h"));
|
||||
action->setShortcutContext(Qt::ApplicationShortcut);
|
||||
|
||||
//fake containment/applet actions
|
||||
KActionCollection *containmentActions = AppletPrivate::defaultActions(q); //containment has to start with applet stuff
|
||||
ContainmentPrivate::addDefaultActions(containmentActions); //now it's really containment
|
||||
actionCollections << &actions << AppletPrivate::defaultActions(q) << containmentActions;
|
||||
q->updateShortcuts();
|
||||
}
|
||||
|
||||
void CoronaPrivate::showShortcutConfig()
|
||||
{
|
||||
//show a kshortcutsdialog with the actions
|
||||
KShortcutsDialog *dlg = shortcutsDlg.data();
|
||||
if (!dlg) {
|
||||
dlg = new KShortcutsDialog();
|
||||
dlg->setModal(false);
|
||||
dlg->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
QObject::connect(dlg, SIGNAL(saved()), q, SIGNAL(shortcutsChanged()));
|
||||
|
||||
dlg->addCollection(&actions);
|
||||
QMutableListIterator<QWeakPointer<KActionCollection> > it(actionCollections);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
KActionCollection *collection = it.value().data();
|
||||
if (!collection) {
|
||||
// get rid of KActionCollections that have been deleted behind our backs
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
dlg->addCollection(collection);
|
||||
}
|
||||
}
|
||||
|
||||
KWindowSystem::setOnDesktop(dlg->winId(), KWindowSystem::currentDesktop());
|
||||
dlg->configure();
|
||||
dlg->raise();
|
||||
}
|
||||
|
||||
void CoronaPrivate::toggleImmutability()
|
||||
{
|
||||
if (immutability == Mutable) {
|
||||
q->setImmutability(UserImmutable);
|
||||
} else {
|
||||
q->setImmutability(Mutable);
|
||||
}
|
||||
}
|
||||
|
||||
void CoronaPrivate::saveLayout(KSharedConfigPtr cg) const
|
||||
{
|
||||
KConfigGroup containmentsGroup(cg, "Containments");
|
||||
foreach (const Containment *containment, containments) {
|
||||
QString cid = QString::number(containment->id());
|
||||
KConfigGroup containmentConfig(&containmentsGroup, cid);
|
||||
containment->save(containmentConfig);
|
||||
}
|
||||
}
|
||||
|
||||
void CoronaPrivate::updateContainmentImmutability()
|
||||
{
|
||||
foreach (Containment *c, containments) {
|
||||
// we need to tell each containment that immutability has been altered
|
||||
c->updateConstraints(ImmutableConstraint);
|
||||
}
|
||||
}
|
||||
|
||||
void CoronaPrivate::containmentDestroyed(QObject *obj)
|
||||
{
|
||||
// we do a static_cast here since it really isn't an Containment by this
|
||||
// point anymore since we are in the qobject dtor. we don't actually
|
||||
// try and do anything with it, we just need the value of the pointer
|
||||
// so this unsafe looking code is actually just fine.
|
||||
Containment* containment = static_cast<Plasma::Containment*>(obj);
|
||||
int index = containments.indexOf(containment);
|
||||
|
||||
if (index > -1) {
|
||||
containments.removeAt(index);
|
||||
q->requestConfigSync();
|
||||
}
|
||||
}
|
||||
|
||||
void CoronaPrivate::syncConfig()
|
||||
{
|
||||
q->config()->sync();
|
||||
emit q->configSynced();
|
||||
}
|
||||
|
||||
Containment *CoronaPrivate::addContainment(const QString &name, const QVariantList &args, uint id)
|
||||
{
|
||||
QString pluginName = name;
|
||||
Containment *containment = 0;
|
||||
Applet *applet = 0;
|
||||
|
||||
//kDebug() << "Loading" << name << args << id;
|
||||
|
||||
if (pluginName.isEmpty() || pluginName == "default") {
|
||||
// default to the desktop containment
|
||||
pluginName = defaultContainmentPlugin;
|
||||
}
|
||||
|
||||
bool loadingNull = pluginName == "null";
|
||||
if (!loadingNull) {
|
||||
applet = PluginLoader::self()->loadApplet(pluginName, id, args);
|
||||
containment = dynamic_cast<Containment*>(applet);
|
||||
if (containment) {
|
||||
containment->setParent(q);
|
||||
}
|
||||
}
|
||||
|
||||
if (!containment) {
|
||||
if (!loadingNull) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "loading of containment" << name << "failed.";
|
||||
#endif
|
||||
}
|
||||
|
||||
// in case we got a non-Containment from Applet::loadApplet or
|
||||
// a null containment was requested
|
||||
if (applet) {
|
||||
// the applet probably doesn't know what's hit it, so let's pretend it can be
|
||||
// initialized to make assumptions in the applet's dtor safer
|
||||
applet->init();
|
||||
delete applet;
|
||||
}
|
||||
applet = containment = new Containment(q, 0, id);
|
||||
|
||||
if (loadingNull) {
|
||||
containment->setDrawWallpaper(false);
|
||||
} else {
|
||||
containment->setFailedToLaunch(false);
|
||||
}
|
||||
|
||||
// we want to provide something and don't care about the failure to launch
|
||||
containment->setFormFactor(Plasma::Planar);
|
||||
}
|
||||
|
||||
// if this is a new containment, we need to ensure that there are no stale
|
||||
// configuration data around
|
||||
if (id == 0) {
|
||||
KConfigGroup conf(q->config(), "Containments");
|
||||
conf = KConfigGroup(&conf, QString::number(containment->id()));
|
||||
conf.deleteGroup();
|
||||
}
|
||||
|
||||
applet->d->isContainment = true;
|
||||
applet->d->setIsContainment(true, true);
|
||||
containments.append(containment);
|
||||
containmentsNeedingInit.append(containment);
|
||||
delayedInitTimer->start();
|
||||
|
||||
QObject::connect(containment, SIGNAL(destroyed(QObject*)),
|
||||
q, SLOT(containmentDestroyed(QObject*)));
|
||||
QObject::connect(containment, SIGNAL(configNeedsSaving()),
|
||||
q, SLOT(requestConfigSync()));
|
||||
QObject::connect(containment, SIGNAL(releaseVisualFocus()),
|
||||
q, SIGNAL(releaseVisualFocus()));
|
||||
QObject::connect(containment, SIGNAL(screenChanged(int,int,Plasma::Containment*)),
|
||||
q, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)));
|
||||
|
||||
return containment;
|
||||
}
|
||||
|
||||
void CoronaPrivate::delayedContainmentInit()
|
||||
{
|
||||
foreach (QWeakPointer<Containment> c, containmentsNeedingInit) {
|
||||
Containment *containment = c.data();
|
||||
if (!containment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
containment->init();
|
||||
KConfigGroup cg = containment->config();
|
||||
containment->restore(cg);
|
||||
containment->updateConstraints(Plasma::StartupCompletedConstraint);
|
||||
containment->save(cg);
|
||||
q->requestConfigSync();
|
||||
containment->flushPendingConstraintsEvents();
|
||||
emit q->containmentAdded(containment);
|
||||
}
|
||||
|
||||
containmentsNeedingInit.clear();
|
||||
}
|
||||
|
||||
QList<Plasma::Containment *> CoronaPrivate::importLayout(const KConfigGroup &conf, bool mergeConfig)
|
||||
{
|
||||
if (!conf.isValid()) {
|
||||
return QList<Containment *>();
|
||||
}
|
||||
|
||||
QList<Plasma::Containment *> newContainments;
|
||||
QSet<uint> containmentsIds;
|
||||
|
||||
foreach (Containment *containment, containments) {
|
||||
containmentsIds.insert(containment->id());
|
||||
}
|
||||
|
||||
KConfigGroup containmentsGroup(&conf, "Containments");
|
||||
|
||||
foreach (const QString &group, containmentsGroup.groupList()) {
|
||||
KConfigGroup containmentConfig(&containmentsGroup, group);
|
||||
|
||||
if (containmentConfig.entryMap().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint cid = group.toUInt();
|
||||
if (containmentsIds.contains(cid)) {
|
||||
cid = ++AppletPrivate::s_maxAppletId;
|
||||
} else if (cid > AppletPrivate::s_maxAppletId) {
|
||||
AppletPrivate::s_maxAppletId = cid;
|
||||
}
|
||||
|
||||
if (mergeConfig) {
|
||||
KConfigGroup realConf(q->config(), "Containments");
|
||||
realConf = KConfigGroup(&realConf, QString::number(cid));
|
||||
// in case something was there before us
|
||||
realConf.deleteGroup();
|
||||
containmentConfig.copyTo(&realConf);
|
||||
}
|
||||
|
||||
//kDebug() << "got a containment in the config, trying to make a" << containmentConfig.readEntry("plugin", QString()) << "from" << group;
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Adding Containment" << containmentConfig.readEntry("plugin", QString());
|
||||
#endif
|
||||
Containment *c = addContainment(containmentConfig.readEntry("plugin", QString()), QVariantList(), cid);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
|
||||
newContainments.append(c);
|
||||
containmentsIds.insert(c->id());
|
||||
|
||||
c->init();
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Init Containment" << c->pluginName();
|
||||
#endif
|
||||
c->restore(containmentConfig);
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Restored Containment" << c->pluginName();
|
||||
#endif
|
||||
}
|
||||
|
||||
foreach (Containment *containment, newContainments) {
|
||||
containment->updateConstraints(Plasma::StartupCompletedConstraint);
|
||||
containment->d->initApplets();
|
||||
emit q->containmentAdded(containment);
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Containment" << containment->name();
|
||||
#endif
|
||||
}
|
||||
|
||||
return newContainments;
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
|
||||
|
||||
#include "moc_corona.cpp"
|
404
plasma/corona.h
Normal file
404
plasma/corona.h
Normal file
@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright 2007 Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2007 Matt Broadstone <mbroadst@gmail.com>
|
||||
* Copyright 2012 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 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 PLASMA_CORONABASE_H
|
||||
#define PLASMA_CORONABASE_H
|
||||
|
||||
#include <plasma/containment.h>
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
class QAction;
|
||||
|
||||
class KAction;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class CoronaPrivate;
|
||||
class ContainmentActionsPluginsConfig;
|
||||
class AbstractDialogManager;
|
||||
|
||||
/**
|
||||
* @class CoronaBase plasma/CoronaBase.h <Plasma/CoronaBase>
|
||||
*
|
||||
* @short A bookkeeping Scene for Plasma::Applets
|
||||
*/
|
||||
class PLASMA_EXPORT Corona : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Corona(QObject * parent = 0);
|
||||
~Corona();
|
||||
|
||||
/**
|
||||
* Sets the mimetype of Drag/Drop items. Default is
|
||||
* text/x-plasmoidservicename
|
||||
*/
|
||||
void setAppletMimeType(const QString &mimetype);
|
||||
|
||||
/**
|
||||
* The current mime type of Drag/Drop items.
|
||||
*/
|
||||
QString appletMimeType();
|
||||
|
||||
/**
|
||||
* @return the default containment plugin type
|
||||
* @since 4.7
|
||||
*/
|
||||
QString defaultContainmentPlugin() const;
|
||||
|
||||
/**
|
||||
* @return all containments on this CoronaBase
|
||||
*/
|
||||
QList<Containment*> containments() const;
|
||||
|
||||
/**
|
||||
* Clear the CoronaBase from all applets.
|
||||
*/
|
||||
void clearContainments();
|
||||
|
||||
/**
|
||||
* Returns the config file used to store the configuration for this CoronaBase
|
||||
*/
|
||||
KSharedConfig::Ptr config() const;
|
||||
|
||||
/**
|
||||
* Adds a Containment to the CoronaBase
|
||||
*
|
||||
* @param name the plugin name for the containment, as given by
|
||||
* KPluginInfo::pluginName(). If an empty string is passed in, the default
|
||||
* containment plugin will be used (usually DesktopContainment). If the
|
||||
* string literal "null" is passed in, then no plugin will be loaded and
|
||||
* a simple Containment object will be created instead.
|
||||
* @param args argument list to pass to the containment
|
||||
*
|
||||
* @return a pointer to the containment on success, or 0 on failure. Failure can be
|
||||
* caused by too restrictive of an Immutability type, as containments cannot be added
|
||||
* when widgets are locked, or if the requested containment plugin can not be located
|
||||
* or successfully loaded.
|
||||
*/
|
||||
Containment *addContainment(const QString &name, const QVariantList &args = QVariantList());
|
||||
|
||||
/**
|
||||
* Returns the Containment, if any, for a given physical screen and desktop
|
||||
*
|
||||
* @param screen number of the physical screen to locate
|
||||
* @param desktop the virtual desktop) to locate; if < 0 then it will
|
||||
* simply return the first Containment associated with screen
|
||||
*/
|
||||
Containment *containmentForScreen(int screen, int desktop = -1) const;
|
||||
|
||||
/**
|
||||
* Returns the Containment for a given physical screen and desktop, creating one
|
||||
* if none exists
|
||||
*
|
||||
* @param screen number of the physical screen to locate
|
||||
* @param desktop the virtual desktop) to locate; if < 0 then it will
|
||||
* simply return the first Containment associated with screen
|
||||
* @param defaultPluginIfNonExistent the plugin to load by default; "null" is an empty
|
||||
* Containment and "default" creates the default plugin
|
||||
* @param defaultArgs optional arguments to pass in when creating a Containment if needed
|
||||
* @since 4.6
|
||||
*/
|
||||
Containment *containmentForScreen(int screen, int desktop,
|
||||
const QString &defaultPluginIfNonExistent,
|
||||
const QVariantList &defaultArgs = QVariantList());
|
||||
|
||||
/**
|
||||
* Returns the number of screens available to plasma.
|
||||
* Subclasses should override this method as the default
|
||||
* implementation returns a meaningless value.
|
||||
*/
|
||||
virtual int numScreens() const;
|
||||
|
||||
/**
|
||||
* Returns the geometry of a given screen.
|
||||
* Valid screen ids are 0 to numScreen()-1, or -1 for the full desktop geometry.
|
||||
* Subclasses should override this method as the default
|
||||
* implementation returns a meaningless value.
|
||||
*/
|
||||
virtual QRect screenGeometry(int id) const;
|
||||
|
||||
/**
|
||||
* Returns the available region for a given screen.
|
||||
* The available region excludes panels and similar windows.
|
||||
* Valid screen ids are 0 to numScreens()-1.
|
||||
* By default this method returns a rectangular region
|
||||
* equal to screenGeometry(id); subclasses that need another
|
||||
* behavior should override this method.
|
||||
*/
|
||||
virtual QRegion availableScreenRegion(int id) const;
|
||||
|
||||
/**
|
||||
* This method is useful in order to retrieve the list of available
|
||||
* screen edges for panel type containments.
|
||||
* @param screen the id of the screen to look for free edges.
|
||||
* @returns a list of free edges not filled with panel type containments.
|
||||
*/
|
||||
QList<Plasma::Location> freeEdges(int screen) const;
|
||||
|
||||
/**
|
||||
* Returns the QAction with the given name from our collection
|
||||
*/
|
||||
QAction *action(QString name) const;
|
||||
|
||||
/**
|
||||
* Adds the action to our collection under the given name
|
||||
*/
|
||||
void addAction(QString name, QAction *action);
|
||||
|
||||
/**
|
||||
* Returns all the actions in our collection
|
||||
*/
|
||||
QList<QAction*> actions() const;
|
||||
|
||||
/**
|
||||
* convenience function - enables or disables an action by name
|
||||
*
|
||||
* @param name the name of the action in our collection
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
void enableAction(const QString &name, bool enable);
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
* Updates keyboard shortcuts for all the CoronaBase's actions.
|
||||
* If you've added actions to the CoronaBase you'll need to
|
||||
* call this for them to be configurable.
|
||||
*/
|
||||
void updateShortcuts();
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
* Adds a set of actions to the shortcut config dialog.
|
||||
* don't use this on actions in the CoronaBase's own actioncollection,
|
||||
* those are handled automatically. this is for stuff outside of that.
|
||||
*/
|
||||
void addShortcuts(KActionCollection *newShortcuts);
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
* Creates an action in our collection under the given name
|
||||
* @return the new action
|
||||
* FIXME I'm wrapping so much of kactioncollection API now, maybe I should just expose the
|
||||
* collection itself :P
|
||||
*/
|
||||
KAction* addAction(QString name);
|
||||
|
||||
/**
|
||||
* @since 4.4
|
||||
* Sets the default containmentactions plugins for the given containment type
|
||||
*/
|
||||
void setContainmentActionsDefaults(Containment::Type containmentType, const ContainmentActionsPluginsConfig &config);
|
||||
|
||||
/**
|
||||
* @since 4.4
|
||||
* Returns the default containmentactions plugins for the given containment type
|
||||
*/
|
||||
ContainmentActionsPluginsConfig containmentActionsDefaults(Containment::Type containmentType);
|
||||
|
||||
/**
|
||||
* @param the AbstractDialogManager implementaion
|
||||
*
|
||||
* @since 4.5
|
||||
*/
|
||||
void setDialogManager(AbstractDialogManager *manager);
|
||||
|
||||
/**
|
||||
* @return the AbstractDialogManager that will show dialogs used by applets, like configuration dialogs
|
||||
*
|
||||
* @since 4.5
|
||||
*/
|
||||
AbstractDialogManager *dialogManager();
|
||||
|
||||
/**
|
||||
* Returns the name of the preferred plugin to be used as containment toolboxes.
|
||||
* CustomContainments and CustomPanelContainments can still override it as their liking. It's also not guaranteed that the plugin will actually exist.
|
||||
*
|
||||
* @param type the containment type of which we want to know the associated toolbox plugin
|
||||
* @since 4.6
|
||||
*/
|
||||
QString preferredToolBoxPlugin(const Containment::Type type) const;
|
||||
|
||||
/**
|
||||
* Imports an applet layout from a config file. The results will be added to the
|
||||
* current set of Containments.
|
||||
*
|
||||
* @param config the name of the config file to load from,
|
||||
* or the default config file if QString()
|
||||
* @return the list of containments that were loaded
|
||||
* @since 4.6
|
||||
*/
|
||||
QList<Plasma::Containment *> importLayout(const KConfigGroup &config);
|
||||
|
||||
/**
|
||||
* Exports a set of containments to a config file.
|
||||
*
|
||||
* @param config the config group to save to
|
||||
* @param containments the list of containments to save
|
||||
* @since 4.6
|
||||
*/
|
||||
void exportLayout(KConfigGroup &config, QList<Containment*> containments);
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Initializes the layout from a config file. This will first clear any existing
|
||||
* Containments, load a layout from the requested configuration file, request the
|
||||
* default layout if needed and update immutability.
|
||||
*
|
||||
* @param config the name of the config file to load from,
|
||||
* or the default config file if QString()
|
||||
*/
|
||||
void initializeLayout(const QString &config = QString());
|
||||
|
||||
/**
|
||||
* Load applet layout from a config file. The results will be added to the
|
||||
* current set of Containments.
|
||||
*
|
||||
* @param config the name of the config file to load from,
|
||||
* or the default config file if QString()
|
||||
*/
|
||||
void loadLayout(const QString &config = QString());
|
||||
|
||||
/**
|
||||
* Save applets layout to file
|
||||
* @param config the file to save to, or the default config file if QString()
|
||||
*/
|
||||
void saveLayout(const QString &config = QString()) const;
|
||||
|
||||
/**
|
||||
* @return The type of immutability of this CoronaBase
|
||||
*/
|
||||
ImmutabilityType immutability() const;
|
||||
|
||||
/**
|
||||
* Sets the immutability type for this CoronaBase (not immutable,
|
||||
* user immutable or system immutable)
|
||||
* @param immutable the new immutability type of this applet
|
||||
*/
|
||||
void setImmutability(const ImmutabilityType immutable);
|
||||
|
||||
/**
|
||||
* Schedules a flush-to-disk synchronization of the configuration state
|
||||
* at the next convenient moment.
|
||||
*/
|
||||
void requestConfigSync();
|
||||
|
||||
/**
|
||||
* Schedules a time sensitive flush-to-disk synchronization of the
|
||||
* configuration state. Since this method does not provide any sort of
|
||||
* event compression, it should only be used when an *immediate* disk
|
||||
* sync is *absolutely* required. Otherwise, use @see requestConfigSync()
|
||||
* which does do event compression.
|
||||
*/
|
||||
void requireConfigSync();
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* This signal indicates a new containment has been added to
|
||||
* the CoronaBase
|
||||
*/
|
||||
void containmentAdded(Plasma::Containment *containment);
|
||||
|
||||
/**
|
||||
* This signal indicates that a containment has been newly
|
||||
* associated (or dissociated) with a physical screen.
|
||||
*
|
||||
* @param wasScreen the screen it was associated with
|
||||
* @param isScreen the screen it is now associated with
|
||||
* @param containment the containment switching screens
|
||||
*/
|
||||
void screenOwnerChanged(int wasScreen, int isScreen, Plasma::Containment *containment);
|
||||
|
||||
/**
|
||||
* This signal indicates that an application launch, window
|
||||
* creation or window focus event was triggered. This is used, for instance,
|
||||
* to ensure that the Dashboard view in Plasma hides when such an event is
|
||||
* triggered by an item it is displaying.
|
||||
*/
|
||||
void releaseVisualFocus();
|
||||
|
||||
/**
|
||||
* This signal indicates that the configuration file was flushed to disc.
|
||||
*/
|
||||
void configSynced();
|
||||
|
||||
/**
|
||||
* This signal inicates that a change in available screen goemetry occurred.
|
||||
*/
|
||||
void availableScreenRegionChanged();
|
||||
|
||||
/**
|
||||
* emitted when immutability changes.
|
||||
* this is for use by things that don't get contraints events, like plasmaapp.
|
||||
* it's NOT for containments or applets or any of the other stuff on the scene.
|
||||
* if your code's not in shells/ it probably shouldn't be using it.
|
||||
*/
|
||||
void immutabilityChanged(Plasma::ImmutabilityType immutability);
|
||||
|
||||
/**
|
||||
* @since 4.3
|
||||
* emitted when the user changes keyboard shortcut settings
|
||||
* connect to this if you've put some extra shortcuts in your app
|
||||
* that are NOT in CoronaBase's actioncollection.
|
||||
* if your code's not in shells/ it probably shouldn't be using this function.
|
||||
* @see addShortcuts
|
||||
*/
|
||||
void shortcutsChanged();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Loads the default (system wide) layout for this user
|
||||
**/
|
||||
virtual void loadDefaultLayout();
|
||||
|
||||
/**
|
||||
* @return The preferred toolbox plugin name for a given containment type.
|
||||
* @param type the containment type of which we want to know the preferred toolbox plugin.
|
||||
* @param plugin the toolbox plugin name
|
||||
* @since 4.6
|
||||
*/
|
||||
void setPreferredToolBoxPlugin(const Containment::Type type, const QString &plugin);
|
||||
|
||||
/**
|
||||
* Sets the default containment plugin to try and load
|
||||
* @since 4.7
|
||||
*/
|
||||
void setDefaultContainmentPlugin(const QString &name);
|
||||
|
||||
private:
|
||||
CoronaPrivate *const d;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void containmentDestroyed(QObject*))
|
||||
Q_PRIVATE_SLOT(d, void syncConfig())
|
||||
Q_PRIVATE_SLOT(d, void toggleImmutability())
|
||||
Q_PRIVATE_SLOT(d, void showShortcutConfig())
|
||||
|
||||
friend class CoronaPrivate;
|
||||
friend class View;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
0
plasma/coronabase.h
Normal file
0
plasma/coronabase.h
Normal file
19
plasma/data/kconfigxt/libplasma-theme-global.kcfg
Normal file
19
plasma/data/kconfigxt/libplasma-theme-global.kcfg
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="plasmarc" />
|
||||
<group name="CachePolicies">
|
||||
<entry key="CacheTheme" type="Bool">
|
||||
<label>Whether or not to create an on-disk cache for the theme.</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
|
||||
<entry key="ThemeCacheKb" type="Int">
|
||||
<label>The maximum size of the on-disk Theme cache in kilobytes. Note that these files are sparse files, so the maximum size may not be used. Setting a larger size is therefore often quite safe.</label>
|
||||
<default>81920</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
|
4
plasma/data/kconfigxt/libplasma-theme-global.kcfgc
Normal file
4
plasma/data/kconfigxt/libplasma-theme-global.kcfgc
Normal file
@ -0,0 +1,4 @@
|
||||
File=libplasma-theme-global.kcfg
|
||||
ClassName=ThemeConfig
|
||||
Singleton=false
|
||||
Mutators=false
|
6
plasma/data/knewstuff/plasmoids.knsrc
Normal file
6
plasma/data/knewstuff/plasmoids.knsrc
Normal file
@ -0,0 +1,6 @@
|
||||
[KNewStuff3]
|
||||
ProvidersUrl=http://download.kde.org/ocs/providers.xml
|
||||
Categories=Plasmoid Script
|
||||
StandardResource=tmp
|
||||
InstallationCommand=plasmapkg -i %f
|
||||
UninstallCommand=plasmapkg -r %f
|
19
plasma/data/operations/dataengineservice.operations
Normal file
19
plasma/data/operations/dataengineservice.operations
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE kcfg SYSTEM
|
||||
"http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
|
||||
<kcfg>
|
||||
<group name="GetSource">
|
||||
<entry name="SourceName" type="String">
|
||||
<label>The name of the desired datasource.</label>
|
||||
</entry>
|
||||
<entry name="UUID" type="String">
|
||||
<label>Specify a UUID here.</label>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="ServiceForSource">
|
||||
<entry name="SourceName" type="String">
|
||||
<label>The name of the desired datasource's service.</label>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="GetSourceNames" />
|
||||
</kcfg>
|
12
plasma/data/operations/plasmoidservice.operations
Normal file
12
plasma/data/operations/plasmoidservice.operations
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE kcfg SYSTEM
|
||||
"http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
|
||||
<kcfg>
|
||||
<group name="GetPackage" />
|
||||
<group name="GetMetaData" />
|
||||
<group name="DataEngine">
|
||||
<entry name="EngineName" type="String">
|
||||
<label>The name of the engine we want to obtain.</label>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
47
plasma/data/operations/storage.operations
Normal file
47
plasma/data/operations/storage.operations
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE kcfg SYSTEM
|
||||
"http://www.kde.org/standards/kcfg/1.0/kcfg.xsd">
|
||||
<kcfg>
|
||||
<group name="save">
|
||||
<entry name="group" type="String">
|
||||
<label>Group the key/value saved belongs to</label>
|
||||
</entry>
|
||||
<entry name="key" type="String">
|
||||
<label>The key that indicizes the value in the storage</label>
|
||||
</entry>
|
||||
<entry name="data" type="Int">
|
||||
<label>The actual data to be stored.</label>
|
||||
</entry>
|
||||
<entry name="data" type="String">
|
||||
<label>The actual data to be stored.</label>
|
||||
</entry>
|
||||
<entry name="data" type="StringList">
|
||||
<label>The actual data to be stored.</label>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="retrieve">
|
||||
<entry name="group" type="String">
|
||||
<label>Group the key/value saved belongs to</label>
|
||||
</entry>
|
||||
<entry name="key" type="String">
|
||||
<label>The key that indicizes the value in the storage. If empty all group will be retrieved.</label>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="delete">
|
||||
<entry name="group" type="String">
|
||||
<label>Group the key/value saved belongs to</label>
|
||||
</entry>
|
||||
<entry name="key" type="String">
|
||||
<label>The key that indicizes the value in the storage. If empty all group will be deleted</label>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="expire">
|
||||
<entry name="group" type="String">
|
||||
<label>Group the key/value saved belongs to. If empty all ntries will be checked for expiration.</label>
|
||||
</entry>
|
||||
<entry name="age" type="UInt">
|
||||
<label>Set the age the stored data will expire in seconds. Default is 4 days.</label>
|
||||
<default>345600</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
66
plasma/data/services/plasma.protocol
Normal file
66
plasma/data/services/plasma.protocol
Normal file
@ -0,0 +1,66 @@
|
||||
[Protocol]
|
||||
protocol=plasma
|
||||
|
||||
exec=plasma-remote-helper %u
|
||||
input=none
|
||||
output=none
|
||||
|
||||
Icon=plasma
|
||||
Description=A protocol for Plasma services
|
||||
Description[ar]=ميفاق لخدمات بلازما
|
||||
Description[bg]=Протокол за услуги Plasma
|
||||
Description[bs]=Protokol Plazma usluga
|
||||
Description[ca]=Un protocol pels serveis del Plasma
|
||||
Description[ca@valencia]=Un protocol pels serveis del Plasma
|
||||
Description[cs]=Protokol pro služby Plasma
|
||||
Description[da]=En protokol til Plasma-tjenester
|
||||
Description[de]=Ein Protokoll für Plasma-Dienste
|
||||
Description[el]=Ένα πρωτόκολλο υπηρεσιών Plasma
|
||||
Description[es]=Un protocolo para los servicios de Plasma
|
||||
Description[et]=Plasma teenuste protokoll
|
||||
Description[eu]=Plasma zerbitzuentzako protokolo bat
|
||||
Description[fi]=Plasma-palvelujen yhteyskäytäntö
|
||||
Description[fr]=Un protocole pour les services Plasma
|
||||
Description[ga]=Prótacal le haghaidh seirbhísí Plasma
|
||||
Description[gl]=Un protocolo para servizos do Plasma
|
||||
Description[he]=פרוטוקול עבור הרכיבים של Plasma
|
||||
Description[hr]=Protokol za servise u Plasmi
|
||||
Description[hu]=Protokoll a Plazma-szolgáltatáshoz
|
||||
Description[ia]=un protocollo per servicios de Plasma
|
||||
Description[is]=Samskiptamáti fyrir Plasma-þjónustur
|
||||
Description[it]=Un protocollo per servizi plasma
|
||||
Description[ja]=Plasma サービスのためのプロトコル
|
||||
Description[kk]=Plasma қызметінің протоколы
|
||||
Description[km]=ពិធីការសម្រាប់សេវាកម្មប្លាស្មា
|
||||
Description[ko]=Plasma 서비스 프로토콜
|
||||
Description[lv]=Plasma servisu protokols
|
||||
Description[mr]=प्लाज्मा सेवांसाठी शिष्टाचार
|
||||
Description[nb]=En protokoll for plasma-tjenester
|
||||
Description[nds]=En Protokoll för Plasma-Deensten
|
||||
Description[nl]=Een protocol voor Plasma-services
|
||||
Description[pa]=ਪਲਾਜ਼ਮਾ ਸਰਵਿਸ ਲਈ ਪਰੋਟੋਕਾਲ
|
||||
Description[pl]=Protokół dla usług Plazmy
|
||||
Description[pt]=Um protocolo para os serviços do Plasma
|
||||
Description[pt_BR]=Protocolo para os serviços do Plasma
|
||||
Description[ro]=Un protocol pentru servicii Plasma
|
||||
Description[ru]=Протокол для служб Plasma
|
||||
Description[se]=Protokolla Plasma-bálvalusaid várás
|
||||
Description[sk]=Protokol pre Plasma služby
|
||||
Description[sl]=Protokol za storitve Plasme
|
||||
Description[sr]=Протокол за плазма сервисе
|
||||
Description[sr@ijekavian]=Протокол за плазма сервисе
|
||||
Description[sr@ijekavianlatin]=Protokol za plasma servise
|
||||
Description[sr@latin]=Protokol za plasma servise
|
||||
Description[sv]=Ett protokoll för Plasma-tjänster
|
||||
Description[tg]=Протоколи хидматҳои Plasma
|
||||
Description[tr]=Plasma servisleri için bir protokol
|
||||
Description[tt]=Plasma хезмәте өчен беркетмә
|
||||
Description[ug]=پلازما(Plasma) مۇلازىمىتىنىڭ كېلىشىمى
|
||||
Description[uk]=Протокол для служб Плазми
|
||||
Description[vi]=Một giao thức cho các dịch vụ Plasma
|
||||
Description[x-test]=xxA protocol for Plasma servicesxx
|
||||
Description[zh_CN]=Plasma 服务协议
|
||||
Description[zh_TW]=Plasma 服務協定
|
||||
|
||||
helper=true
|
||||
Class=:internet
|
95
plasma/data/servicetypes/plasma-applet.desktop
Normal file
95
plasma/data/servicetypes/plasma-applet.desktop
Normal file
@ -0,0 +1,95 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/Applet
|
||||
|
||||
Comment=Plasma applet
|
||||
Comment[ar]=بريمج بلازما
|
||||
Comment[as]=Plasma এপ্লেট
|
||||
Comment[ast]=Miniaplicación Plasma
|
||||
Comment[be@latin]=Aplet „Plasma”
|
||||
Comment[bg]=Аплет за Plasma
|
||||
Comment[bn]=প্লাসমা অ্যাপলেট
|
||||
Comment[bn_IN]=Plasma অ্যাপ্লেট
|
||||
Comment[bs]=Plazma aplet
|
||||
Comment[ca]=Miniaplicació del Plasma
|
||||
Comment[ca@valencia]=Miniaplicació del Plasma
|
||||
Comment[cs]=Plasma applet
|
||||
Comment[da]=Plasma-applet
|
||||
Comment[de]=Plasma-Miniprogramm
|
||||
Comment[el]=Μικροεφαρμογή plasma
|
||||
Comment[en_GB]=Plasma applet
|
||||
Comment[eo]=Plasma apleto
|
||||
Comment[es]=Miniaplicación para Plasma
|
||||
Comment[et]=Plasma aplett
|
||||
Comment[eu]=Plasma appleta
|
||||
Comment[fi]=Plasma-sovelma
|
||||
Comment[fr]=Applet Plasma
|
||||
Comment[fy]=Plasma Applet
|
||||
Comment[ga]=Feidhmchláirín Plasma
|
||||
Comment[gl]=Applet de Plasma
|
||||
Comment[gu]=પ્લાઝમા એપ્લેટ
|
||||
Comment[he]=יישומון של Plasma
|
||||
Comment[hi]=प्लासमा एप्पलेट
|
||||
Comment[hne]=प्लाज्मा एपलेट
|
||||
Comment[hr]=Plasma applet
|
||||
Comment[hsb]=Plasma applet
|
||||
Comment[hu]=Plasma-kisalkalmazás
|
||||
Comment[ia]=Applet Plasma
|
||||
Comment[id]=Applet Plasma
|
||||
Comment[is]=Plasma smáforrit
|
||||
Comment[it]=Applet Plasma
|
||||
Comment[ja]=Plasma アプレット
|
||||
Comment[kk]=Plasma апплеті
|
||||
Comment[km]=អាប់ភ្លេតប្លាស្មា
|
||||
Comment[kn]=ಪ್ಲಾಸ್ಮಾ ಅನ್ವಯಾಂಶ (ಆಪ್ಲೆಟ್)
|
||||
Comment[ko]=Plasma 애플릿
|
||||
Comment[ku]=Sepanoka Plasma
|
||||
Comment[lt]=Plasma įskiepis
|
||||
Comment[lv]=Plasma aplets
|
||||
Comment[mai]=प्लाजमा एप्पलेट
|
||||
Comment[ml]=പ്ലാസ്മ ലഘുപ്രയോഗം
|
||||
Comment[mr]=प्लाज्मा एप्लेट
|
||||
Comment[nb]=Plasma miniprogram
|
||||
Comment[nds]=Plasma-Lüttprogramm
|
||||
Comment[nl]=Plasma-applet
|
||||
Comment[nn]=Plasma-element
|
||||
Comment[pa]=ਪਾਲਜ਼ਮਾ ਐਪਲਿਟ
|
||||
Comment[pl]=Aplet Plazmy
|
||||
Comment[pt]='Applet' do Plasma
|
||||
Comment[pt_BR]=Miniaplicativo do Plasma
|
||||
Comment[ro]=Miniaplicație Plasma
|
||||
Comment[ru]=Виджет Plasma
|
||||
Comment[se]=Plasma-prográmmaš
|
||||
Comment[si]=Plasma යෙදුම්පත
|
||||
Comment[sk]=Plasma aplet
|
||||
Comment[sl]=Plasma programček
|
||||
Comment[sr]=Плазма аплет
|
||||
Comment[sr@ijekavian]=Плазма аплет
|
||||
Comment[sr@ijekavianlatin]=Plasma aplet
|
||||
Comment[sr@latin]=Plasma aplet
|
||||
Comment[sv]=Plasma-miniprogram
|
||||
Comment[ta]=பிளாஸ்மா ஆப்லெட்
|
||||
Comment[tg]=Барномаи Plasma
|
||||
Comment[th]=แอพเพล็ตของพลาสมา
|
||||
Comment[tr]=Plasma programcığı
|
||||
Comment[tt]=Plasma кушымтасы
|
||||
Comment[ug]=Plasma قوللانچاق
|
||||
Comment[uk]=Аплет Плазми
|
||||
Comment[vi]=Tiểu dụng Plasma
|
||||
Comment[wa]=Aplikete di Plasma
|
||||
Comment[x-test]=xxPlasma appletxx
|
||||
Comment[zh_CN]=Plasma 小程序
|
||||
Comment[zh_TW]=Plasma 小程式
|
||||
|
||||
[PropertyDef::X-Plasma-API]
|
||||
Type=QString
|
||||
|
||||
[PropertyDef::X-Plasma-DropMimeTypes]
|
||||
Type=QStringList
|
||||
|
||||
[PropertyDef::X-Plasma-DropUrlPatterns]
|
||||
Type=QStringList
|
||||
|
||||
[PropertyDef::X-Plasma-DefaultSize]
|
||||
Type=QSize
|
||||
|
83
plasma/data/servicetypes/plasma-containment.desktop
Normal file
83
plasma/data/servicetypes/plasma-containment.desktop
Normal file
@ -0,0 +1,83 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/Containment
|
||||
|
||||
Comment=Plasma applet container and background painter
|
||||
Comment[ar]=حاوية بريمج بلازما ورسام خلفية
|
||||
Comment[as]=Plasma এপ্লেটৰ টেমা আৰু পৃষ্ঠভূমিৰ চিত্ৰকাৰ
|
||||
Comment[ast]=Contenedor de miniaplicación Plasma y pintor del fondu
|
||||
Comment[be@latin]=Schovišča dla apletaŭ „Plasma” j malar fonu
|
||||
Comment[bg]=Контейнер за аплети на Plasma и рисуване на фона
|
||||
Comment[bs]=Sadržalac plazma apletâ i iscrtavač pozadine
|
||||
Comment[ca]=Contenidor de miniaplicació del Plasma i pintor de fons
|
||||
Comment[ca@valencia]=Contenidor de miniaplicació del Plasma i pintor de fons
|
||||
Comment[cs]=Kontejner apletů a vykreslovač pozadí Plasma
|
||||
Comment[da]=Beholder og baggrundstegning til Plasma-applets
|
||||
Comment[de]=Plasma-Programmcontainer und Hintergrund-Zeichnung
|
||||
Comment[el]=Υποδοχέας μικροεφαρμογών Plasma και σχεδιαστής του φόντου
|
||||
Comment[en_GB]=Plasma applet container and background painter
|
||||
Comment[eo]=Plasma apletujo kaj fonpentrilo
|
||||
Comment[es]=Contenedor de miniaplicaciones para Plasma y pintor del fondo
|
||||
Comment[et]=Plasma apleti konteiner ja tausta joonistaja
|
||||
Comment[eu]=Plasma appletaren edukiontzia eta hondoa margotzekoa
|
||||
Comment[fi]=Plasma sovelmasisällyttäjä ja taustapiirtäjä
|
||||
Comment[fr]=Conteneur d'applet Plasma et affichage d'arrière-plan
|
||||
Comment[fy]=Plasma applet container en eftergrûn skilder
|
||||
Comment[ga]=Coimeádán feidhmchláiríní Plasma agus péintéir cúlra
|
||||
Comment[gl]=Un contedor de applet de Plasma e pintor do fondo
|
||||
Comment[gu]=પ્લાઝમા એપ્લેટ ધરાવનાર અને પાશ્ચભાગ રંગનાર
|
||||
Comment[he]=תוחם של יישומון Plasma וצובע הרקע
|
||||
Comment[hne]=प्लाज्मा एपलेट कंटेनर अउ पिछोत अंगना पुतइया
|
||||
Comment[hr]=Spremnik za Plasmin applet i crtač pozadine
|
||||
Comment[hsb]=Plasma-container za applet a molowadło pozadka
|
||||
Comment[hu]=Tartóelem és háttérrajzoló Plasma-kisalkalmazásokhoz
|
||||
Comment[ia]=Receptaculo applet Plasma e pictor de fundo
|
||||
Comment[id]=Applet pengisi dan penggambar latar belakang Plasma
|
||||
Comment[is]=Grunnur fyrir Plasma smáforrit og bakgrunnslitun
|
||||
Comment[it]=Contenitore applet Plasma e disegnatore dello sfondo
|
||||
Comment[ja]=Plasma アプレットの入れ物、背景の描画
|
||||
Comment[kk]=Plasma апплет контейнері және ая боятқышы
|
||||
Comment[km]=ឧបករណ៍ផ្ទុកអាប់ភ្លេតប្លាស្មា និងកម្មវិធីគូរផ្ទៃខាងក្រោយ
|
||||
Comment[kn]=ಪ್ಲಾಸ್ಮಾ ಅನ್ವಯಾಂಶ (ಆಪ್ಲೆಟ್) ಧಾರಕ (ಕಂಟೈನರ್)ಮತ್ತು ಹಿನ್ನೆಲೆ ಬಣ್ಣಗಾರ (ಪೇಯಿಂಟರ್)
|
||||
Comment[ko]=Plasma 애플릿 컨테이너 및 배경 칠하는 도구
|
||||
Comment[ku]=Embarvanê sepanoka Plasma û nexşevanê rûerdê
|
||||
Comment[lt]=Plasma įskiepio dėklas ir fono paišiklis
|
||||
Comment[lv]=Plasma sīkrīku konteiners un fona zīmētājs
|
||||
Comment[mai]=प्लाजमा एप्पलेट कंटेनर आओर पृष्ठभूमि पेंटर
|
||||
Comment[ml]=പ്ലാസ്മ ലഘുപ്രയോഗം കണ്ടൈനറും പശ്ചാത്തല പെയിന്ററും
|
||||
Comment[mr]=प्लाज्मा एप्लेट कंटेनर व बेकग्राउंड पेंटर
|
||||
Comment[nb]=Plasma beholder for miniprogram og bakgrunnsopptegner
|
||||
Comment[nds]=Plasma-Gelaats för Lüttprogrammen un Achtergrundpleger
|
||||
Comment[nl]=Container voor plasma-applets en achtergrondinvulling
|
||||
Comment[nn]=Plasma-behaldar og bakgrunnsmålar
|
||||
Comment[pa]=ਪਲਾਜ਼ਮਾ ਐਪਲਿਟ ਕੰਨਟੇਨਰ ਅਤੇ ਬੈਕਗਰਾਊਂਡ ਪੇਂਟਰ
|
||||
Comment[pl]=Kontener apletu Plazmy i rysowanie tła
|
||||
Comment[pt]=Contentor de 'applets' do Plasma e pintor do fundo
|
||||
Comment[pt_BR]=Recipiente de miniaplicativos do Plasma e pintor de plano de fundo
|
||||
Comment[ro]=Container de miniaplicații Plasma și desenator de fundal
|
||||
Comment[ru]=Контейнер и модуль отрисовки виджета Plasma
|
||||
Comment[se]=Plasma-prográmmašlihtti ja -duogášmálejeaddji
|
||||
Comment[si]=Plasma යෙදුම්පත් බහලුම සහ පසුබීම්
|
||||
Comment[sk]=Kontajner apletu a vykresľovanie pozadia Plasma
|
||||
Comment[sl]=Vsebnik programčkov in izrisovalnik ozadja za Plasmo
|
||||
Comment[sr]=Садржалац плазма аплетâ и исцртавач позадине
|
||||
Comment[sr@ijekavian]=Садржалац плазма аплетâ и исцртавач позадине
|
||||
Comment[sr@ijekavianlatin]=Sadržalac plasma apletâ i iscrtavač pozadine
|
||||
Comment[sr@latin]=Sadržalac plasma apletâ i iscrtavač pozadine
|
||||
Comment[sv]=Plasmaminiprogram-omgivning och bakgrundsuppritning
|
||||
Comment[ta]=பிளாஸ்மா ஆப்லெட் கொள்ளியும் பின்னணி வண்ணம்பூசியும்
|
||||
Comment[tg]=Системаи захиракунӣ ва тасвирии Plasma
|
||||
Comment[th]=ตัววาดพื้นหลังและตัวบรรจุแแอพเพล็ตของพลาสมา
|
||||
Comment[tr]=Plasma programcık içerici ve arkaplan oluşturucu
|
||||
Comment[tt]=Plasma кушымтаның контейнеры һәм сүрәтләү модуле
|
||||
Comment[ug]=Plasma قاچا ھەرىكىتى ۋە تەگلىك سىزغۇچ
|
||||
Comment[uk]=Контейнер аплетів плазми і малювання тла
|
||||
Comment[wa]=Contneu d' aplikete eyet pondeu do fond di plasma
|
||||
Comment[x-test]=xxPlasma applet container and background painterxx
|
||||
Comment[zh_CN]=Plasma 小程序容器及背景绘制器
|
||||
Comment[zh_TW]=Plasma 小程式容器與背景畫家
|
||||
|
||||
[PropertyDef::X-Plasma-ContainmentCategories]
|
||||
Type=QStringList
|
||||
|
||||
|
70
plasma/data/servicetypes/plasma-containmentactions.desktop
Normal file
70
plasma/data/servicetypes/plasma-containmentactions.desktop
Normal file
@ -0,0 +1,70 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/ContainmentActions
|
||||
|
||||
Comment=Plasma ContainmentActions
|
||||
Comment[ar]=Plasma ContainmentActions
|
||||
Comment[bg]=Действия за контейнера на Plasma
|
||||
Comment[bs]=Plazma radnje sadržalaca
|
||||
Comment[ca]=ContainmentActions del Plasma
|
||||
Comment[ca@valencia]=ContainmentActions del Plasma
|
||||
Comment[cs]=Akce plasma kontejneru
|
||||
Comment[da]=Plasma ContainmentActions
|
||||
Comment[de]=Plasma-Container-Aktionen
|
||||
Comment[el]=Ενέργειες Υποδοχέα Plasma
|
||||
Comment[en_GB]=Plasma ContainmentActions
|
||||
Comment[es]=ContainmentActions de Plasma
|
||||
Comment[et]=Plasma konteineritoimingud
|
||||
Comment[eu]=Plasma ContainmentActions
|
||||
Comment[fi]=Plasma ContainmentActions
|
||||
Comment[fr]=Plasma d'actions contenantes
|
||||
Comment[ga]=Gníomhartha Coimeádán Plasma
|
||||
Comment[gl]=ContainmentActions de Plasma
|
||||
Comment[he]=Plasma ContainmentActions
|
||||
Comment[hr]=Plasma ContainmentActions
|
||||
Comment[hu]=Plasma tartóműveletek
|
||||
Comment[ia]=Actiones de continemento Plasma
|
||||
Comment[id]=Plasma Aksi Berisi
|
||||
Comment[is]=Plasma ContainmentActions
|
||||
Comment[it]=ContainmentActions di Plasma
|
||||
Comment[ja]=Plasma コンテナアクション
|
||||
Comment[kk]=Plasma контейнер әрекеті
|
||||
Comment[km]=ប្លាស្មា ContainmentActions
|
||||
Comment[ko]=Plasma ContainmentActions
|
||||
Comment[ku]=Plasma ContainmentActions
|
||||
Comment[lt]=Plasma konteinerių veiksmai
|
||||
Comment[lv]=Plasma ietvara darbības
|
||||
Comment[mr]=प्लाज्मा कंटेनमेंट कृती
|
||||
Comment[nb]=Plasma ContainmentActions
|
||||
Comment[nds]=Plasma-Gelaatsakschonen
|
||||
Comment[nl]=Plasma Containeracties
|
||||
Comment[nn]=Plasma behaldarhandlingar
|
||||
Comment[pa]=ਪਲਾਜ਼ਮਾ ਕਨਟੇਨਮੈਂਟਐਕਸ਼ਨ
|
||||
Comment[pl]=Kontener Plazmy: akcje
|
||||
Comment[pt]=Acções do Contentor do Plasma
|
||||
Comment[pt_BR]=Ações do contêiner do Plasma
|
||||
Comment[ro]=AcțiuniContainer Plasma
|
||||
Comment[ru]=Действия для контейнеров Plasma
|
||||
Comment[se]=Plasma ContainmentActions
|
||||
Comment[sk]=Akcie Plasma
|
||||
Comment[sl]=Dejanja za vsebnik za Plasmo
|
||||
Comment[sr]=Плазма радње садржалаца
|
||||
Comment[sr@ijekavian]=Плазма радње садржалаца
|
||||
Comment[sr@ijekavianlatin]=Plasma radnje sadržalaca
|
||||
Comment[sr@latin]=Plasma radnje sadržalaca
|
||||
Comment[sv]=Plasma omgivningsåtgärder
|
||||
Comment[ta]=பிளாஸ்மா ContainmentActions
|
||||
Comment[tg]=Plasma ContainmentActions
|
||||
Comment[th]=การกระทำในส่วนบรรจุของพลาสมา
|
||||
Comment[tr]=Plasma İçerici Eylemleri
|
||||
Comment[tt]=Plasma контейнеры гамәлләре
|
||||
Comment[ug]=Plasma قاچا ھەرىكىتى
|
||||
Comment[uk]=Дії контейнерів Плазми
|
||||
Comment[wa]=Contneu d' accions di Plasma
|
||||
Comment[x-test]=xxPlasma ContainmentActionsxx
|
||||
Comment[zh_CN]=Plasma 容器动作
|
||||
Comment[zh_TW]=Plasma 容器動作
|
||||
|
||||
[PropertyDef::X-Plasma-HasConfigurationInterface]
|
||||
Type=bool
|
||||
|
83
plasma/data/servicetypes/plasma-dataengine.desktop
Normal file
83
plasma/data/servicetypes/plasma-dataengine.desktop
Normal file
@ -0,0 +1,83 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/DataEngine
|
||||
|
||||
Comment=Plasma Data Engine
|
||||
Comment[ar]=محرك بيانات بلازما
|
||||
Comment[as]=Plasma Data Engine
|
||||
Comment[ast]=Motor de datos Plasma
|
||||
Comment[be@latin]=Systema dostupu da źviestak „Plasma”
|
||||
Comment[bg]=Ядро за данни на Plasma
|
||||
Comment[bn]=প্লাসমা ডাটা ইঞ্জিন
|
||||
Comment[bn_IN]=Plasma ডাটা ইঞ্জিন
|
||||
Comment[bs]=Plazma datomotor
|
||||
Comment[ca]=Motor de dades del Plasma
|
||||
Comment[ca@valencia]=Motor de dades del Plasma
|
||||
Comment[cs]=Datový nástroj plasma
|
||||
Comment[da]=Plasma datamotor
|
||||
Comment[de]=Plasma-Daten-Treiber
|
||||
Comment[el]=Μηχανή δεδομένων Plasma
|
||||
Comment[en_GB]=Plasma Data Engine
|
||||
Comment[eo]=Plasma Datuma Motoro
|
||||
Comment[es]=Motor de datos para Plasma
|
||||
Comment[et]=Plasma andmemootor
|
||||
Comment[eu]=Plasmaren datu motorra
|
||||
Comment[fi]=Plasma-tietomoottori
|
||||
Comment[fr]=Moteur de données Plasma
|
||||
Comment[fy]=Plasma gegevensmotor
|
||||
Comment[ga]=Inneall Sonraí Plasma
|
||||
Comment[gl]=Motor de datos de plasma
|
||||
Comment[gu]=પ્લાઝમા માહિતી એન્જિન
|
||||
Comment[he]=מנוע מידע עבור Plasma
|
||||
Comment[hne]=प्लाज्मा डाटा इंजिन
|
||||
Comment[hr]=Plasmin podaktovni mehanizam
|
||||
Comment[hsb]=Datowa engine za Plasma
|
||||
Comment[hu]=Plasma adatkezelő
|
||||
Comment[ia]=Motor de datos de Plasma
|
||||
Comment[id]=Mesin Data Plasma
|
||||
Comment[is]=Plasma gagnavél
|
||||
Comment[it]=Motore dati Plasma
|
||||
Comment[ja]=Plasma データエンジン
|
||||
Comment[kk]=Plasma деректер тетігі
|
||||
Comment[km]=ម៉ាស៊ីនទិន្នន័យប្លាស្មា
|
||||
Comment[kn]=ಪ್ಲಾಸ್ಮಾ ದತ್ತ ಯಂತ್ರ
|
||||
Comment[ko]=Plasma 데이터 엔진
|
||||
Comment[ku]=Motora Dane ya Plasma
|
||||
Comment[lt]=Plasma duomenų varikliukas
|
||||
Comment[lv]=Plasma datu dzinējs
|
||||
Comment[mai]=प्लाजमा डेटा इंजन
|
||||
Comment[ml]=പ്ലാസ്മ ഡാറ്റ എഞ്ചിന്
|
||||
Comment[mr]=प्लाज्मा डेटा इंजिन
|
||||
Comment[nb]=Plasma datamotor
|
||||
Comment[nds]=Plasma-Datenkarn
|
||||
Comment[nl]=Plasma-gegevensengine
|
||||
Comment[nn]=Plasma-datamotor
|
||||
Comment[pa]=ਪਲਾਜ਼ਮਾ ਡਾਟਾ ਇੰਜਣ
|
||||
Comment[pl]=Silnik danych Plazmy
|
||||
Comment[pt]=Motor de Dados do Plasma
|
||||
Comment[pt_BR]=Mecanismo de dados do Plasma
|
||||
Comment[ro]=Motor de date Plasma
|
||||
Comment[ru]=Источник данных Plasma
|
||||
Comment[se]=Plasma-dáhtamohtor
|
||||
Comment[si]=Plasma දත්ත එංජිම
|
||||
Comment[sk]=Dátový nástroj Plasma
|
||||
Comment[sl]=Podatkovni pogon za Plasmo
|
||||
Comment[sq]=Motor të Dhënash Plasma
|
||||
Comment[sr]=Плазма датомотор
|
||||
Comment[sr@ijekavian]=Плазма датомотор
|
||||
Comment[sr@ijekavianlatin]=Plasma datomotor
|
||||
Comment[sr@latin]=Plasma datomotor
|
||||
Comment[sv]=Plasma datagränssnitt
|
||||
Comment[ta]=பிளாஸ்மா தரவு இயந்திரம்
|
||||
Comment[tg]=Системаи маълумотии Plasma
|
||||
Comment[th]=กลไกข้อมูลของพลาสมา
|
||||
Comment[tr]=Plasma Veri Motoru
|
||||
Comment[tt]=Plasma мәгълүмат коралы
|
||||
Comment[ug]=Plasma سانلىق-مەلۇمات ماتورى
|
||||
Comment[uk]=Рушій даних Плазми
|
||||
Comment[vi]=Cơ chế dữ liệu Plasma
|
||||
Comment[wa]=Moteur di dnêyes di Plasma
|
||||
Comment[x-test]=xxPlasma Data Enginexx
|
||||
Comment[zh_CN]=Plasma 数据引擎
|
||||
Comment[zh_TW]=Plasma 資料引擎
|
||||
|
86
plasma/data/servicetypes/plasma-packagestructure.desktop
Normal file
86
plasma/data/servicetypes/plasma-packagestructure.desktop
Normal file
@ -0,0 +1,86 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/PackageStructure
|
||||
Comment=Plasma package structure definition
|
||||
Comment[ar]=تعريف بنية حزمة بلازما
|
||||
Comment[as]=Plasma সৰঞ্জাম আকাৰৰ সংজ্ঞা
|
||||
Comment[ast]=Definición d'estructura de paquete Plasma
|
||||
Comment[be@latin]=Aznačeńnie struktury pakunka „Plasma”
|
||||
Comment[bg]=Структурно определение на пакет на Plasma
|
||||
Comment[bs]=Definicija strukture plazma paketa
|
||||
Comment[ca]=Definició de l'estructura d'un paquet Plasma
|
||||
Comment[ca@valencia]=Definició de l'estructura d'un paquet Plasma
|
||||
Comment[cs]=Definice struktury Plasma balíčku
|
||||
Comment[da]=Definition af pakkestruktur til Plasma
|
||||
Comment[de]=Plasma-Paket-Struktur-Definition
|
||||
Comment[el]=Ορισμός δομής πακέτου του Plasma
|
||||
Comment[en_GB]=Plasma package structure definition
|
||||
Comment[es]=Definición de estructura de paquete para Plasma
|
||||
Comment[et]=Plasma paketi struktuuri definitsioon
|
||||
Comment[eu]=Plasma paketearen egituraren definizioa
|
||||
Comment[fi]=Plasma-pakettirakenteen määritelmä
|
||||
Comment[fr]=Définition de la structure des paquetages Plasma
|
||||
Comment[fy]=Plasma pakket sstruktuer defenysje
|
||||
Comment[ga]=Sainmhíniú ar struchtúr pacáiste Plasma
|
||||
Comment[gl]=Definición da estrutura do paquete de Plasma
|
||||
Comment[gu]=પ્લાઝમા પેકેજ માળખાંની વ્યાખ્યા
|
||||
Comment[he]=הגדרת מבנה של חבילת Plasma
|
||||
Comment[hne]=प्लाज्मा पैकेज स्ट्रक्चर परिभासा
|
||||
Comment[hr]=Plasmina definicija strukture paketa
|
||||
Comment[hsb]=Strukturna definicija Plasma-pakćika
|
||||
Comment[hu]=Struktúraleíró Plasma-csomagokhoz
|
||||
Comment[ia]=Definition del structura de pacchetto de Plasma
|
||||
Comment[id]=Definisi struktur paket Plasma
|
||||
Comment[is]=Skilgreiningar Plasma pakkauppbyggingar
|
||||
Comment[it]=Definizione struttura pacchetto Plasma
|
||||
Comment[ja]=Plasma パッケージ構造の定義
|
||||
Comment[kk]=Plasma дестесінің құрамынын анықтауы
|
||||
Comment[km]=ការកំណត់រចនាសម្ព័ន្ធកញ្ចប់របស់ប្លាស្មា
|
||||
Comment[kn]=ಪ್ಲಾಸ್ಮಾ ಕಂತೆ (ಪ್ಯಾಕೇಜ್) ರಚನಾ ಲಕ್ಷಣ (ಡೆಫೆನಿಶನ್)
|
||||
Comment[ko]=Plasma 패키지 구조 정의
|
||||
Comment[ku]=Daxuyaniya çêbûna pakêta Plasma
|
||||
Comment[lt]=Plasma paketo struktūros aprašymas
|
||||
Comment[lv]=Plasma pakotņu struktūras definīcija
|
||||
Comment[mai]=प्लाजमा पैकेज संरचनाक परिभाषा
|
||||
Comment[ml]=പ്ലാസ്മ പാക്കേജ് സ്ട്രക്ചര് ഡെഫനിഷന്
|
||||
Comment[mr]=प्लाज्मा पेकेज संरचना व्याख्या
|
||||
Comment[nb]=Definisjon av Plasma pakkestruktur
|
||||
Comment[nds]=Paketstruktuur-Fastleggen vun Plasma
|
||||
Comment[nl]=Structuurdefinitie van plasmapakket
|
||||
Comment[nn]=Pakkestrukturdefinisjon for Plasma
|
||||
Comment[pa]=ਪਲਾਜ਼ਮਾ ਪੈਕੇਜ ਢਾਂਚਾ ਪਰਿਭਾਸ਼ਾ
|
||||
Comment[pl]=Definicja struktury pakietu Plazmy
|
||||
Comment[pt]=Definição da estrutura de pacotes do Plasma
|
||||
Comment[pt_BR]=Definição de estrutura de pacote do Plasma
|
||||
Comment[ro]=Definiție de structură a pachetului Plasma
|
||||
Comment[ru]=Определение структуры пакета Plasma
|
||||
Comment[se]=Plasma-páhkkaráhkadusdefinišuvdna
|
||||
Comment[sk]=Definícia štruktúry Plasma balíčkov
|
||||
Comment[sl]=Definicija strukture paketa za Plasmo
|
||||
Comment[sr]=Дефиниција структуре плазма пакета
|
||||
Comment[sr@ijekavian]=Дефиниција структуре плазма пакета
|
||||
Comment[sr@ijekavianlatin]=Definicija strukture plasma paketa
|
||||
Comment[sr@latin]=Definicija strukture plasma paketa
|
||||
Comment[sv]=Strukturdefinition av Plasma-paket
|
||||
Comment[ta]=பிளாஸ்மா பொதி வடிவமைப்பு வரையறை
|
||||
Comment[tg]=Барномаи муайянкунии сохтори Plasma
|
||||
Comment[th]=นิยามโครงสร้างแพกเกจของพลาสมา
|
||||
Comment[tr]=Plasma paketi yapı tanımlaması
|
||||
Comment[tt]=Plasma төргәк төзелешен билгеләү
|
||||
Comment[ug]=Plasma بوغچا قۇرۇلما ئېنىقلىمىسى
|
||||
Comment[uk]=Опис структури пакунка плазми
|
||||
Comment[vi]=Định nghĩa cấu trúc gói Plasma
|
||||
Comment[wa]=Definixha del sitructeure do pacaedje di Plasma
|
||||
Comment[x-test]=xxPlasma package structure definitionxx
|
||||
Comment[zh_CN]=Plasma 包结构定义
|
||||
Comment[zh_TW]=Plasma 套件結構定義
|
||||
|
||||
[PropertyDef::X-Plasma-PackageFileFilter]
|
||||
Type=QString
|
||||
|
||||
[PropertyDef::X-Plasma-PackageFileMimetypes]
|
||||
Type=QStringList
|
||||
|
||||
[PropertyDef::X-Plasma-ProvidesWidgetBrowser]
|
||||
Type=bool
|
||||
|
94
plasma/data/servicetypes/plasma-runner.desktop
Normal file
94
plasma/data/servicetypes/plasma-runner.desktop
Normal file
@ -0,0 +1,94 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/Runner
|
||||
|
||||
Comment=KRunner plugin
|
||||
Comment[ar]=ملحق KRunner
|
||||
Comment[as]=KRunner প্লাগ-ইন
|
||||
Comment[ast]=Complementu KRunner
|
||||
Comment[be@latin]=Plugin dla „KRunner”
|
||||
Comment[bg]=Приставка за KRunner
|
||||
Comment[bn]=কে-রানার প্লাগ-ইন
|
||||
Comment[bn_IN]=KRunner প্লাগ-ইন
|
||||
Comment[bs]=Priključak za K‑izvođač
|
||||
Comment[ca]=Connector del KRunner
|
||||
Comment[ca@valencia]=Connector del KRunner
|
||||
Comment[cs]=KRunner modul
|
||||
Comment[csb]=Wtëkôcz KRunner
|
||||
Comment[da]=KRunner-plugin
|
||||
Comment[de]=KRunner-Modul
|
||||
Comment[el]=Πρόσθετο του KRunner
|
||||
Comment[en_GB]=KRunner plugin
|
||||
Comment[es]=Complemento para KRunner
|
||||
Comment[et]=KRunneri plugin
|
||||
Comment[eu]=KRnner plugin-a
|
||||
Comment[fa]=وصله KRunner
|
||||
Comment[fi]=KRunner-liitännäinen
|
||||
Comment[fr]=Module KRunner
|
||||
Comment[fy]=KRunner plugin
|
||||
Comment[ga]=Breiseán KRunner
|
||||
Comment[gl]=Complemento KFileWrite
|
||||
Comment[gu]=KRunner પ્લગઈન
|
||||
Comment[he]=תוסף KRunner
|
||||
Comment[hi]=केरन्नर प्लगइन
|
||||
Comment[hne]=के-रनरइट प्लगइन
|
||||
Comment[hr]=Priključak Krunner
|
||||
Comment[hsb]=KRunner plugin
|
||||
Comment[hu]=KRunner-bővítmény
|
||||
Comment[ia]=Plugin KRunner
|
||||
Comment[id]=Plguin KRunner
|
||||
Comment[is]=KRunner íforrit
|
||||
Comment[it]=Plugin KRunner
|
||||
Comment[ja]=KRunner プラグイン
|
||||
Comment[kk]=KRunner плагині
|
||||
Comment[km]=កម្មវិធីជំនួយរបស់ KRunner
|
||||
Comment[kn]=ಕೆರನ್ನರ್ ಮಿಳಿತಾನ್ವಯ (ಪ್ಲಗಿನ್)
|
||||
Comment[ko]=KRunner 플러그인
|
||||
Comment[ku]=Pêveka KAjoker
|
||||
Comment[lt]=KRunner priedas
|
||||
Comment[lv]=KRunner spraudnis
|
||||
Comment[mai]=केरनर प्लगइन
|
||||
Comment[ml]=കെറണ്ണര് സംയോജകം
|
||||
Comment[mr]=KRunner प्लगइन
|
||||
Comment[nb]=KRunner-programtillegg
|
||||
Comment[nds]=KRunner-Moduul
|
||||
Comment[nl]=KRunner-plugin
|
||||
Comment[nn]=KRunner-tillegg
|
||||
Comment[pa]=ਕੇਰਨਰ ਪਲੱਗਇਨ
|
||||
Comment[pl]=Wtyczka KRunnera
|
||||
Comment[pt]='Plugin' do KRunner
|
||||
Comment[pt_BR]=Plugin do KRunner
|
||||
Comment[ro]=Modul KRunner
|
||||
Comment[ru]=Расширение KRunner
|
||||
Comment[se]=KRunner-lassemodula
|
||||
Comment[si]=KRunner ප්ලගීනය
|
||||
Comment[sk]=KRunner modul
|
||||
Comment[sl]=Vstavek za KRunner
|
||||
Comment[sq]=KRunner plugin
|
||||
Comment[sr]=Прикључак за К‑извођач
|
||||
Comment[sr@ijekavian]=Прикључак за К‑извођач
|
||||
Comment[sr@ijekavianlatin]=Priključak za K‑izvođač
|
||||
Comment[sr@latin]=Priključak za K‑izvođač
|
||||
Comment[sv]=Krunner-insticksprogram
|
||||
Comment[ta]=கேரன்னர் செருகி
|
||||
Comment[tg]=Васлкунаки KRunner
|
||||
Comment[th]=โปรแกรมเสริมของ KRunner
|
||||
Comment[tr]=KRunner eklentisi
|
||||
Comment[tt]=KRunner өстәмәсе
|
||||
Comment[ug]=KRunner قىستۇرما
|
||||
Comment[uk]=Додаток до KRunner
|
||||
Comment[vi]=Phần bổ sung KRunner
|
||||
Comment[wa]=Tchôke-divins KRunner
|
||||
Comment[x-test]=xxKRunner pluginxx
|
||||
Comment[zh_CN]=KRunner 插件
|
||||
Comment[zh_TW]=KRunner 外掛程式
|
||||
|
||||
[PropertyDef::X-Plasma-AdvertiseSingleRunnerQueryMode]
|
||||
Type=bool
|
||||
|
||||
[PropertyDef::TryExec]
|
||||
Type=QString
|
||||
|
||||
[PropertyDef::X-Plasma-Args]
|
||||
Type=QStringList
|
||||
|
86
plasma/data/servicetypes/plasma-scriptengine.desktop
Normal file
86
plasma/data/servicetypes/plasma-scriptengine.desktop
Normal file
@ -0,0 +1,86 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/ScriptEngine
|
||||
|
||||
Comment=Scripting language extension for Plasma
|
||||
Comment[ar]=امتداد لغة سكربت لبلازما
|
||||
Comment[as]=Plasma ৰ কাৰণে স্ক্ৰিপ্টিং ভাষাৰ সম্প্ৰসাৰণ
|
||||
Comment[ast]=Estensión de llinguaxe de guiones pa Plasma
|
||||
Comment[be@latin]=Pašyreńnie skryptavaj movy dla systemy „Plasma”
|
||||
Comment[bg]=Разширение на Plasma за скриптов език
|
||||
Comment[bs]=Proširenje Plazme za skriptne jezike
|
||||
Comment[ca]=Extensió de llenguatge d'script per al Plasma
|
||||
Comment[ca@valencia]=Extensió de llenguatge d'script per al Plasma
|
||||
Comment[cs]=Rozšíření pro skriptovací jazyky Plasma
|
||||
Comment[da]=Scriptsprog-udvidelse til Plasma
|
||||
Comment[de]=Skriptsprachen-Erweiterung für Plasma
|
||||
Comment[el]=Επέκταση γλώσσας σεναρίων για το Plasma
|
||||
Comment[en_GB]=Scripting language extension for Plasma
|
||||
Comment[eo]=Skriptlingva etendaĵo por Plasma
|
||||
Comment[es]=Extensión de lenguaje de script para Plasma
|
||||
Comment[et]=Skriptikeele laiendus Plasmale
|
||||
Comment[eu]=Plasmarako script lengoaien gehigarria
|
||||
Comment[fi]=Skriptauskielituki Plasmalle
|
||||
Comment[fr]=Langage de script d'extension pour Plasma
|
||||
Comment[fy]=Scripting taal taheaksel foar Plasma
|
||||
Comment[ga]=Eisínteacht teanga scriptithe le haghaidh Plasma
|
||||
Comment[gl]=Extensión de linguaxe de scripts para o Plasma
|
||||
Comment[gu]=પ્લાઝમા માટે સ્ક્રિપ્ટીંગ ભાષા એક્સટેન્શન
|
||||
Comment[he]=הרחבת שפת תסריטים של Plasma
|
||||
Comment[hne]=प्लाज्मा बर स्क्रिप्टिंग भाखा
|
||||
Comment[hr]=Proširenje Plasme za skriptne jezike
|
||||
Comment[hsb]=Skriptowa rěč jako Plasma-ekstensija
|
||||
Comment[hu]=Szkriptkezelő bővítmény a Plasmához
|
||||
Comment[ia]=Extension del language de script de Plasma
|
||||
Comment[id]=Tambahan bahasa skrip untuk Plasma
|
||||
Comment[is]=Framlenging á skriftunarmál fyrir Plasma
|
||||
Comment[it]=Estensione linguaggio scripting per Plasma
|
||||
Comment[ja]=Plasma のためのスクリプト言語拡張
|
||||
Comment[kk]=Plasma-ның скрипт тілі
|
||||
Comment[km]=ផ្នែកបន្ថែមភាសាស្គ្រីបសម្រាប់ប្លាស្មា
|
||||
Comment[kn]=ಪ್ಲಾಸ್ಮಾ ಕ್ಕೆ ವಿಧಿಗುಚ್ಛ (ಸ್ಕ್ರಿಪ್ಟ್) ರಚನಾ ಭಾಷೆ ಯ ವಿಸ್ತರಣೆ
|
||||
Comment[ko]=Plasma 스크립트 언어 확장
|
||||
Comment[ku]=Pêveka zimanê skrîpt kirinê ji bo Plasma
|
||||
Comment[lt]=Scenarijų kalbos praplėtimas, skirtas Plasma
|
||||
Comment[lv]=Skriptēšanas valodu Plasma paplašinājums
|
||||
Comment[mai]=प्लाजमाक लेल स्क्रिप्टिंग भाषाक विस्तार
|
||||
Comment[ml]=പ്ലാസ്മയ്ക്കുള്ള സ്ക്രിപ്റ്റിങ്ങ് ഭാഷാ എക്സ്റ്റന്ഷന്
|
||||
Comment[mr]=प्लाज्मा साठी स्क्रिप्टींग भाषा एक्सटेंशन
|
||||
Comment[nb]=Skriptspråk-utvidelse for Plasma
|
||||
Comment[nds]=Skriptspraak-Verwiedern för Plasma
|
||||
Comment[nl]=Scripttaalextensie voor Plasma
|
||||
Comment[nn]=Skriptspråkutviding for Plasma
|
||||
Comment[pa]=ਪਲਾਜ਼ਮਾ ਲਈ ਸਕ੍ਰਿਪਟਿੰਗ ਭਾਸ਼ਾ ਇਕਸਟੈਨਸ਼ਨ
|
||||
Comment[pl]=Rozszerzenie języka skryptów dla Plazmy
|
||||
Comment[pt]=Extensão de linguagens de programação para o Plasma
|
||||
Comment[pt_BR]=Extensão de linguagem de script do Plasma
|
||||
Comment[ro]=Extensie de limbaj pentru scripturi Plasma
|
||||
Comment[ru]=Поддержка языков сценариев для Plasma
|
||||
Comment[se]=Skriptagiellaviiddádus Plasmai
|
||||
Comment[si]=Plasma සඳහා ස්කටිප්ට භාෂා දිගුව
|
||||
Comment[sk]=Rozšírenie pre skriptovacie jazyky Plasma
|
||||
Comment[sl]=Razširitev s skriptnim jezikom za Plasmo
|
||||
Comment[sr]=Проширење Плазме за скриптне језике
|
||||
Comment[sr@ijekavian]=Проширење Плазме за скриптне језике
|
||||
Comment[sr@ijekavianlatin]=Proširenje Plasme za skriptne jezike
|
||||
Comment[sr@latin]=Proširenje Plasme za skriptne jezike
|
||||
Comment[sv]=Skriptspråksutökning för Plasma
|
||||
Comment[ta]=பிளாஸ்மாவிற்கான குறுநிரலாக்க மொழி விரிவாக்கம்
|
||||
Comment[tg]=Скрипти забонҳои иловагӣ барои Plasma
|
||||
Comment[th]=ส่วนเสริมภาษาสคริปต์สำหรับพลาสมา
|
||||
Comment[tr]=Plasma için betik dili eklentisi
|
||||
Comment[tt]=Plasma өчен скрипт телләр өстәмәсе
|
||||
Comment[ug]=Plasma نىڭ قوليازما تىل كېڭەيتىلمىسى
|
||||
Comment[uk]=Розширення скриптових мов для Плазми
|
||||
Comment[vi]=Phần mở rộng ngôn ngữ lệnh cho Plasma
|
||||
Comment[wa]=Rawete di lingaedje di scriptaedje po Plasma
|
||||
Comment[x-test]=xxScripting language extension for Plasmaxx
|
||||
Comment[zh_CN]=Plasma 的脚本语言扩展
|
||||
Comment[zh_TW]=Plasma 文稿語言延伸
|
||||
|
||||
[PropertyDef::X-Plasma-ComponentTypes]
|
||||
Type=QStringList
|
||||
|
||||
[PropertyDef::X-Plasma-PackageFormat]
|
||||
Type=QString
|
||||
|
66
plasma/data/servicetypes/plasma-service.desktop
Normal file
66
plasma/data/servicetypes/plasma-service.desktop
Normal file
@ -0,0 +1,66 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/Service
|
||||
|
||||
Comment=Plasma service
|
||||
Comment[ar]=خدمة بلازما
|
||||
Comment[bg]=Услуга Plasma
|
||||
Comment[bs]=Plazma usluga
|
||||
Comment[ca]=Servei del Plasma
|
||||
Comment[ca@valencia]=Servei del Plasma
|
||||
Comment[cs]=Služba Plasma
|
||||
Comment[da]=Plasma-tjeneste
|
||||
Comment[de]=Plasma-Dienst
|
||||
Comment[el]=Υπηρεσία plasma
|
||||
Comment[en_GB]=Plasma service
|
||||
Comment[es]=Servicio de Plasma
|
||||
Comment[et]=Plasma teenus
|
||||
Comment[eu]=Plasma zerbitzua
|
||||
Comment[fi]=Plasma-palvelu
|
||||
Comment[fr]=Service Plasma
|
||||
Comment[ga]=Seirbhís Plasma
|
||||
Comment[gl]=Servizo do Plasma
|
||||
Comment[he]=שירות של Plasma
|
||||
Comment[hi]=प्लासमा सेवा
|
||||
Comment[hr]=Servis u Plasmi
|
||||
Comment[hu]=Plazma-szolgáltatás
|
||||
Comment[ia]=Servicio de Plasma
|
||||
Comment[is]=Plasma-þjónusta
|
||||
Comment[it]=Servizio plasma
|
||||
Comment[ja]=Plasma サービス
|
||||
Comment[kk]=Plasma қызметі
|
||||
Comment[km]=សេវាប្លាស្មា
|
||||
Comment[ko]=Plasma 서비스
|
||||
Comment[lt]=Plasma tarnyba
|
||||
Comment[lv]=Plasma serviss
|
||||
Comment[mr]=प्लाज्मा सेवा
|
||||
Comment[nb]=Plasma-tjeneste
|
||||
Comment[nds]=Plasma-Deenst
|
||||
Comment[nl]=Plasma-service
|
||||
Comment[pa]=ਪਲਾਜ਼ਮਾ ਸਰਵਿਸ
|
||||
Comment[pl]=Usługa Plazmy
|
||||
Comment[pt]=Serviço do Plasma
|
||||
Comment[pt_BR]=Serviço do Plasma
|
||||
Comment[ro]=Servicu Plasma
|
||||
Comment[ru]=Служба Plasma
|
||||
Comment[se]=Plasma-bálvalus
|
||||
Comment[si]=ප්ලස්මා සේවා
|
||||
Comment[sk]=Služba Plasma
|
||||
Comment[sl]=Storitev Plasme
|
||||
Comment[sq]=Shërbimi plazma
|
||||
Comment[sr]=Плазма сервис
|
||||
Comment[sr@ijekavian]=Плазма сервис
|
||||
Comment[sr@ijekavianlatin]=Plasma servis
|
||||
Comment[sr@latin]=Plasma servis
|
||||
Comment[sv]=Plasma-tjänst
|
||||
Comment[tg]=Хидматҳои Plasma
|
||||
Comment[th]=บริการของพลาสมา
|
||||
Comment[tr]=Plasma servisi
|
||||
Comment[tt]=Plasma хезмәте
|
||||
Comment[ug]=Plasma مۇلازىمىتى
|
||||
Comment[uk]=Служба Плазми
|
||||
Comment[vi]=Dịch vụ Plasma
|
||||
Comment[wa]=Siervice di Plasma
|
||||
Comment[x-test]=xxPlasma servicexx
|
||||
Comment[zh_CN]=Plasma 服务
|
||||
Comment[zh_TW]=Plasma 服務
|
67
plasma/data/servicetypes/plasma-toolbox.desktop
Normal file
67
plasma/data/servicetypes/plasma-toolbox.desktop
Normal file
@ -0,0 +1,67 @@
|
||||
[Desktop Entry]
|
||||
Type=ServiceType
|
||||
X-KDE-ServiceType=Plasma/ToolBox
|
||||
|
||||
Comment=Plasma toolbox
|
||||
Comment[ar]=صندوق أدوات بلازما
|
||||
Comment[bg]=Инструменти за Plasma
|
||||
Comment[bs]=Plazma alatna traka
|
||||
Comment[ca]=Caixa d'eines del Plasma
|
||||
Comment[ca@valencia]=Caixa d'eines del Plasma
|
||||
Comment[cs]=Plasma toolbox
|
||||
Comment[da]=Plasma værktøjskasse
|
||||
Comment[de]=Plasma-Werkzeugkasten
|
||||
Comment[el]=Εργαλειοθήκη Plasma
|
||||
Comment[en_GB]=Plasma toolbox
|
||||
Comment[es]=Caja de herramientas de Plasma
|
||||
Comment[et]=Plasma tööriistakast
|
||||
Comment[eu]=Plasma tresna-kutxa
|
||||
Comment[fi]=Plasma-työkalurivi
|
||||
Comment[fr]=Boîte à outils Plasma
|
||||
Comment[ga]=Bosca uirlisí Plasma
|
||||
Comment[gl]=Barra de ferramentas do Plasma
|
||||
Comment[he]=ארגז כלים של Plasma
|
||||
Comment[hi]=प्लासमा औज़ारबक्सा
|
||||
Comment[hr]=Plasma alatni okvir
|
||||
Comment[hu]=Plazma-eszközkészlet
|
||||
Comment[ia]=Instrumentario de Plasma
|
||||
Comment[is]=Plasma verkfærasafn
|
||||
Comment[it]=Barra degli strumenti plasma
|
||||
Comment[ja]=Plasma ツールボックス
|
||||
Comment[kk]=Plasma құралдары
|
||||
Comment[km]=ប្រអប់ឧបករណ៍ប្លាស្មា
|
||||
Comment[ko]=Plasma 도구 상자
|
||||
Comment[ku]=Qutiya amûrên Plasma
|
||||
Comment[lt]=Pasma įrankinė
|
||||
Comment[lv]=Plasma rīkkopa
|
||||
Comment[mr]=प्लाज्मा साधने
|
||||
Comment[nb]=Plasma-verktøykasse
|
||||
Comment[nds]=Plasma-Warktüüchkist
|
||||
Comment[nl]=Plasma-hulpmiddelen
|
||||
Comment[pa]=ਪਲਾਜ਼ਮਾ ਟੂਲਬਾਕਸ
|
||||
Comment[pl]=Przybornik Plazmy
|
||||
Comment[pt]=Barra de ferramentas do Plasma
|
||||
Comment[pt_BR]=Barra de ferramentas do Plasma
|
||||
Comment[ro]=Cutie de unelte Plasma
|
||||
Comment[ru]=Панель инструментов Plasma
|
||||
Comment[se]=Plasma-reaidoboksa
|
||||
Comment[si]=ප්ලස්මා මෙවලම් පෙට්ටිය
|
||||
Comment[sk]=Nástroje Plasma
|
||||
Comment[sl]=Orodjana v Plasmi
|
||||
Comment[sr]=Плазма алатница
|
||||
Comment[sr@ijekavian]=Плазма алатница
|
||||
Comment[sr@ijekavianlatin]=Plasma alatnica
|
||||
Comment[sr@latin]=Plasma alatnica
|
||||
Comment[sv]=Plasma verktygslåda
|
||||
Comment[ta]=பிளாஸ்மா கருவிப்பட்டி
|
||||
Comment[tg]=Лавҳаи воситаҳои Plasma
|
||||
Comment[th]=กล่องเครื่องมือของพลาสมา
|
||||
Comment[tr]=Plasma araç kutusu
|
||||
Comment[tt]=Plasma корал панеле
|
||||
Comment[ug]=Plasma قورال ساندۇقى
|
||||
Comment[uk]=Набір інструментів Плазми
|
||||
Comment[vi]=Hộp công cụ Plasma
|
||||
Comment[wa]=Boesse ås usteyes di Plasma
|
||||
Comment[x-test]=xxPlasma toolboxxx
|
||||
Comment[zh_CN]=Plasma 工具箱
|
||||
Comment[zh_TW]=Plasma 工具盒
|
360
plasma/datacontainer.cpp
Normal file
360
plasma/datacontainer.cpp
Normal file
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 "datacontainer.h"
|
||||
#include "private/datacontainer_p.h"
|
||||
#include "private/storage_p.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
#include "plasma.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
DataContainer::DataContainer(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new DataContainerPrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
DataContainer::~DataContainer()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
const DataEngine::Data DataContainer::data() const
|
||||
{
|
||||
return d->data;
|
||||
}
|
||||
|
||||
void DataContainer::setData(const QString &key, const QVariant &value)
|
||||
{
|
||||
if (!value.isValid()) {
|
||||
d->data.remove(key);
|
||||
} else {
|
||||
d->data.insert(key, value);
|
||||
}
|
||||
|
||||
d->dirty = true;
|
||||
d->updateTs.start();
|
||||
|
||||
//check if storage is enabled and if storage is needed.
|
||||
//If it is not set to be stored,then this is the first
|
||||
//setData() since the last time it was stored. This
|
||||
//gives us only one singleShot timer.
|
||||
if (isStorageEnabled() || !needsToBeStored()) {
|
||||
d->storageTimer.start(180000, this);
|
||||
}
|
||||
|
||||
setNeedsToBeStored(true);
|
||||
}
|
||||
|
||||
void DataContainer::removeAllData()
|
||||
{
|
||||
if (d->data.isEmpty()) {
|
||||
// avoid an update if we don't have any data anyways
|
||||
return;
|
||||
}
|
||||
|
||||
d->data.clear();
|
||||
d->dirty = true;
|
||||
d->updateTs.start();
|
||||
}
|
||||
|
||||
bool DataContainer::visualizationIsConnected(QObject *visualization) const
|
||||
{
|
||||
return d->relayObjects.contains(visualization);
|
||||
}
|
||||
|
||||
void DataContainer::connectVisualization(QObject *visualization, uint pollingInterval,
|
||||
Plasma::IntervalAlignment alignment)
|
||||
{
|
||||
//kDebug() << "connecting visualization" << visualization << "at interval of"
|
||||
// << pollingInterval << "to" << objectName();
|
||||
QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
|
||||
bool connected = objIt != d->relayObjects.end();
|
||||
if (connected) {
|
||||
// this visualization is already connected. just adjust the update
|
||||
// frequency if necessary
|
||||
SignalRelay *relay = objIt.value();
|
||||
if (relay) {
|
||||
// connected to a relay
|
||||
//kDebug() << " already connected, but to a relay";
|
||||
if (relay->m_interval == pollingInterval) {
|
||||
//kDebug() << " already connected to a relay of the same interval of"
|
||||
// << pollingInterval << ", nothing to do";
|
||||
return;
|
||||
}
|
||||
|
||||
if (relay->receiverCount() == 1) {
|
||||
//kDebug() << " removing relay, as it is now unused";
|
||||
d->relays.remove(relay->m_interval);
|
||||
delete relay;
|
||||
} else {
|
||||
disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
|
||||
visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
|
||||
//relay->isUnused();
|
||||
}
|
||||
} else if (pollingInterval < 1) {
|
||||
// the visualization was connected already, but not to a relay
|
||||
// and it still doesn't want to connect to a relay, so we have
|
||||
// nothing to do!
|
||||
//kDebug() << " already connected, nothing to do";
|
||||
return;
|
||||
} else {
|
||||
disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
|
||||
visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
|
||||
}
|
||||
} else {
|
||||
connect(visualization, SIGNAL(destroyed(QObject*)),
|
||||
this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
if (pollingInterval < 1) {
|
||||
//kDebug() << " connecting directly";
|
||||
d->relayObjects[visualization] = 0;
|
||||
connect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
|
||||
visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
|
||||
} else {
|
||||
//kDebug() << " connecting to a relay";
|
||||
// we only want to do an imediate update if this is not the first object to connect to us
|
||||
// if it is the first visualization, then the source will already have been populated
|
||||
// engine's sourceRequested method
|
||||
bool immediateUpdate = connected || d->relayObjects.count() > 1;
|
||||
SignalRelay *relay = d->signalRelay(this, visualization, pollingInterval,
|
||||
alignment, immediateUpdate);
|
||||
connect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
|
||||
visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
|
||||
}
|
||||
}
|
||||
|
||||
void DataContainer::setStorageEnabled(bool store)
|
||||
{
|
||||
QTime time = QTime::currentTime();
|
||||
qsrand((uint)time.msec());
|
||||
d->enableStorage = store;
|
||||
if (store) {
|
||||
QTimer::singleShot(qrand() % (2000 + 1) , this, SLOT(retrieve()));
|
||||
}
|
||||
}
|
||||
|
||||
bool DataContainer::isStorageEnabled() const
|
||||
{
|
||||
return d->enableStorage;
|
||||
}
|
||||
|
||||
bool DataContainer::needsToBeStored() const
|
||||
{
|
||||
return !d->isStored;
|
||||
}
|
||||
|
||||
void DataContainer::setNeedsToBeStored(bool store)
|
||||
{
|
||||
d->isStored = !store;
|
||||
}
|
||||
|
||||
DataEngine* DataContainer::getDataEngine()
|
||||
{
|
||||
QObject *o = this;
|
||||
DataEngine *de = NULL;
|
||||
while (de == NULL)
|
||||
{
|
||||
o = dynamic_cast<QObject *> (o->parent());
|
||||
if (o == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
de = dynamic_cast<DataEngine *> (o);
|
||||
}
|
||||
return de;
|
||||
}
|
||||
|
||||
void DataContainerPrivate::store()
|
||||
{
|
||||
if (!q->needsToBeStored() || !q->isStorageEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DataEngine* de = q->getDataEngine();
|
||||
if (!de) {
|
||||
return;
|
||||
}
|
||||
|
||||
q->setNeedsToBeStored(false);
|
||||
|
||||
if (!storage) {
|
||||
storage = new Storage(q);
|
||||
}
|
||||
|
||||
KConfigGroup op = storage->operationDescription("save");
|
||||
op.writeEntry("group", q->objectName());
|
||||
StorageJob *job = static_cast<StorageJob *>(storage->startOperationCall(op));
|
||||
job->setData(data);
|
||||
storageCount++;
|
||||
QObject::connect(job, SIGNAL(finished(KJob*)), q, SLOT(storeJobFinished(KJob*)));
|
||||
}
|
||||
|
||||
void DataContainerPrivate::storeJobFinished(KJob* )
|
||||
{
|
||||
--storageCount;
|
||||
if (storageCount < 1) {
|
||||
storage->deleteLater();
|
||||
storage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DataContainerPrivate::retrieve()
|
||||
{
|
||||
DataEngine* de = q->getDataEngine();
|
||||
if (de == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!storage) {
|
||||
storage = new Storage(q);
|
||||
}
|
||||
|
||||
KConfigGroup retrieveGroup = storage->operationDescription("retrieve");
|
||||
retrieveGroup.writeEntry("group", q->objectName());
|
||||
ServiceJob* retrieveJob = storage->startOperationCall(retrieveGroup);
|
||||
QObject::connect(retrieveJob, SIGNAL(result(KJob*)), q,
|
||||
SLOT(populateFromStoredData(KJob*)));
|
||||
}
|
||||
|
||||
void DataContainerPrivate::populateFromStoredData(KJob *job)
|
||||
{
|
||||
if (job->error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
StorageJob *ret = dynamic_cast<StorageJob*>(job);
|
||||
if (!ret) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only fill the source with old stored
|
||||
// data if it is not already populated with new data.
|
||||
if (data.isEmpty() && !ret->data().isEmpty()) {
|
||||
data = ret->data();
|
||||
dirty = true;
|
||||
q->forceImmediateUpdate();
|
||||
}
|
||||
|
||||
KConfigGroup expireGroup = storage->operationDescription("expire");
|
||||
//expire things older than 4 days
|
||||
expireGroup.writeEntry("age", 345600);
|
||||
storage->startOperationCall(expireGroup);
|
||||
}
|
||||
|
||||
void DataContainer::disconnectVisualization(QObject *visualization)
|
||||
{
|
||||
QMap<QObject *, SignalRelay *>::iterator objIt = d->relayObjects.find(visualization);
|
||||
disconnect(visualization, SIGNAL(destroyed(QObject*)),
|
||||
this, SLOT(disconnectVisualization(QObject*)));//, Qt::QueuedConnection);
|
||||
|
||||
if (objIt == d->relayObjects.end() || !objIt.value()) {
|
||||
// it is connected directly to the DataContainer itself
|
||||
disconnect(this, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
|
||||
visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
|
||||
} else {
|
||||
SignalRelay *relay = objIt.value();
|
||||
|
||||
if (relay->receiverCount() == 1) {
|
||||
d->relays.remove(relay->m_interval);
|
||||
delete relay;
|
||||
} else {
|
||||
disconnect(relay, SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)),
|
||||
visualization, SLOT(dataUpdated(QString,Plasma::DataEngine::Data)));
|
||||
}
|
||||
}
|
||||
|
||||
d->relayObjects.erase(objIt);
|
||||
d->checkUsage();
|
||||
}
|
||||
|
||||
void DataContainer::checkForUpdate()
|
||||
{
|
||||
//kDebug() << objectName() << d->dirty;
|
||||
if (d->dirty) {
|
||||
emit dataUpdated(objectName(), d->data);
|
||||
|
||||
foreach (SignalRelay *relay, d->relays) {
|
||||
relay->checkQueueing();
|
||||
}
|
||||
|
||||
d->dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DataContainer::forceImmediateUpdate()
|
||||
{
|
||||
if (d->dirty) {
|
||||
d->dirty = false;
|
||||
emit dataUpdated(objectName(), d->data);
|
||||
}
|
||||
|
||||
foreach (SignalRelay *relay, d->relays) {
|
||||
relay->forceImmediateUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
uint DataContainer::timeSinceLastUpdate() const
|
||||
{
|
||||
//FIXME: we still assume it's been <24h
|
||||
//and ignore possible daylight savings changes
|
||||
return d->updateTs.elapsed();
|
||||
}
|
||||
|
||||
void DataContainer::setNeedsUpdate(bool update)
|
||||
{
|
||||
d->cached = update;
|
||||
}
|
||||
|
||||
bool DataContainer::isUsed() const
|
||||
{
|
||||
return !d->relays.isEmpty() &&
|
||||
receivers(SIGNAL(dataUpdated(QString, Plasma::DataEngine::Data))) > 0;
|
||||
}
|
||||
|
||||
void DataContainerPrivate::checkUsage()
|
||||
{
|
||||
if (!checkUsageTimer.isActive()) {
|
||||
checkUsageTimer.start(10, q);
|
||||
}
|
||||
}
|
||||
|
||||
void DataContainer::timerEvent(QTimerEvent * event)
|
||||
{
|
||||
if (event->timerId() == d->checkUsageTimer.timerId()) {
|
||||
if (!isUsed()) {
|
||||
// DO NOT CALL ANYTHING AFTER THIS LINE AS IT MAY GET DELETED!
|
||||
//kDebug() << objectName() << "is unused";
|
||||
emit becameUnused(objectName());
|
||||
}
|
||||
d->checkUsageTimer.stop();
|
||||
} else if (event->timerId() == d->storageTimer.timerId()) {
|
||||
d->store();
|
||||
d->storageTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
|
||||
#include "moc_datacontainer.cpp"
|
261
plasma/datacontainer.h
Normal file
261
plasma/datacontainer.h
Normal file
@ -0,0 +1,261 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 PLASMA_DATACONTAINER_H
|
||||
#define PLASMA_DATACONTAINER_H
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <kjob.h>
|
||||
#include <plasma/plasma_export.h>
|
||||
#include <plasma/dataengine.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataContainerPrivate;
|
||||
|
||||
/**
|
||||
* @class DataContainer plasma/datacontainer.h <Plasma/DataContainer>
|
||||
*
|
||||
* @brief A set of data exported via a DataEngine
|
||||
*
|
||||
* Plasma::DataContainer wraps the data exported by a DataEngine
|
||||
* implementation, providing a generic wrapper for the data.
|
||||
*
|
||||
* A DataContainer may have zero or more associated pieces of data which
|
||||
* are keyed by strings. The data itself is stored as QVariants. This allows
|
||||
* easy and flexible retrieval of the information associated with this object
|
||||
* without writing DataContainer or DataEngine specific code in visualizations.
|
||||
*
|
||||
* If you are creating your own DataContainer objects (and are passing them to
|
||||
* DataEngine::addSource()), you normally just need to listen to the
|
||||
* updateRequested() signal (as well as any other methods you might have of
|
||||
* being notified of new data) and call setData() to actually update the data.
|
||||
* Then you need to either trigger the scheduleSourcesUpdated signal of the
|
||||
* parent DataEngine or call checkForUpdate() on the DataContainer.
|
||||
*
|
||||
* You also need to set a suitable name for the source with setObjectName().
|
||||
* See DataEngine::addSource() for more information.
|
||||
*
|
||||
* Note that there is normally no need to subclass DataContainer, except as
|
||||
* a way of encapsulating the data retrieval for a source, since all notifications
|
||||
* are done via signals rather than virtual methods.
|
||||
**/
|
||||
class PLASMA_EXPORT DataContainer : public QObject
|
||||
{
|
||||
friend class DataEngine;
|
||||
friend class DataEnginePrivate;
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructs a default DataContainer that has no name or data
|
||||
* associated with it
|
||||
**/
|
||||
explicit DataContainer(QObject *parent = 0);
|
||||
virtual ~DataContainer();
|
||||
|
||||
/**
|
||||
* Returns the data for this DataContainer
|
||||
**/
|
||||
const DataEngine::Data data() const;
|
||||
|
||||
/**
|
||||
* Set a value for a key.
|
||||
*
|
||||
* This also marks this source as needing to signal an update.
|
||||
*
|
||||
* If you call setData() directly on a DataContainer, you need to
|
||||
* either trigger the scheduleSourcesUpdated() slot for the
|
||||
* data engine it belongs to or call checkForUpdate() on the
|
||||
* DataContainer.
|
||||
*
|
||||
* @param key a string used as the key for the data
|
||||
* @param value a QVariant holding the actual data. If a invalid
|
||||
* QVariant is passed in and the key currently exists in the
|
||||
* data, then the data entry is removed
|
||||
**/
|
||||
void setData(const QString &key, const QVariant &value);
|
||||
|
||||
/**
|
||||
* Removes all data currently associated with this source
|
||||
*
|
||||
* If you call removeAllData() on a DataContainer, you need to
|
||||
* either trigger the scheduleSourcesUpdated() slot for the
|
||||
* data engine it belongs to or call checkForUpdate() on the
|
||||
* DataContainer.
|
||||
**/
|
||||
void removeAllData();
|
||||
|
||||
/**
|
||||
* @return true if the visualization is currently connected
|
||||
*/
|
||||
bool visualizationIsConnected(QObject *visualization) const;
|
||||
|
||||
/**
|
||||
* Connects an object to this DataContainer.
|
||||
*
|
||||
* May be called repeatedly for the same visualization without
|
||||
* side effects
|
||||
*
|
||||
* @param visualization the object to connect to this DataContainer
|
||||
* @param pollingInterval the time in milliseconds between updates
|
||||
* @param alignment the clock position to align updates to
|
||||
**/
|
||||
void connectVisualization(QObject *visualization, uint pollingInterval,
|
||||
Plasma::IntervalAlignment alignment);
|
||||
|
||||
/**
|
||||
* sets this data container to be automatically stored.
|
||||
* @param whether this data container should be stored
|
||||
* @since 4.6
|
||||
*/
|
||||
void setStorageEnabled(bool store);
|
||||
|
||||
/**
|
||||
* @return true if the data container has been marked for storage
|
||||
* @since 4.6
|
||||
*/
|
||||
bool isStorageEnabled() const;
|
||||
|
||||
/**
|
||||
* @return true if the data container has been updated, but not stored
|
||||
*/
|
||||
bool needsToBeStored() const;
|
||||
|
||||
/**
|
||||
* sets that the data container needs to be stored or not.
|
||||
* @param whether the data container needs to be stored
|
||||
*/
|
||||
void setNeedsToBeStored(bool store);
|
||||
|
||||
/**
|
||||
* @return the DataEngine that the DataContainer is
|
||||
* a child of.
|
||||
*/
|
||||
DataEngine* getDataEngine();
|
||||
|
||||
/**
|
||||
* @return true if one or more visualizations is connected to this DataContainer
|
||||
*/
|
||||
bool isUsed() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* Disconnects an object from this DataContainer.
|
||||
*
|
||||
* Note that if this source was created by DataEngine::sourceRequestEvent(),
|
||||
* it will be deleted by DataEngine once control returns to the event loop.
|
||||
**/
|
||||
void disconnectVisualization(QObject *visualization);
|
||||
|
||||
/**
|
||||
* Forces immediate update signals to all visualizations
|
||||
* @since 4.4
|
||||
*/
|
||||
void forceImmediateUpdate();
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emitted when the data has been updated, allowing visualizations to
|
||||
* reflect the new data.
|
||||
*
|
||||
* Note that you should not normally emit this directly. Instead, use
|
||||
* checkForUpdate() or the DataEngine::scheduleSourcesUpdated() slot.
|
||||
*
|
||||
* @param source the objectName() of the DataContainer (and hence the name
|
||||
* of the source) that updated its data
|
||||
* @param data the updated data
|
||||
**/
|
||||
void dataUpdated(const QString &source, const Plasma::DataEngine::Data &data);
|
||||
|
||||
/**
|
||||
* Emitted when the last visualization is disconnected.
|
||||
*
|
||||
* Note that if this source was created by DataEngine::sourceRequestEvent(),
|
||||
* it will be deleted by DataEngine once control returns to the event loop
|
||||
* after this signal is emitted.
|
||||
*
|
||||
* @param source the name of the source that became unused
|
||||
**/
|
||||
void becameUnused(const QString &source);
|
||||
|
||||
/**
|
||||
* Emitted when an update is requested.
|
||||
*
|
||||
* If a polling interval was passed connectVisualization(), this signal
|
||||
* will be emitted every time the interval expires.
|
||||
*
|
||||
* Note that if you create your own DataContainer (and pass it to
|
||||
* DataEngine::addSource()), you will need to listen to this signal
|
||||
* and refresh the data when it is triggered.
|
||||
*
|
||||
* @param source the datacontainer the update was requested for. Useful
|
||||
* for classes that update the data for several containers.
|
||||
**/
|
||||
void updateRequested(DataContainer *source);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Checks whether any data has changed and, if so, emits dataUpdated().
|
||||
**/
|
||||
void checkForUpdate();
|
||||
|
||||
/**
|
||||
* Returns how long ago, in msecs, that the data in this container was last updated.
|
||||
*
|
||||
* This is used by DataEngine to compress updates that happen more quickly than the
|
||||
* minimum polling interval by calling setNeedsUpdate() instead of calling
|
||||
* updateSourceEvent() immediately.
|
||||
**/
|
||||
uint timeSinceLastUpdate() const;
|
||||
|
||||
/**
|
||||
* Indicates that the data should be treated as dirty the next time hasUpdates() is called.
|
||||
*
|
||||
* This is needed for the case where updateRequested() is triggered but we don't want to
|
||||
* update the data immediately because it has just been updated. The second request won't
|
||||
* be fulfilled in this case, because we never updated the data and so never called
|
||||
* checkForUpdate(). So we claim it needs an update anyway.
|
||||
**/
|
||||
void setNeedsUpdate(bool update = true);
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* @reimp from QObject
|
||||
*/
|
||||
void timerEvent(QTimerEvent * event);
|
||||
|
||||
private:
|
||||
friend class SignalRelay;
|
||||
friend class DataContainerPrivate;
|
||||
friend class DataEngineManager;
|
||||
DataContainerPrivate *const d;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void storeJobFinished(KJob *job))
|
||||
Q_PRIVATE_SLOT(d, void populateFromStoredData(KJob *job))
|
||||
Q_PRIVATE_SLOT(d, void retrieve())
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif // multiple inclusion guard
|
759
plasma/dataengine.cpp
Normal file
759
plasma/dataengine.cpp
Normal file
@ -0,0 +1,759 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 "dataengine.h"
|
||||
#include "private/dataengine_p.h"
|
||||
#include "private/datacontainer_p.h"
|
||||
|
||||
#include <QQueue>
|
||||
#include <QTimer>
|
||||
#include <QTime>
|
||||
#include <QTimerEvent>
|
||||
#include <QVariant>
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <kplugininfo.h>
|
||||
#include <kglobal.h>
|
||||
#include <kservice.h>
|
||||
#include <kservicetypetrader.h>
|
||||
#include <kstandarddirs.h>
|
||||
#include <klocalizedstring.h>
|
||||
|
||||
#include "datacontainer.h"
|
||||
#include "package.h"
|
||||
#include "pluginloader.h"
|
||||
#include "remote/authorizationmanager.h"
|
||||
#include "remote/authorizationmanager_p.h"
|
||||
#include "service.h"
|
||||
#include "scripting/dataenginescript.h"
|
||||
|
||||
#include "private/datacontainer_p.h"
|
||||
#include "private/dataengineservice_p.h"
|
||||
#include "private/remotedataengine_p.h"
|
||||
#include "private/service_p.h"
|
||||
#include "private/storage_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
DataEngine::DataEngine(QObject *parent, KService::Ptr service)
|
||||
: QObject(parent),
|
||||
d(new DataEnginePrivate(this, KPluginInfo(service)))
|
||||
{
|
||||
}
|
||||
|
||||
DataEngine::DataEngine(QObject *parent, const QVariantList &args)
|
||||
: QObject(parent),
|
||||
d(new DataEnginePrivate(this, KPluginInfo(KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString()))))
|
||||
{
|
||||
}
|
||||
|
||||
DataEngine::~DataEngine()
|
||||
{
|
||||
//kDebug() << objectName() << ": bye bye birdy! ";
|
||||
delete d;
|
||||
}
|
||||
|
||||
QStringList DataEngine::sources() const
|
||||
{
|
||||
if (d->script) {
|
||||
return d->script->sources();
|
||||
} else {
|
||||
return d->sources.keys();
|
||||
}
|
||||
}
|
||||
|
||||
Service *DataEngine::serviceForSource(const QString &source)
|
||||
{
|
||||
if (d->script) {
|
||||
Service * s = d->script->serviceForSource(source);
|
||||
if (s) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
return new NullService(source, this);
|
||||
}
|
||||
|
||||
void DataEngine::connectSource(const QString &source, QObject *visualization,
|
||||
uint pollingInterval,
|
||||
Plasma::IntervalAlignment intervalAlignment) const
|
||||
{
|
||||
//kDebug() << "connectSource" << source;
|
||||
bool newSource;
|
||||
DataContainer *s = d->requestSource(source, &newSource);
|
||||
|
||||
if (s) {
|
||||
// we suppress the immediate invocation of dataUpdated here if the
|
||||
// source was prexisting and they don't request delayed updates
|
||||
// (we want to do an immediate update in that case so they don't
|
||||
// have to wait for the first time out)
|
||||
if (newSource && !s->data().isEmpty()) {
|
||||
newSource = false;
|
||||
}
|
||||
d->connectSource(s, visualization, pollingInterval, intervalAlignment,
|
||||
!newSource || pollingInterval > 0);
|
||||
//kDebug() << " ==> source connected";
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::connectAllSources(QObject *visualization, uint pollingInterval,
|
||||
Plasma::IntervalAlignment intervalAlignment) const
|
||||
{
|
||||
foreach (DataContainer *s, d->sources) {
|
||||
d->connectSource(s, visualization, pollingInterval, intervalAlignment);
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::disconnectSource(const QString &source, QObject *visualization) const
|
||||
{
|
||||
DataContainer *s = d->source(source, false);
|
||||
|
||||
if (s) {
|
||||
s->disconnectVisualization(visualization);
|
||||
}
|
||||
}
|
||||
|
||||
DataContainer *DataEngine::containerForSource(const QString &source)
|
||||
{
|
||||
return d->source(source, false);
|
||||
}
|
||||
|
||||
DataEngine::Data DataEngine::query(const QString &source) const
|
||||
{
|
||||
bool newSource;
|
||||
DataContainer *s = d->requestSource(source, &newSource);
|
||||
|
||||
if (!s) {
|
||||
return DataEngine::Data();
|
||||
} else if (!newSource && d->minPollingInterval >= 0 &&
|
||||
s->timeSinceLastUpdate() >= uint(d->minPollingInterval)) {
|
||||
DataEngine *unconstThis = const_cast<DataEngine*>(this);
|
||||
if (unconstThis->updateSourceEvent(source)) {
|
||||
unconstThis->scheduleSourcesUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
DataEngine::Data data = s->data();
|
||||
s->d->checkUsage();
|
||||
return data;
|
||||
}
|
||||
|
||||
void DataEngine::init()
|
||||
{
|
||||
if (d->script) {
|
||||
d->setupScriptSupport();
|
||||
d->script->init();
|
||||
} else {
|
||||
// kDebug() << "called";
|
||||
// default implementation does nothing. this is for engines that have to
|
||||
// start things in motion external to themselves before they can work
|
||||
}
|
||||
}
|
||||
|
||||
bool DataEngine::sourceRequestEvent(const QString &name)
|
||||
{
|
||||
if (d->script) {
|
||||
return d->script->sourceRequestEvent(name);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DataEngine::updateSourceEvent(const QString &source)
|
||||
{
|
||||
if (d->script) {
|
||||
return d->script->updateSourceEvent(source);
|
||||
} else {
|
||||
//kDebug() << source;
|
||||
return false; //TODO: should this be true to trigger, even needless, updates on every tick?
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::setData(const QString &source, const QVariant &value)
|
||||
{
|
||||
setData(source, source, value);
|
||||
}
|
||||
|
||||
void DataEngine::setData(const QString &source, const QString &key, const QVariant &value)
|
||||
{
|
||||
DataContainer *s = d->source(source, false);
|
||||
bool isNew = !s;
|
||||
|
||||
if (isNew) {
|
||||
s = d->source(source);
|
||||
}
|
||||
|
||||
s->setData(key, value);
|
||||
|
||||
if (isNew && source != d->waitingSourceRequest) {
|
||||
emit sourceAdded(source);
|
||||
}
|
||||
|
||||
scheduleSourcesUpdated();
|
||||
}
|
||||
|
||||
void DataEngine::setData(const QString &source, const Data &data)
|
||||
{
|
||||
DataContainer *s = d->source(source, false);
|
||||
bool isNew = !s;
|
||||
|
||||
if (isNew) {
|
||||
s = d->source(source);
|
||||
}
|
||||
|
||||
Data::const_iterator it = data.constBegin();
|
||||
while (it != data.constEnd()) {
|
||||
s->setData(it.key(), it.value());
|
||||
++it;
|
||||
}
|
||||
|
||||
if (isNew && source != d->waitingSourceRequest) {
|
||||
emit sourceAdded(source);
|
||||
}
|
||||
|
||||
scheduleSourcesUpdated();
|
||||
}
|
||||
|
||||
void DataEngine::removeAllData(const QString &source)
|
||||
{
|
||||
DataContainer *s = d->source(source, false);
|
||||
if (s) {
|
||||
s->removeAllData();
|
||||
scheduleSourcesUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::removeData(const QString &source, const QString &key)
|
||||
{
|
||||
DataContainer *s = d->source(source, false);
|
||||
if (s) {
|
||||
s->setData(key, QVariant());
|
||||
scheduleSourcesUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::addSource(DataContainer *source)
|
||||
{
|
||||
if (d->sources.contains(source->objectName())) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "source named \"" << source->objectName() << "\" already exists.";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
QObject::connect(source, SIGNAL(updateRequested(DataContainer*)),
|
||||
this, SLOT(internalUpdateSource(DataContainer*)));
|
||||
QObject::connect(source, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*)));
|
||||
d->sources.insert(source->objectName(), source);
|
||||
emit sourceAdded(source->objectName());
|
||||
scheduleSourcesUpdated();
|
||||
}
|
||||
|
||||
void DataEngine::setMinimumPollingInterval(int minimumMs)
|
||||
{
|
||||
d->minPollingInterval = minimumMs;
|
||||
}
|
||||
|
||||
int DataEngine::minimumPollingInterval() const
|
||||
{
|
||||
return d->minPollingInterval;
|
||||
}
|
||||
|
||||
void DataEngine::setPollingInterval(uint frequency)
|
||||
{
|
||||
killTimer(d->updateTimerId);
|
||||
d->updateTimerId = 0;
|
||||
|
||||
if (frequency > 0) {
|
||||
d->updateTimerId = startTimer(frequency);
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::removeSource(const QString &source)
|
||||
{
|
||||
SourceDict::iterator it = d->sources.find(source);
|
||||
if (it != d->sources.end()) {
|
||||
DataContainer *s = it.value();
|
||||
s->d->store();
|
||||
s->disconnect(this);
|
||||
s->deleteLater();
|
||||
d->sources.erase(it);
|
||||
emit sourceRemoved(source);
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::removeAllSources()
|
||||
{
|
||||
QMutableHashIterator<QString, Plasma::DataContainer*> it(d->sources);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
Plasma::DataContainer *s = it.value();
|
||||
const QString source = it.key();
|
||||
it.remove();
|
||||
s->disconnect(this);
|
||||
s->deleteLater();
|
||||
emit sourceRemoved(source);
|
||||
}
|
||||
}
|
||||
|
||||
bool DataEngine::isValid() const
|
||||
{
|
||||
return d->valid;
|
||||
}
|
||||
|
||||
bool DataEngine::isEmpty() const
|
||||
{
|
||||
return d->sources.isEmpty();
|
||||
}
|
||||
|
||||
void DataEngine::setValid(bool valid)
|
||||
{
|
||||
d->valid = valid;
|
||||
}
|
||||
|
||||
DataEngine::SourceDict DataEngine::containerDict() const
|
||||
{
|
||||
return d->sources;
|
||||
}
|
||||
|
||||
void DataEngine::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
//kDebug();
|
||||
if (event->timerId() == d->updateTimerId) {
|
||||
// if the freq update is less than 0, don't bother
|
||||
if (d->minPollingInterval < 0) {
|
||||
//kDebug() << "uh oh.. no polling allowed!";
|
||||
return;
|
||||
}
|
||||
|
||||
// minPollingInterval
|
||||
if (d->updateTimestamp.elapsed() < d->minPollingInterval) {
|
||||
//kDebug() << "hey now.. slow down!";
|
||||
return;
|
||||
}
|
||||
|
||||
d->updateTimestamp.restart();
|
||||
updateAllSources();
|
||||
} else if (event->timerId() == d->checkSourcesTimerId) {
|
||||
killTimer(d->checkSourcesTimerId);
|
||||
d->checkSourcesTimerId = 0;
|
||||
|
||||
QHashIterator<QString, Plasma::DataContainer*> it(d->sources);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
it.value()->checkForUpdate();
|
||||
}
|
||||
} else {
|
||||
QObject::timerEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::updateAllSources()
|
||||
{
|
||||
QHashIterator<QString, Plasma::DataContainer*> it(d->sources);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
//kDebug() << "updating" << it.key();
|
||||
updateSourceEvent(it.key());
|
||||
}
|
||||
|
||||
scheduleSourcesUpdated();
|
||||
}
|
||||
|
||||
void DataEngine::forceImmediateUpdateOfAllVisualizations()
|
||||
{
|
||||
foreach (DataContainer *source, d->sources) {
|
||||
source->forceImmediateUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngine::setIcon(const QString &icon)
|
||||
{
|
||||
d->icon = icon;
|
||||
}
|
||||
|
||||
QString DataEngine::icon() const
|
||||
{
|
||||
return d->icon;
|
||||
}
|
||||
|
||||
QString DataEngine::pluginName() const
|
||||
{
|
||||
if (!d->dataEngineDescription.isValid()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return d->dataEngineDescription.pluginName();
|
||||
}
|
||||
|
||||
void DataEngine::setDefaultService(const QString &serviceName)
|
||||
{
|
||||
d->serviceName = serviceName;
|
||||
}
|
||||
|
||||
Service* DataEngine::createDefaultService(QObject *parent)
|
||||
{
|
||||
QVariantList args;
|
||||
args << QVariant::fromValue<DataEngine*>(this);
|
||||
return PluginLoader::self()->loadService(d->serviceName, args, parent);
|
||||
}
|
||||
|
||||
void DataEnginePrivate::publish(AnnouncementMethods methods, const QString &name)
|
||||
{
|
||||
if (!publishedService) {
|
||||
publishedService = new DataEngineService(q);
|
||||
}
|
||||
|
||||
//QString resourceName =
|
||||
//i18nc("%1 is the name of a dataengine, %2 the name of the machine that engine is published
|
||||
//on",
|
||||
//"%1 dataengine on %2", name(), AuthorizationManager::self()->d->myCredentials.name());
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "name: " << name;
|
||||
#endif
|
||||
publishedService->d->publish(methods, name);
|
||||
}
|
||||
|
||||
void DataEnginePrivate::unpublish(const QString &name)
|
||||
{
|
||||
Q_UNUSED(name)
|
||||
|
||||
if (publishedService) {
|
||||
publishedService->d->unpublish();
|
||||
}
|
||||
}
|
||||
|
||||
bool DataEnginePrivate::isPublished() const
|
||||
{
|
||||
if (publishedService) {
|
||||
return publishedService->d->isPublished();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Package DataEngine::package() const
|
||||
{
|
||||
return d->package ? *d->package : Package();
|
||||
}
|
||||
|
||||
void DataEngine::scheduleSourcesUpdated()
|
||||
{
|
||||
if (d->checkSourcesTimerId) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->checkSourcesTimerId = startTimer(0);
|
||||
}
|
||||
|
||||
QString DataEngine::name() const
|
||||
{
|
||||
return d->engineName;
|
||||
}
|
||||
|
||||
void DataEngine::setName(const QString &name)
|
||||
{
|
||||
d->engineName = name;
|
||||
setObjectName(name);
|
||||
}
|
||||
|
||||
void DataEngine::setStorageEnabled(const QString &source, bool store)
|
||||
{
|
||||
DataContainer *s = d->source(source, false);
|
||||
if (s) {
|
||||
s->setStorageEnabled(store);
|
||||
}
|
||||
}
|
||||
|
||||
// Private class implementations
|
||||
DataEnginePrivate::DataEnginePrivate(DataEngine *e, const KPluginInfo &info)
|
||||
: q(e),
|
||||
dataEngineDescription(info),
|
||||
refCount(-1), // first ref
|
||||
checkSourcesTimerId(0),
|
||||
updateTimerId(0),
|
||||
minPollingInterval(-1),
|
||||
valid(true),
|
||||
script(0),
|
||||
package(0),
|
||||
publishedService(0)
|
||||
{
|
||||
updateTimestamp.start();
|
||||
|
||||
if (!info.isValid()) {
|
||||
engineName = i18n("Unnamed");
|
||||
return;
|
||||
}
|
||||
|
||||
engineName = info.name();
|
||||
if (engineName.isEmpty()) {
|
||||
engineName = i18n("Unnamed");
|
||||
}
|
||||
e->setObjectName(engineName);
|
||||
icon = info.icon();
|
||||
|
||||
if (dataEngineDescription.isValid()) {
|
||||
QString api = dataEngineDescription.property("X-Plasma-API").toString();
|
||||
|
||||
if (!api.isEmpty()) {
|
||||
const QString path =
|
||||
KStandardDirs::locate("data",
|
||||
"plasma/dataengines/" + dataEngineDescription.pluginName() + '/');
|
||||
package = new Package(PluginLoader::self()->loadPackage("Plasma/DataEngine", api));
|
||||
package->setPath(path);
|
||||
|
||||
if (package->isValid()) {
|
||||
script = Plasma::loadScriptEngine(api, q);
|
||||
}
|
||||
|
||||
if (!script) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Could not create a" << api << "ScriptEngine for the"
|
||||
<< dataEngineDescription.name() << "DataEngine.";
|
||||
#endif
|
||||
delete package;
|
||||
package = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DataEnginePrivate::~DataEnginePrivate()
|
||||
{
|
||||
delete script;
|
||||
script = 0;
|
||||
delete package;
|
||||
package = 0;
|
||||
}
|
||||
|
||||
void DataEnginePrivate::internalUpdateSource(DataContainer *source)
|
||||
{
|
||||
if (minPollingInterval > 0 &&
|
||||
source->timeSinceLastUpdate() < (uint)minPollingInterval) {
|
||||
// skip updating this source; it's been too soon
|
||||
//kDebug() << "internal update source is delaying" << source->timeSinceLastUpdate() << minPollingInterval;
|
||||
//but fake an update so that the signalrelay that triggered this gets the data from the
|
||||
//recent update. this way we don't have to worry about queuing - the relay will send a
|
||||
//signal immediately and everyone else is undisturbed.
|
||||
source->setNeedsUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (q->updateSourceEvent(source->objectName())) {
|
||||
//kDebug() << "queuing an update";
|
||||
q->scheduleSourcesUpdated();
|
||||
}/* else {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "no update";
|
||||
#endif
|
||||
}*/
|
||||
}
|
||||
|
||||
void DataEnginePrivate::ref()
|
||||
{
|
||||
--refCount;
|
||||
}
|
||||
|
||||
void DataEnginePrivate::deref()
|
||||
{
|
||||
++refCount;
|
||||
}
|
||||
|
||||
bool DataEnginePrivate::isUsed() const
|
||||
{
|
||||
return refCount != 0;
|
||||
}
|
||||
|
||||
DataContainer *DataEnginePrivate::source(const QString &sourceName, bool createWhenMissing)
|
||||
{
|
||||
DataEngine::SourceDict::const_iterator it = sources.constFind(sourceName);
|
||||
if (it != sources.constEnd()) {
|
||||
DataContainer *s = it.value();
|
||||
return s;
|
||||
}
|
||||
|
||||
if (!createWhenMissing) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//kDebug() << "DataEngine " << q->objectName() << ": could not find DataContainer " << sourceName << ", creating";
|
||||
DataContainer *s = new DataContainer(q);
|
||||
s->setObjectName(sourceName);
|
||||
sources.insert(sourceName, s);
|
||||
QObject::connect(s, SIGNAL(destroyed(QObject*)), q, SLOT(sourceDestroyed(QObject*)));
|
||||
QObject::connect(s, SIGNAL(updateRequested(DataContainer*)),
|
||||
q, SLOT(internalUpdateSource(DataContainer*)));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void DataEnginePrivate::connectSource(DataContainer *s, QObject *visualization,
|
||||
uint pollingInterval,
|
||||
Plasma::IntervalAlignment align,
|
||||
bool immediateCall)
|
||||
{
|
||||
//kDebug() << "connect source called" << s->objectName() << "with interval" << pollingInterval;
|
||||
|
||||
//FIXME: at the moment a remote dataengine can only poll, a push mechanism will be needed instead
|
||||
if (pollingInterval == 0 && qobject_cast<RemoteDataEngine *>(q)) {
|
||||
pollingInterval = 5000;
|
||||
}
|
||||
if (pollingInterval > 0) {
|
||||
// never more frequently than allowed, never more than 20 times per second
|
||||
uint min = qMax(50, minPollingInterval); // for qMax below
|
||||
pollingInterval = qMax(min, pollingInterval);
|
||||
|
||||
// align on the 50ms
|
||||
pollingInterval = pollingInterval - (pollingInterval % 50);
|
||||
}
|
||||
|
||||
if (immediateCall) {
|
||||
// we don't want to do an immediate call if we are simply
|
||||
// reconnecting
|
||||
//kDebug() << "immediate call requested, we have:" << s->visualizationIsConnected(visualization);
|
||||
immediateCall = !s->data().isEmpty() &&
|
||||
!s->visualizationIsConnected(visualization);
|
||||
}
|
||||
|
||||
s->connectVisualization(visualization, pollingInterval, align);
|
||||
|
||||
if (immediateCall) {
|
||||
QMetaObject::invokeMethod(visualization, "dataUpdated",
|
||||
Q_ARG(QString, s->objectName()),
|
||||
Q_ARG(Plasma::DataEngine::Data, s->data()));
|
||||
s->d->dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DataEnginePrivate::sourceDestroyed(QObject *object)
|
||||
{
|
||||
DataEngine::SourceDict::iterator it = sources.begin();
|
||||
while (it != sources.end()) {
|
||||
if (it.value() == object) {
|
||||
sources.erase(it);
|
||||
emit q->sourceRemoved(object->objectName());
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
DataContainer *DataEnginePrivate::requestSource(const QString &sourceName, bool *newSource)
|
||||
{
|
||||
if (newSource) {
|
||||
*newSource = false;
|
||||
}
|
||||
|
||||
//kDebug() << "requesting source " << sourceName;
|
||||
DataContainer *s = source(sourceName, false);
|
||||
|
||||
if (!s) {
|
||||
// we didn't find a data source, so give the engine an opportunity to make one
|
||||
/*kDebug() << "DataEngine " << q->objectName()
|
||||
<< ": could not find DataContainer " << sourceName
|
||||
<< " will create on request" << endl;*/
|
||||
waitingSourceRequest = sourceName;
|
||||
if (q->sourceRequestEvent(sourceName)) {
|
||||
s = source(sourceName, false);
|
||||
if (s) {
|
||||
// now we have a source; since it was created on demand, assume
|
||||
// it should be removed when not used
|
||||
if (newSource) {
|
||||
*newSource = true;
|
||||
}
|
||||
QObject::connect(s, SIGNAL(becameUnused(QString)), q, SLOT(removeSource(QString)));
|
||||
emit q->sourceAdded(sourceName);
|
||||
}
|
||||
}
|
||||
waitingSourceRequest.clear();
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// put all setup routines for script here. at this point we can assume that
|
||||
// package exists and that we have a script engine
|
||||
void DataEnginePrivate::setupScriptSupport()
|
||||
{
|
||||
if (!package) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "sletting up script support, package is in" << package->path()
|
||||
#endif
|
||||
<< "which is a" << package->structure()->type() << "package"
|
||||
<< ", main script is" << package->filePath("mainscript");
|
||||
*/
|
||||
|
||||
const QString translationsPath = package->filePath("translations");
|
||||
if (!translationsPath.isEmpty()) {
|
||||
KGlobal::dirs()->addResourceDir("locale", translationsPath);
|
||||
KLocalizedString::insertCatalog(dataEngineDescription.pluginName());
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DataEngine::listAllEngines(const QString &parentApp)
|
||||
{
|
||||
QString constraint;
|
||||
|
||||
if (parentApp.isEmpty()) {
|
||||
constraint.append("(not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '')");
|
||||
} else {
|
||||
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint);
|
||||
|
||||
QStringList engines;
|
||||
foreach (const KService::Ptr &service, offers) {
|
||||
QString name = service->property("X-KDE-PluginInfo-Name").toString();
|
||||
if (!name.isEmpty()) {
|
||||
engines.append(name);
|
||||
}
|
||||
}
|
||||
|
||||
return engines;
|
||||
}
|
||||
|
||||
KPluginInfo::List DataEngine::listEngineInfo(const QString &parentApp)
|
||||
{
|
||||
return PluginLoader::self()->listDataEngineInfo(parentApp);
|
||||
}
|
||||
|
||||
KPluginInfo::List DataEngine::listEngineInfoByCategory(const QString &category, const QString &parentApp)
|
||||
{
|
||||
QString constraint = QString("[X-KDE-PluginInfo-Category] == '%1'").arg(category);
|
||||
|
||||
if (parentApp.isEmpty()) {
|
||||
constraint.append(" and not exist [X-KDE-ParentApp]");
|
||||
} else {
|
||||
constraint.append(" and [X-KDE-ParentApp] == '").append(parentApp).append("'");
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint);
|
||||
return KPluginInfo::fromServices(offers);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include "moc_dataengine.cpp"
|
548
plasma/dataengine.h
Normal file
548
plasma/dataengine.h
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 PLASMA_DATAENGINE_H
|
||||
#define PLASMA_DATAENGINE_H
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
#include <kservice.h>
|
||||
|
||||
#include <plasma/version.h>
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/service.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataContainer;
|
||||
class DataEngineScript;
|
||||
class Package;
|
||||
class Service;
|
||||
class DataEnginePrivate;
|
||||
|
||||
/**
|
||||
* @class DataEngine plasma/dataengine.h <Plasma/DataEngine>
|
||||
*
|
||||
* @short Data provider for plasmoids (Plasma plugins)
|
||||
*
|
||||
* This is the base class for DataEngines, which provide access to bodies of
|
||||
* data via a common and consistent interface. The common use of a DataEngine
|
||||
* is to provide data to a widget for display. This allows a user interface
|
||||
* element to show all sorts of data: as long as there is a DataEngine, the
|
||||
* data is retrievable.
|
||||
*
|
||||
* DataEngines are loaded as plugins on demand and provide zero, one or more
|
||||
* data sources which are identified by name. For instance, a network
|
||||
* DataEngine might provide a data source for each network interface.
|
||||
**/
|
||||
class PLASMA_EXPORT DataEngine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QStringList sources READ sources)
|
||||
Q_PROPERTY(bool valid READ isValid)
|
||||
Q_PROPERTY(QString icon READ icon WRITE setIcon)
|
||||
Q_PROPERTY(QString name READ name)
|
||||
|
||||
public:
|
||||
typedef QHash<QString, DataEngine*> Dict;
|
||||
typedef QHash<QString, QVariant> Data;
|
||||
typedef QHashIterator<QString, QVariant> DataIterator;
|
||||
typedef QHash<QString, DataContainer*> SourceDict;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param parent The parent object.
|
||||
* @param service pointer to the service that describes the engine
|
||||
**/
|
||||
explicit DataEngine(QObject *parent = 0, KService::Ptr service = KService::Ptr(0));
|
||||
DataEngine(QObject *parent, const QVariantList &args);
|
||||
~DataEngine();
|
||||
|
||||
/**
|
||||
* This method is called when the DataEngine is started. When this
|
||||
* method is called the DataEngine is fully constructed and ready to be
|
||||
* used. This method should be reimplemented by DataEngine subclasses
|
||||
* which need to perform a startup routine.
|
||||
*
|
||||
* The default implementation does nothing. Reimplementations in
|
||||
* subclasses don't need to call this one.
|
||||
**/
|
||||
virtual void init();
|
||||
|
||||
/**
|
||||
* @return a list of all the data sources available via this DataEngine
|
||||
* Whether these sources are currently available (which is what
|
||||
* the default implementation provides) or not is up to the
|
||||
* DataEngine to decide.
|
||||
**/
|
||||
virtual QStringList sources() const;
|
||||
|
||||
/**
|
||||
* @param source the source to target the Service at
|
||||
* @return a Service that has the source as a destination. The service
|
||||
* is parented to the DataEngine, but should be deleted by the
|
||||
* caller when finished with it
|
||||
*/
|
||||
Q_INVOKABLE virtual Service *serviceForSource(const QString &source);
|
||||
|
||||
/**
|
||||
* Returns the engine name for the DataEngine
|
||||
*/
|
||||
QString name() const;
|
||||
|
||||
/**
|
||||
* Connects a source to an object for data updates. The object must
|
||||
* have a slot with the following signature:
|
||||
*
|
||||
* dataUpdated(const QString &sourceName, const Plasma::DataEngine::Data &data)
|
||||
*
|
||||
* The data is a QHash of QVariants keyed by QString names, allowing
|
||||
* one data source to provide sets of related data.
|
||||
*
|
||||
* @param source the name of the data source
|
||||
* @param visualization the object to connect the data source to
|
||||
* @param pollingInterval the frequency, in milliseconds, with which to check for updates;
|
||||
* a value of 0 (the default) means to update only
|
||||
* when there is new data spontaneously generated
|
||||
* (e.g. by the engine); any other value results in
|
||||
* periodic updates from this source. This value is
|
||||
* per-visualization and can be handy for items that require
|
||||
* constant updates such as scrolling graphs or clocks.
|
||||
* If the data has not changed, no update will be sent.
|
||||
* @param intervalAlignment the number of ms to align the interval to
|
||||
**/
|
||||
Q_INVOKABLE void connectSource(
|
||||
const QString &source, QObject *visualization,
|
||||
uint pollingInterval = 0,
|
||||
Plasma::IntervalAlignment intervalAlignment = NoAlignment) const;
|
||||
|
||||
/**
|
||||
* Connects all currently existing sources to an object for data updates.
|
||||
* The object must have a slot with the following signature:
|
||||
*
|
||||
* SLOT(dataUpdated(QString,Plasma::DataEngine::Data))
|
||||
*
|
||||
* The data is a QHash of QVariants keyed by QString names, allowing
|
||||
* one data source to provide sets of related data.
|
||||
*
|
||||
* This method may be called multiple times for the same visualization
|
||||
* without side-effects. This can be useful to change the pollingInterval.
|
||||
*
|
||||
* Note that this method does not automatically connect sources that
|
||||
* may appear later on. Connecting and responding to the sourceAdded signal
|
||||
* is still required to achieve that.
|
||||
*
|
||||
* @param visualization the object to connect the data source to
|
||||
* @param pollingInterval the frequency, in milliseconds, with which to check for updates;
|
||||
* a value of 0 (the default) means to update only
|
||||
* when there is new data spontaneously generated
|
||||
* (e.g. by the engine); any other value results in
|
||||
* periodic updates from this source. This value is
|
||||
* per-visualization and can be handy for items that require
|
||||
* constant updates such as scrolling graphs or clocks.
|
||||
* If the data has not changed, no update will be sent.
|
||||
* @param intervalAlignment the number of ms to align the interval to
|
||||
**/
|
||||
Q_INVOKABLE void connectAllSources(QObject *visualization, uint pollingInterval = 0,
|
||||
Plasma::IntervalAlignment intervalAlignment =
|
||||
NoAlignment) const;
|
||||
|
||||
/**
|
||||
* Disconnects a source from an object that was receiving data updates.
|
||||
*
|
||||
* @param source the name of the data source
|
||||
* @param visualization the object to connect the data source to
|
||||
**/
|
||||
Q_INVOKABLE void disconnectSource(const QString &source, QObject *visualization) const;
|
||||
|
||||
/**
|
||||
* Retrieves a pointer to the DataContainer for a given source. This method
|
||||
* should not be used if possible. An exception is for script engines that
|
||||
* can not provide a QMetaObject as required by connectSource for the initial
|
||||
* call to dataUpdated. Using this method, such engines can provide their own
|
||||
* connectSource API.
|
||||
*
|
||||
* @param source the name of the source.
|
||||
* @return pointer to a DataContainer, or zero on failure
|
||||
**/
|
||||
Q_INVOKABLE DataContainer *containerForSource(const QString &source);
|
||||
|
||||
/**
|
||||
* Gets the Data associated with a data source.
|
||||
*
|
||||
* The data is a QHash of QVariants keyed by QString names, allowing
|
||||
* one data source to provide sets of related data.
|
||||
*
|
||||
* @param source the data source to retrieve the data for
|
||||
* @return the Data associated with the source; if the source doesn't
|
||||
* exist an empty data set is returned
|
||||
**/
|
||||
Q_INVOKABLE DataEngine::Data query(const QString &source) const;
|
||||
|
||||
/**
|
||||
* Returns true if this engine is valid, otherwise returns false
|
||||
*
|
||||
* @return true if the engine is valid
|
||||
**/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Returns true if the data engine is empty, which is to say that it has no
|
||||
* data sources currently.
|
||||
*
|
||||
* @return true if the engine has no sources currently
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
* @return the name of the icon for this data engine; and empty string
|
||||
* is returned if there is no associated icon.
|
||||
**/
|
||||
QString icon() const;
|
||||
|
||||
/**
|
||||
* Accessor for the associated Package object if any.
|
||||
*
|
||||
* @return the Package object, or 0 if none
|
||||
**/
|
||||
Package package() const;
|
||||
|
||||
/**
|
||||
* @return the plugin name for the applet
|
||||
*/
|
||||
QString pluginName() const;
|
||||
|
||||
/**
|
||||
* Initializes and returns a new service from the name that was set
|
||||
* with setDefaultService. (service name is set internally). Remember to dispose
|
||||
* of the Service* when you are finished with it (even if a parent is passed)
|
||||
* A DataEngine* is sent to the created service via the QVariantList arguments.
|
||||
*
|
||||
* @see setDefaultService
|
||||
* @param the parent of the object, if any, for the returned service
|
||||
* @return the newly created service
|
||||
* @since 4.5
|
||||
*/
|
||||
Q_INVOKABLE Service* createDefaultService(QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* @return a listing of all known DataEngines by name
|
||||
*
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
*/
|
||||
static QStringList listAllEngines(const QString &parentApp = QString());
|
||||
|
||||
/**
|
||||
* Returns a list of all known DataEngines.
|
||||
*
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of DataEngines
|
||||
**/
|
||||
static KPluginInfo::List listEngineInfo(const QString &parentApp = QString());
|
||||
|
||||
/**
|
||||
* Returns a list of all known DataEngines filtering by category.
|
||||
*
|
||||
* @param category the category to filter applets on. Uses the
|
||||
* X-KDE-PluginInfo-Category entry (if any) in the
|
||||
* plugin info. The value of QString() will
|
||||
* result in a list of engines with an empty category.
|
||||
*
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of DataEngines
|
||||
* @since 4.3
|
||||
**/
|
||||
static KPluginInfo::List listEngineInfoByCategory(const QString &category, const QString &parentApp = QString());
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emitted when a new data source is created
|
||||
*
|
||||
* Note that you do not need to emit this yourself unless
|
||||
* you are reimplementing sources() and want to advertise
|
||||
* that a new source is available (but hasn't been created
|
||||
* yet).
|
||||
*
|
||||
* @param source the name of the new data source
|
||||
**/
|
||||
void sourceAdded(const QString &source);
|
||||
|
||||
/**
|
||||
* Emitted when a data source is removed.
|
||||
*
|
||||
* Note that you do not need to emit this yourself unless
|
||||
* you have reimplemented sources() and want to signal that
|
||||
* a source that was available but was never created is no
|
||||
* longer available.
|
||||
*
|
||||
* @param source the name of the data source that was removed
|
||||
**/
|
||||
void sourceRemoved(const QString &source);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* When a source that does not currently exist is requested by the
|
||||
* consumer, this method is called to give the DataEngine the
|
||||
* opportunity to create one.
|
||||
*
|
||||
* The name of the data source (e.g. the source parameter passed into
|
||||
* setData) must be the same as the name passed to sourceRequestEvent
|
||||
* otherwise the requesting visualization may not receive notice of a
|
||||
* data update.
|
||||
*
|
||||
* If the source can not be populated with data immediately (e.g. due to
|
||||
* an asynchronous data acquisition method such as an HTTP request)
|
||||
* the source must still be created, even if it is empty. This can
|
||||
* be accomplished in these cases with the follow line:
|
||||
*
|
||||
* setData(name, DataEngine::Data());
|
||||
*
|
||||
* @param source the name of the source that has been requested
|
||||
* @return true if a DataContainer was set up, false otherwise
|
||||
*/
|
||||
virtual bool sourceRequestEvent(const QString &source);
|
||||
|
||||
/**
|
||||
* Called by internal updating mechanisms to trigger the engine
|
||||
* to refresh the data contained in a given source. Reimplement this
|
||||
* method when using facilities such as setPollingInterval.
|
||||
* @see setPollingInterval
|
||||
*
|
||||
* @param source the name of the source that should be updated
|
||||
* @return true if the data was changed, or false if there was no
|
||||
* change or if the change will occur later
|
||||
**/
|
||||
virtual bool updateSourceEvent(const QString &source);
|
||||
|
||||
/**
|
||||
* Sets a value for a data source. If the source
|
||||
* doesn't exist then it is created.
|
||||
*
|
||||
* @param source the name of the data source
|
||||
* @param value the data to associated with the source
|
||||
**/
|
||||
void setData(const QString &source, const QVariant &value);
|
||||
|
||||
/**
|
||||
* Sets a value for a data source. If the source
|
||||
* doesn't exist then it is created.
|
||||
*
|
||||
* @param source the name of the data source
|
||||
* @param key the key to use for the data
|
||||
* @param value the data to associated with the source
|
||||
**/
|
||||
void setData(const QString &source, const QString &key, const QVariant &value);
|
||||
|
||||
/**
|
||||
* Adds a set of data to a data source. If the source
|
||||
* doesn't exist then it is created.
|
||||
*
|
||||
* @param source the name of the data source
|
||||
* @param data the data to add to the source
|
||||
**/
|
||||
void setData(const QString &source, const Data &data);
|
||||
|
||||
/**
|
||||
* Removes all the data associated with a data source.
|
||||
*
|
||||
* @param source the name of the data source
|
||||
**/
|
||||
void removeAllData(const QString &source);
|
||||
|
||||
/**
|
||||
* Removes a data entry from a source
|
||||
*
|
||||
* @param source the name of the data source
|
||||
* @param key the data entry to remove
|
||||
**/
|
||||
void removeData(const QString &source, const QString &key);
|
||||
|
||||
/**
|
||||
* Adds an already constructed data source. The DataEngine takes
|
||||
* ownership of the DataContainer object. The objectName of the source
|
||||
* is used for the source name.
|
||||
*
|
||||
* @param source the DataContainer to add to the DataEngine
|
||||
**/
|
||||
void addSource(DataContainer *source);
|
||||
|
||||
/**
|
||||
* Sets the minimum amount of time, in milliseconds, that must pass between
|
||||
* successive updates of data. This can help prevent too many updates happening
|
||||
* due to multiple update requests coming in, which can be useful for
|
||||
* expensive (time- or resource-wise) update mechanisms.
|
||||
*
|
||||
* The default minimumPollingInterval is -1, or "never perform automatic updates"
|
||||
*
|
||||
* @param minimumMs the minimum time lapse, in milliseconds, between updates.
|
||||
* A value less than 0 means to never perform automatic updates,
|
||||
* a value of 0 means update immediately on every update request,
|
||||
* a value >0 will result in a minimum time lapse being enforced.
|
||||
**/
|
||||
void setMinimumPollingInterval(int minimumMs);
|
||||
|
||||
/**
|
||||
* @return the minimum time between updates. @see setMinimumPollingInterval
|
||||
**/
|
||||
int minimumPollingInterval() const;
|
||||
|
||||
/**
|
||||
* Sets up an internal update tick for all data sources. On every update,
|
||||
* updateSourceEvent will be called for each applicable source.
|
||||
* @see updateSourceEvent
|
||||
*
|
||||
* @param frequency the time, in milliseconds, between updates. A value of 0
|
||||
* will stop internally triggered updates.
|
||||
**/
|
||||
void setPollingInterval(uint frequency);
|
||||
|
||||
/**
|
||||
* Removes all data sources
|
||||
**/
|
||||
void removeAllSources();
|
||||
|
||||
/**
|
||||
* Sets whether or not this engine is valid, e.g. can be used.
|
||||
* In practice, only the internal fall-back engine, the NullEngine
|
||||
* should have need for this.
|
||||
*
|
||||
* @param valid whether or not the engine is valid
|
||||
**/
|
||||
void setValid(bool valid);
|
||||
|
||||
/**
|
||||
* @return the list of active DataContainers.
|
||||
*/
|
||||
SourceDict containerDict() const;
|
||||
|
||||
/**
|
||||
* Reimplemented from QObject
|
||||
**/
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
/**
|
||||
* Sets the engine name for the DataEngine
|
||||
*/
|
||||
void setName(const QString &name);
|
||||
|
||||
/**
|
||||
* Sets the icon for this data engine
|
||||
**/
|
||||
void setIcon(const QString &icon);
|
||||
|
||||
/**
|
||||
* Should be set if there will be 1 main service.
|
||||
* This saves any users of this DataEngine from having to know the service name to load.
|
||||
* It is not created until createDefaultService is called.
|
||||
*
|
||||
* @code
|
||||
* DataEngine *engine = dataEngine("foo");
|
||||
* Service *service = engine->createDefaultService(this);
|
||||
* @endcode
|
||||
*
|
||||
* @see createDefaultService
|
||||
* @param serviceName the name of the service to load (plugin name)
|
||||
* @since 4.5
|
||||
*/
|
||||
void setDefaultService(const QString &serviceName);
|
||||
|
||||
/**
|
||||
* Sets a source to be stored for easy retrieval
|
||||
* when the real source of the data (usually a network connection)
|
||||
* is unavailable.
|
||||
* @param source the name of the source
|
||||
* @param store if source should be stored
|
||||
* @since 4.6
|
||||
*/
|
||||
void setStorageEnabled(const QString &source, bool store);
|
||||
|
||||
protected Q_SLOTS:
|
||||
/**
|
||||
* Call this method when you call setData directly on a DataContainer instead
|
||||
* of using the DataEngine::setData methods.
|
||||
* If this method is not called, no dataUpdated(..) signals will be emitted!
|
||||
*/
|
||||
void scheduleSourcesUpdated();
|
||||
|
||||
/**
|
||||
* Removes a data source.
|
||||
* @param source the name of the data source to remove
|
||||
**/
|
||||
void removeSource(const QString &source);
|
||||
|
||||
/**
|
||||
* Immediately updates all existing sources when called
|
||||
*/
|
||||
void updateAllSources();
|
||||
|
||||
/**
|
||||
* Forces an immediate update to all connected sources, even those with
|
||||
* timeouts that haven't yet expired. This should _only_ be used when
|
||||
* there was no data available, e.g. due to network non-availability,
|
||||
* and then it becomes available. Normal changes in data values due to
|
||||
* calls to updateSource or in the natural progression of the monitored
|
||||
* object (e.g. CPU heat) should not result in a call to this method!
|
||||
*
|
||||
* @since 4.4
|
||||
*/
|
||||
void forceImmediateUpdateOfAllVisualizations();
|
||||
|
||||
private:
|
||||
friend class DataEnginePrivate;
|
||||
friend class DataEngineScript;
|
||||
friend class DataEngineManager;
|
||||
friend class PlasmoidServiceJob;
|
||||
friend class NullEngine;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void internalUpdateSource(DataContainer *source))
|
||||
Q_PRIVATE_SLOT(d, void sourceDestroyed(QObject *object))
|
||||
|
||||
DataEnginePrivate *const d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
/**
|
||||
* Register a data engine when it is contained in a loadable module
|
||||
*/
|
||||
#define K_EXPORT_PLASMA_DATAENGINE(libname, classname) \
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
|
||||
K_EXPORT_PLUGIN(factory("plasma_engine_" #libname)) \
|
||||
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
|
||||
|
||||
Q_DECLARE_METATYPE(Plasma::DataEngine*)
|
||||
|
||||
#endif // multiple inclusion guard
|
161
plasma/dataengineconsumer.cpp
Normal file
161
plasma/dataengineconsumer.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright 2005 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
*
|
||||
* 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 "dataengineconsumer.h"
|
||||
#include "private/dataengineconsumer_p.h"
|
||||
|
||||
#include <QSet>
|
||||
#include <qurlpathinfo.h>
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
#include "private/dataenginemanager_p.h"
|
||||
#include "private/remotedataengine_p.h"
|
||||
#include "servicejob.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
void DataEngineConsumerPrivate::slotJobFinished(Plasma::ServiceJob *job)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "engine ready!";
|
||||
#endif
|
||||
QString engineName = job->parameters()["EngineName"].toString();
|
||||
QString location = job->destination();
|
||||
QPair<QString, QString> pair(location, engineName);
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "pair = " << pair;
|
||||
#endif
|
||||
if (!remoteEngines.contains(pair)) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "engine does not exist yet!";
|
||||
#endif
|
||||
} else {
|
||||
QUrlPathInfo engineLocation = QUrlPathInfo(QUrl(location));
|
||||
engineLocation.setFileName(job->result().toString());
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "setting location : " << engineLocation.url();
|
||||
#endif
|
||||
remoteEngines[pair]->setLocation(engineLocation.url());
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngineConsumerPrivate::slotServiceReady(Plasma::Service *plasmoidService)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "service ready!";
|
||||
#endif
|
||||
if (!engineNameForService.contains(plasmoidService)) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "no engine name for service!";
|
||||
#endif
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "amount of services in map: " << engineNameForService.count();
|
||||
#endif
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "value = " << engineNameForService.value(plasmoidService);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "requesting dataengine!";
|
||||
#endif
|
||||
KConfigGroup op = plasmoidService->operationDescription("DataEngine");
|
||||
op.writeEntry("EngineName", engineNameForService.value(plasmoidService));
|
||||
plasmoidService->startOperationCall(op);
|
||||
connect(plasmoidService, SIGNAL(finished(Plasma::ServiceJob*)),
|
||||
this, SLOT(slotJobFinished(Plasma::ServiceJob*)));
|
||||
}
|
||||
|
||||
DataEngine *DataEngineConsumerPrivate::remoteDataEngine(const QString &name, const QUrl &location)
|
||||
{
|
||||
QPair<QString, QString> pair(location.toString(), name);
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "pair = " << pair;
|
||||
#endif
|
||||
if (remoteEngines.contains(pair)) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "existing remote dataengine at " << location;
|
||||
#endif
|
||||
return remoteEngines[pair];
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "new remote dataengine at " << location;
|
||||
#endif
|
||||
RemoteDataEngine *engine = new RemoteDataEngine(QUrl());
|
||||
remoteEngines[pair] = engine;
|
||||
Service *plasmoidService = Service::access(location);
|
||||
plasmoidService->setDestination(location.toString());
|
||||
engineNameForService[plasmoidService] = name;
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "name = " << name;
|
||||
#endif
|
||||
|
||||
connect(plasmoidService, SIGNAL(serviceReady(Plasma::Service*)),
|
||||
this, SLOT(slotServiceReady(Plasma::Service*)));
|
||||
return engine;
|
||||
}
|
||||
|
||||
DataEngineConsumer::DataEngineConsumer()
|
||||
: d(new DataEngineConsumerPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
DataEngineConsumer::~DataEngineConsumer()
|
||||
{
|
||||
foreach (const QString &engine, d->loadedEngines) {
|
||||
DataEngineManager::self()->unloadEngine(engine);
|
||||
}
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
DataEngine *DataEngineConsumer::dataEngine(const QString &name, const QUrl &location)
|
||||
{
|
||||
if (!location.isEmpty()) {
|
||||
return d->remoteDataEngine(name, location);
|
||||
}
|
||||
|
||||
if (d->loadedEngines.contains(name)) {
|
||||
DataEngine *engine = DataEngineManager::self()->engine(name);
|
||||
if (engine->isValid()) {
|
||||
return engine;
|
||||
} else {
|
||||
d->loadedEngines.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
DataEngine *engine = DataEngineManager::self()->loadEngine(name);
|
||||
if (engine->isValid()) {
|
||||
d->loadedEngines.insert(name);
|
||||
}
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#include "private/moc_dataengineconsumer_p.cpp"
|
||||
|
||||
|
83
plasma/dataengineconsumer.h
Normal file
83
plasma/dataengineconsumer.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2012 by Aaron Seigo <aseigo@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 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 PLASMA_DATAENGINECONSUMER_H
|
||||
#define PLASMA_DATAENGINECONSUMER_H
|
||||
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataEngine;
|
||||
class DataEngineConsumerPrivate;
|
||||
|
||||
/**
|
||||
* @class DataEngineConsumer plasma/dataengineconsumer.h <Plasma/DataEngineConsumer>
|
||||
*
|
||||
* @brief A class that makes it safe and easy to use DataEngines
|
||||
*
|
||||
* DataEngineConsumer provides access to DataEngines, which are internally reference
|
||||
* counted and shared between all users of them. The only public method provided is
|
||||
* dataEngine which returns engines upon request.
|
||||
*
|
||||
* When the DataEngineConsumer class is deleted, all engines accessed using it are
|
||||
* de-referenced and possibly deleted (in the case that there are no other users of
|
||||
* the engine in question).
|
||||
*
|
||||
* DataEngineConsumer can be subclassed by other C++ classes to allow this simple
|
||||
* API to be used directly from these classes in a convenient manner.
|
||||
**/
|
||||
class PLASMA_EXPORT DataEngineConsumer
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a DataEngineConsumer
|
||||
**/
|
||||
DataEngineConsumer();
|
||||
~DataEngineConsumer();
|
||||
|
||||
/**
|
||||
* Returns a Plasma::DataEngine. It never returns a null pointer, and the
|
||||
* DataEngine returned should not be deleted. All DataEngines will be dereferenced
|
||||
* once this DataEngineConsumer instance is deleted.
|
||||
*
|
||||
* It is safe and fast to request the same engine more than once.
|
||||
*
|
||||
* @param name the name of the DataEngine. This corresponds to the plugin name
|
||||
* of the DataEngine.
|
||||
* @param location if a non-empty URI is passed in, then a connection with a
|
||||
* remote DataEngine at the location is attempted to be made.
|
||||
* The returned pointer is a proxy object for this connection.
|
||||
* In the common case, location is always an empty URI (QUrl())
|
||||
* and the DataEngine is loaded locally.
|
||||
*/
|
||||
DataEngine *dataEngine(const QString &name, const QUrl &location = QUrl());
|
||||
|
||||
private:
|
||||
DataEngineConsumerPrivate * const d;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
||||
|
43
plasma/design/qml_todos.txt
Normal file
43
plasma/design/qml_todos.txt
Normal file
@ -0,0 +1,43 @@
|
||||
Implementation Items
|
||||
====================
|
||||
* Applet::screenRect
|
||||
|
||||
Functionality Blocks
|
||||
====================
|
||||
* QML Wallpaper
|
||||
* QML Containment
|
||||
* port Sebas' work for QML Containment to libplasma2
|
||||
* wallpaper loading
|
||||
* action plugins access
|
||||
* applet geometry save/restore
|
||||
* move ContainmentPrivate::dropData to be a protected member (slot?) so QML Containment can
|
||||
provide a drop action
|
||||
* ContainmentActions
|
||||
* add ToolBox as a recognized trigger
|
||||
* only return sets of actions
|
||||
* PopupApplet -> merge into Applet with functionality implemented in QML rather than in libplasma
|
||||
* QML Tooltips
|
||||
* ToolTipManager -> replace with a QML component
|
||||
* QML tips
|
||||
* View -> dump
|
||||
* Default Package classes
|
||||
* Can this be provided by the graphics system specialization?
|
||||
* make (all?) plugins able to only be available from specific workspaces
|
||||
* does this mean simply implementing pluginLoaders for the shells?
|
||||
* better yet -> add shell-specific constraints for PluginLoader to use
|
||||
* OR not exists [X-Plasma-<something>] or [X-Plasma-<something>] = 'foo'
|
||||
|
||||
Porting of Applet and Containment
|
||||
=================================
|
||||
|
||||
* ContainmentPrivate::appletAt(const QPointF &point) -> depends from ContainmentActions refactoring : disabled now in the code
|
||||
* ContainmentPrivate::setScreen(int newScreen, int newDesktop, bool preventInvalidDesktops)
|
||||
* all geometry functions in Applet and Containment (width, height, geometry, raise, lower...)
|
||||
* move Containment::addAssociatedWidget/removeAssociatedWidget in the c++ part of the QML implementation
|
||||
|
||||
Porting of Wallpaper
|
||||
====================
|
||||
* port complete dropData/mimeTypeRetrieved from ContainmentPrivate to the c++ part of the Containment implementation. The code is right now in intoDeclarativeEngine/declarativecontainment_p.cpp
|
||||
* Containments should just have a string property for wallpapers that is the name of a Package with the wallpaper qml
|
||||
* the qml wallpaper must receive a signal when Containment::save() is called so it can do own config save (TODO around line 329 of containment.cpp)
|
||||
* redo WallpaperPackage, but this time is a package to load qml
|
1096
plasma/framesvg.cpp
Normal file
1096
plasma/framesvg.cpp
Normal file
File diff suppressed because it is too large
Load Diff
279
plasma/framesvg.h
Normal file
279
plasma/framesvg.h
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Copyright 2008 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* 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 PLASMA_FRAMESVG_H
|
||||
#define PLASMA_FRAMESVG_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QPixmap>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/svg.h>
|
||||
|
||||
class QPainter;
|
||||
class QPoint;
|
||||
class QPointF;
|
||||
class QRect;
|
||||
class QRectF;
|
||||
class QSize;
|
||||
class QSizeF;
|
||||
class QMatrix;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class FrameSvgPrivate;
|
||||
|
||||
/**
|
||||
* @class FrameSvg plasma/framesvg.h <Plasma/FrameSvg>
|
||||
*
|
||||
* @short Provides an SVG with borders.
|
||||
*
|
||||
* When using SVG images for a background of an object that may change
|
||||
* its aspect ratio, such as a dialog, simply scaling a single image
|
||||
* may not be enough.
|
||||
*
|
||||
* FrameSvg allows SVGs to provide several elements for borders as well
|
||||
* as a central element, each of which are scaled individually. These
|
||||
* elements should be named
|
||||
*
|
||||
* - @c center - the central element, which will be scaled in both directions
|
||||
* - @c top - the top border; the height is fixed, but it will be scaled
|
||||
* horizontally to the same width as @c center
|
||||
* - @c bottom - the bottom border; scaled in the same way as @c top
|
||||
* - @c left - the left border; the width is fixed, but it will be scaled
|
||||
* vertically to the same height as @c center
|
||||
* - @c right - the right border; scaled in the same way as @c left
|
||||
* - @c topleft - fixed size; must be the same height as @c top and the same
|
||||
* width as @c left
|
||||
* - @c bottomleft, @c topright, @c bottomright - similar to @c topleft
|
||||
*
|
||||
* @c center must exist, but all the others are optional. @c topleft and
|
||||
* @c topright will be ignored if @c top does not exist, and similarly for
|
||||
* @c bottomleft and @c bottomright.
|
||||
*
|
||||
* @see Plasma::Svg
|
||||
**/
|
||||
class PLASMA_EXPORT FrameSvg : public Svg
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_FLAGS(EnabledBorders)
|
||||
Q_PROPERTY(EnabledBorders enabledBorders READ enabledBorders WRITE setEnabledBorders)
|
||||
|
||||
public:
|
||||
/**
|
||||
* These flags represents what borders should be drawn
|
||||
*/
|
||||
enum EnabledBorder {
|
||||
NoBorder = 0,
|
||||
TopBorder = 1,
|
||||
BottomBorder = 2,
|
||||
LeftBorder = 4,
|
||||
RightBorder = 8,
|
||||
AllBorders = TopBorder | BottomBorder | LeftBorder | RightBorder
|
||||
};
|
||||
Q_DECLARE_FLAGS(EnabledBorders, EnabledBorder)
|
||||
|
||||
/**
|
||||
* Constructs a new FrameSvg that paints the proper named subelements
|
||||
* as borders. It may also be used as a regular Plasma::Svg object
|
||||
* for direct access to elements in the Svg.
|
||||
*
|
||||
* @param parent options QObject to parent this to
|
||||
*
|
||||
* @related Plasma::Theme
|
||||
*/
|
||||
explicit FrameSvg(QObject *parent = 0);
|
||||
~FrameSvg();
|
||||
|
||||
/**
|
||||
* Loads a new Svg
|
||||
* @param imagePath the new file
|
||||
*/
|
||||
Q_INVOKABLE void setImagePath(const QString &path);
|
||||
|
||||
/**
|
||||
* Sets what borders should be painted
|
||||
* @param flags borders we want to paint
|
||||
*/
|
||||
void setEnabledBorders(const EnabledBorders borders);
|
||||
|
||||
/**
|
||||
* Convenience method to get the enabled borders
|
||||
* @return what borders are painted
|
||||
*/
|
||||
EnabledBorders enabledBorders() const;
|
||||
|
||||
/**
|
||||
* Resize the frame maintaining the same border size
|
||||
* @param size the new size of the frame
|
||||
*/
|
||||
Q_INVOKABLE void resizeFrame(const QSizeF &size);
|
||||
|
||||
/**
|
||||
* @returns the size of the frame
|
||||
*/
|
||||
Q_INVOKABLE QSizeF frameSize() const;
|
||||
|
||||
/**
|
||||
* Returns the margin size given the margin edge we want
|
||||
* @param edge the margin edge we want, top, bottom, left or right
|
||||
* @return the margin size
|
||||
*/
|
||||
Q_INVOKABLE qreal marginSize(const Plasma::MarginEdge edge) const;
|
||||
|
||||
/**
|
||||
* Convenience method that extracts the size of the four margins
|
||||
* in the four output parameters
|
||||
* @param left left margin size
|
||||
* @param top top margin size
|
||||
* @param right right margin size
|
||||
* @param bottom bottom margin size
|
||||
*/
|
||||
Q_INVOKABLE void getMargins(qreal &left, qreal &top, qreal &right, qreal &bottom) const;
|
||||
|
||||
/**
|
||||
* @return the rectangle of the center element, taking the margins into account.
|
||||
*/
|
||||
Q_INVOKABLE QRectF contentsRect() const;
|
||||
|
||||
/**
|
||||
* Sets the prefix (@see setElementPrefix) to 'north', 'south', 'west' and 'east'
|
||||
* when the location is TopEdge, BottomEdge, LeftEdge and RightEdge,
|
||||
* respectively. Clears the prefix in other cases.
|
||||
*
|
||||
* The prefix must exist in the SVG document, which means that this can only be
|
||||
* called successfully after setImagePath is called.
|
||||
* @param location location in the UI this frame will be drawn
|
||||
*/
|
||||
Q_INVOKABLE void setElementPrefix(Plasma::Location location);
|
||||
|
||||
/**
|
||||
* Sets the prefix for the SVG elements to be used for painting. For example,
|
||||
* if prefix is 'active', then instead of using the 'top' element of the SVG
|
||||
* file to paint the top border, 'active-top' element will be used. The same
|
||||
* goes for other SVG elements.
|
||||
*
|
||||
* If the elements with prefixes are not present, the default ones are used.
|
||||
* (for the sake of speed, the test is present only for the 'center' element)
|
||||
*
|
||||
* Setting the prefix manually resets the location to Floating.
|
||||
*
|
||||
* The prefix must exist in the SVG document, which means that this can only be
|
||||
* called successfully after setImagePath is called.
|
||||
*
|
||||
* @param prefix prefix for the SVG elements that make up the frame
|
||||
*/
|
||||
Q_INVOKABLE void setElementPrefix(const QString & prefix);
|
||||
|
||||
/**
|
||||
* @return true if the svg has the necessary elements with the given prefix
|
||||
* to draw a frame
|
||||
* @param prefix the given prefix we want to check if drawable
|
||||
*/
|
||||
Q_INVOKABLE bool hasElementPrefix(const QString & prefix) const;
|
||||
|
||||
/**
|
||||
* This is an overloaded method provided for convenience equivalent to
|
||||
* hasElementPrefix("north"), hasElementPrefix("south")
|
||||
* hasElementPrefix("west") and hasElementPrefix("east")
|
||||
* @return true if the svg has the necessary elements with the given prefix
|
||||
* to draw a frame.
|
||||
* @param location the given prefix we want to check if drawable
|
||||
*/
|
||||
Q_INVOKABLE bool hasElementPrefix(Plasma::Location location) const;
|
||||
|
||||
/**
|
||||
* Returns the prefix for SVG elements of the FrameSvg
|
||||
* @return the prefix
|
||||
*/
|
||||
Q_INVOKABLE QString prefix();
|
||||
|
||||
/**
|
||||
* Returns a mask that tightly contains the fully opaque areas of the svg
|
||||
* @return a region of opaque areas
|
||||
*/
|
||||
Q_INVOKABLE QRegion mask() const;
|
||||
|
||||
/**
|
||||
* @return a pixmap whose alpha channel is the opacity of the frame. It may be the frame itself or a special frame with the mask- prefix
|
||||
*/
|
||||
QPixmap alphaMask() const;
|
||||
|
||||
/**
|
||||
* Sets whether saving all the rendered prefixes in a cache or not
|
||||
* @param cache if use the cache or not
|
||||
*/
|
||||
Q_INVOKABLE void setCacheAllRenderedFrames(bool cache);
|
||||
|
||||
/**
|
||||
* @return if all the different prefixes should be kept in a cache when rendered
|
||||
*/
|
||||
Q_INVOKABLE bool cacheAllRenderedFrames() const;
|
||||
|
||||
/**
|
||||
* Deletes the internal cache freeing memory: use this if you want to switch the rendered
|
||||
* element and you don't plan to switch back to the previous one for a long time and you
|
||||
* used setUsingRenderingCache(true)
|
||||
*/
|
||||
Q_INVOKABLE void clearCache();
|
||||
|
||||
/**
|
||||
* Returns a pixmap of the SVG represented by this object.
|
||||
*
|
||||
* @param elelementId the ID string of the element to render, or an empty
|
||||
* string for the whole SVG (the default)
|
||||
* @return a QPixmap of the rendered SVG
|
||||
*/
|
||||
Q_INVOKABLE QPixmap framePixmap();
|
||||
|
||||
/**
|
||||
* Paints the loaded SVG with the elements that represents the border
|
||||
* @param painter the QPainter to use
|
||||
* @param target the target rectangle on the paint device
|
||||
* @param source the portion rectangle of the source image
|
||||
*/
|
||||
Q_INVOKABLE void paintFrame(QPainter *painter, const QRectF &target,
|
||||
const QRectF &source = QRectF());
|
||||
|
||||
/**
|
||||
* Paints the loaded SVG with the elements that represents the border
|
||||
* This is an overloaded member provided for convenience
|
||||
* @param painter the QPainter to use
|
||||
* @param pos where to paint the svg
|
||||
*/
|
||||
Q_INVOKABLE void paintFrame(QPainter *painter, const QPointF &pos = QPointF(0, 0));
|
||||
|
||||
private:
|
||||
FrameSvgPrivate *const d;
|
||||
friend class Applet;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void updateSizes())
|
||||
Q_PRIVATE_SLOT(d, void updateNeeded())
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::FrameSvg::EnabledBorders)
|
||||
|
||||
#endif // multiple inclusion guard
|
53
plasma/intoDeclarativeEngine/declarativecontainment.cpp
Normal file
53
plasma/intoDeclarativeEngine/declarativecontainment.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
* Copyright 2009 Chani Armitage <chani@kde.org>
|
||||
* Copyright 2012 Marco Martin <notmart@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 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.
|
||||
*/
|
||||
|
||||
|
||||
void Containment::focusNextApplet()
|
||||
{
|
||||
if (d->applets.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) + 1 : 0;
|
||||
if (index >= d->applets.size()) {
|
||||
index = 0;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "index" << index;
|
||||
#endif
|
||||
d->focusApplet(d->applets.at(index));
|
||||
}
|
||||
|
||||
void Containment::focusPreviousApplet()
|
||||
{
|
||||
if (d->applets.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) - 1 : -1;
|
||||
if (index < 0) {
|
||||
index = d->applets.size() - 1;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "index" << index;
|
||||
#endif
|
||||
d->focusApplet(d->applets.at(index));
|
||||
}
|
||||
|
74
plasma/intoDeclarativeEngine/declarativecontainment.h
Normal file
74
plasma/intoDeclarativeEngine/declarativecontainment.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 PLASMA_CONTAINMENT_H
|
||||
#define PLASMA_CONTAINMENT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
#include <ksharedconfig.h>
|
||||
|
||||
#include <plasma/applet.h>
|
||||
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AccessAppletJob;
|
||||
class AppletHandle;
|
||||
class DataEngine;
|
||||
class Package;
|
||||
class Corona;
|
||||
class View;
|
||||
class Wallpaper;
|
||||
class DeclarativeContainmentActions;
|
||||
class DeclarativeContainmentPrivate;
|
||||
class AbstractToolBox;
|
||||
|
||||
|
||||
class PLASMA_EXPORT DeclarativeContainment : public Applet
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
void focusNextApplet();
|
||||
void focusPreviousApplet();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
Q_PRIVATE_SLOT(d, void showDropZoneDelayed())
|
||||
Q_PRIVATE_SLOT(d, void remoteAppletReady(Plasma::AccessAppletJob *))
|
||||
/**
|
||||
* This slot is called when the 'stat' after a job event has finished.
|
||||
*/
|
||||
Q_PRIVATE_SLOT(d, void mimeTypeRetrieved(KIO::Job *, const QString &))
|
||||
Q_PRIVATE_SLOT(d, void dropJobResult(KJob *))
|
||||
|
||||
DeclarativeContainmentPrivate *const d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif // multiple inclusion guard
|
476
plasma/intoDeclarativeEngine/declarativecontainment_p.cpp
Normal file
476
plasma/intoDeclarativeEngine/declarativecontainment_p.cpp
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
* Copyright 2009 Chani Armitage <chani@kde.org>
|
||||
* Copyright 2012 Marco Martin <notmart@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 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 "private/containment_p.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QMimeData>
|
||||
#include <QMimeDatabase>
|
||||
#include <QDropEvent>
|
||||
#include <qtemporaryfile.h>
|
||||
|
||||
#include <kaction.h>
|
||||
#include <kactioncollection.h>
|
||||
#include <kcoreauthorized.h>
|
||||
#include <kurlmimedata.h>
|
||||
#include <kwindowsystem.h>
|
||||
|
||||
#include "config-plasma.h"
|
||||
|
||||
#if !PLASMA_NO_KIO
|
||||
#include "kio/jobclasses.h" // for KIO::JobFlags
|
||||
#include "kio/job.h"
|
||||
#include "kio/scheduler.h"
|
||||
#endif
|
||||
|
||||
#include "containmentactions.h"
|
||||
#include "containmentactionspluginsconfig.h"
|
||||
#include "corona.h"
|
||||
#include "pluginloader.h"
|
||||
#include "svg.h"
|
||||
|
||||
#include "remote/accessappletjob.h"
|
||||
#include "remote/accessmanager.h"
|
||||
|
||||
#include "private/applet_p.h"
|
||||
#include "private/containmentactionspluginsconfig_p.h"
|
||||
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
|
||||
const char DeclarativeContainmentPrivate::defaultWallpaperMode[] = "SingleImage";
|
||||
|
||||
|
||||
void DeclarativeContainmentPrivate::showDropZoneDelayed()
|
||||
{
|
||||
dropZoneStarted = true;
|
||||
q->showDropZone(dropPoints.value(0).toPoint());
|
||||
dropPoints.remove(0);
|
||||
}
|
||||
|
||||
void DeclarativeContainmentPrivate::dropData(QPoint screenPos, QDropEvent *dropEvent)
|
||||
{
|
||||
if (q->immutability() != Mutable) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QMimeData *mimeData = 0;
|
||||
|
||||
if (dropEvent) {
|
||||
mimeData = dropEvent->mimeData();
|
||||
} else {
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
mimeData = clipboard->mimeData(QClipboard::Selection);
|
||||
//TODO if that's not supported (ie non-linux) should we try clipboard instead of selection?
|
||||
}
|
||||
|
||||
if (!mimeData) {
|
||||
//Selection is either empty or not supported on this OS
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "no mime data";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
//kDebug() << event->mimeData()->text();
|
||||
|
||||
QString appletMimetype(q->corona() ? q->corona()->appletMimeType() : QString());
|
||||
|
||||
if (!appletMimetype.isEmpty() && mimeData->hasFormat(appletMimetype)) {
|
||||
QString data = mimeData->data(appletMimetype);
|
||||
const QStringList appletNames = data.split('\n', QString::SkipEmptyParts);
|
||||
foreach (const QString &appletName, appletNames) {
|
||||
//kDebug() << "doing" << appletName;
|
||||
QRectF geom(screenPos, QSize(0, 0));
|
||||
q->addApplet(appletName, QVariantList(), geom);
|
||||
}
|
||||
if (dropEvent) {
|
||||
dropEvent->acceptProposedAction();
|
||||
}
|
||||
} else if (mimeData->hasUrls()) {
|
||||
//TODO: collect the mimeTypes of available script engines and offer
|
||||
// to create widgets out of the matching URLs, if any
|
||||
const QList<QUrl> urls = KUrlMimeData::urlsFromMimeData(mimeData);
|
||||
foreach (const QUrl &url, urls) {
|
||||
if (AccessManager::supportedProtocols().contains(url.scheme())) {
|
||||
AccessAppletJob *job = AccessManager::self()->accessRemoteApplet(url);
|
||||
if (dropEvent) {
|
||||
dropPoints[job] = dropEvent->pos();
|
||||
} else {
|
||||
dropPoints[job] = screenPos;
|
||||
}
|
||||
QObject::connect(AccessManager::self(), SIGNAL(finished(Plasma::AccessAppletJob*)),
|
||||
q, SLOT(remoteAppletReady(Plasma::AccessAppletJob*)));
|
||||
}
|
||||
#if !PLASMA_NO_KIO
|
||||
else {
|
||||
QMimeDatabase db;
|
||||
QMimeType mime = db.mimeTypeForUrl(url);
|
||||
QString mimeName = mime.name();
|
||||
QRectF geom(screenPos, QSize());
|
||||
QVariantList args;
|
||||
args << url.toString();
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "can decode" << mimeName << args;
|
||||
#endif
|
||||
|
||||
// It may be a directory or a file, let's stat
|
||||
KIO::JobFlags flags = KIO::HideProgressInfo;
|
||||
KIO::MimetypeJob *job = KIO::mimetype(url, flags);
|
||||
if (dropEvent) {
|
||||
dropPoints[job] = dropEvent->pos();
|
||||
} else {
|
||||
dropPoints[job] = screenPos;
|
||||
}
|
||||
|
||||
QObject::connect(job, SIGNAL(result(KJob*)), q, SLOT(dropJobResult(KJob*)));
|
||||
QObject::connect(job, SIGNAL(mimetype(KIO::Job*,QString)),
|
||||
q, SLOT(mimeTypeRetrieved(KIO::Job*,QString)));
|
||||
|
||||
KMenu *choices = new KMenu("Content dropped");
|
||||
choices->addAction(KDE::icon("process-working"), i18n("Fetching file type..."));
|
||||
if (dropEvent) {
|
||||
choices->popup(dropEvent->pos());
|
||||
} else {
|
||||
choices->popup(screenPos);
|
||||
}
|
||||
|
||||
dropMenus[job] = choices;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dropEvent) {
|
||||
dropEvent->acceptProposedAction();
|
||||
}
|
||||
} else {
|
||||
QStringList formats = mimeData->formats();
|
||||
QHash<QString, KPluginInfo> seenPlugins;
|
||||
QHash<QString, QString> pluginFormats;
|
||||
|
||||
foreach (const QString &format, formats) {
|
||||
KPluginInfo::List plugins = Applet::listAppletInfoForMimeType(format);
|
||||
|
||||
foreach (const KPluginInfo &plugin, plugins) {
|
||||
if (seenPlugins.contains(plugin.pluginName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
seenPlugins.insert(plugin.pluginName(), plugin);
|
||||
pluginFormats.insert(plugin.pluginName(), format);
|
||||
}
|
||||
}
|
||||
//kDebug() << "Mimetype ..." << formats << seenPlugins.keys() << pluginFormats.values();
|
||||
|
||||
QString selectedPlugin;
|
||||
|
||||
if (seenPlugins.isEmpty()) {
|
||||
// do nothing
|
||||
} else if (seenPlugins.count() == 1) {
|
||||
selectedPlugin = seenPlugins.constBegin().key();
|
||||
} else {
|
||||
KMenu choices;
|
||||
QHash<QAction *, QString> actionsToPlugins;
|
||||
foreach (const KPluginInfo &info, seenPlugins) {
|
||||
QAction *action;
|
||||
if (!info.icon().isEmpty()) {
|
||||
action = choices.addAction(KDE::icon(info.icon()), info.name());
|
||||
} else {
|
||||
action = choices.addAction(info.name());
|
||||
}
|
||||
|
||||
actionsToPlugins.insert(action, info.pluginName());
|
||||
}
|
||||
|
||||
QAction *choice = choices.exec(screenPos);
|
||||
if (choice) {
|
||||
selectedPlugin = actionsToPlugins[choice];
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedPlugin.isEmpty()) {
|
||||
if (!dropEvent) {
|
||||
// since we may have entered an event loop up above with the menu,
|
||||
// the clipboard item may no longer be valid, as QClipboard resets
|
||||
// the object behind the back of the application with a zero timer
|
||||
// so we fetch it again here
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
mimeData = clipboard->mimeData(QClipboard::Selection);
|
||||
}
|
||||
|
||||
QTemporaryFile tempFile;
|
||||
if (mimeData && tempFile.open()) {
|
||||
//TODO: what should we do with files after the applet is done with them??
|
||||
tempFile.setAutoRemove(false);
|
||||
|
||||
{
|
||||
QDataStream stream(&tempFile);
|
||||
QByteArray data = mimeData->data(pluginFormats[selectedPlugin]);
|
||||
stream.writeRawData(data, data.size());
|
||||
}
|
||||
|
||||
QRectF geom(screenPos, QSize());
|
||||
QVariantList args;
|
||||
args << tempFile.fileName();
|
||||
#ifndef NDEBUG
|
||||
kDebug() << args;
|
||||
#endif
|
||||
tempFile.close();
|
||||
|
||||
q->addApplet(selectedPlugin, args, geom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarativeContainmentPrivate::clearDataForMimeJob(KIO::Job *job)
|
||||
{
|
||||
#if !PLASMA_NO_KIO
|
||||
QObject::disconnect(job, 0, q, 0);
|
||||
dropPoints.remove(job);
|
||||
KMenu *choices = dropMenus.take(job);
|
||||
delete choices;
|
||||
job->kill();
|
||||
#endif // PLASMA_NO_KIO
|
||||
}
|
||||
|
||||
void DeclarativeContainmentPrivate::dropJobResult(KJob *job)
|
||||
{
|
||||
#if !PLASMA_NO_KIO
|
||||
KIO::TransferJob* tjob = dynamic_cast<KIO::TransferJob*>(job);
|
||||
if (!tjob) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "job is not a KIO::TransferJob, won't handle the drop...";
|
||||
#endif
|
||||
clearDataForMimeJob(tjob);
|
||||
return;
|
||||
}
|
||||
if (job->error()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "ERROR" << tjob->error() << ' ' << tjob->errorString();
|
||||
#endif
|
||||
}
|
||||
// We call mimeTypeRetrieved since there might be other mechanisms
|
||||
// for finding suitable applets. Cleanup happens there as well.
|
||||
mimeTypeRetrieved(qobject_cast<KIO::Job *>(job), QString());
|
||||
#endif // PLASMA_NO_KIO
|
||||
}
|
||||
|
||||
void DeclarativeContainmentPrivate::mimeTypeRetrieved(KIO::Job *job, const QString &mimeType)
|
||||
{
|
||||
#if !PLASMA_NO_KIO
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Mimetype Job returns." << mimeType;
|
||||
#endif
|
||||
KIO::TransferJob* tjob = dynamic_cast<KIO::TransferJob*>(job);
|
||||
if (!tjob) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "job should be a TransferJob, but isn't";
|
||||
#endif
|
||||
clearDataForMimeJob(job);
|
||||
return;
|
||||
}
|
||||
KPluginInfo::List appletList = Applet::listAppletInfoForUrl(tjob->url());
|
||||
if (mimeType.isEmpty() && !appletList.count()) {
|
||||
clearDataForMimeJob(job);
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "No applets found matching the url (" << tjob->url() << ") or the mimeType (" << mimeType << ")";
|
||||
#endif
|
||||
return;
|
||||
} else {
|
||||
|
||||
QPointF posi; // will be overwritten with the event's position
|
||||
if (dropPoints.keys().contains(tjob)) {
|
||||
posi = dropPoints[tjob];
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Received a suitable dropEvent at" << posi;
|
||||
#endif
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Bailing out. Cannot find associated dropEvent related to the TransferJob";
|
||||
#endif
|
||||
clearDataForMimeJob(job);
|
||||
return;
|
||||
}
|
||||
|
||||
KMenu *choices = dropMenus.value(tjob);
|
||||
if (!choices) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Bailing out. No QMenu found for this job.";
|
||||
#endif
|
||||
clearDataForMimeJob(job);
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantList args;
|
||||
args << tjob->url().toString() << mimeType;
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Creating menu for:" << mimeType << posi << args;
|
||||
#endif
|
||||
|
||||
appletList << Applet::listAppletInfoForMimeType(mimeType);
|
||||
KPluginInfo::List wallpaperList;
|
||||
if (drawWallpaper) {
|
||||
if (wallpaper && wallpaper->supportsMimetype(mimeType)) {
|
||||
wallpaperList << wallpaper->d->wallpaperDescription;
|
||||
} else {
|
||||
wallpaperList = Wallpaper::listWallpaperInfoForMimeType(mimeType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!appletList.isEmpty() || !wallpaperList.isEmpty()) {
|
||||
choices->clear();
|
||||
QHash<QAction *, QString> actionsToApplets;
|
||||
choices->addTitle(i18n("Widgets"));
|
||||
foreach (const KPluginInfo &info, appletList) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << info.name();
|
||||
#endif
|
||||
QAction *action;
|
||||
if (!info.icon().isEmpty()) {
|
||||
action = choices->addAction(KDE::icon(info.icon()), info.name());
|
||||
} else {
|
||||
action = choices->addAction(info.name());
|
||||
}
|
||||
|
||||
actionsToApplets.insert(action, info.pluginName());
|
||||
#ifndef NDEBUG
|
||||
kDebug() << info.pluginName();
|
||||
#endif
|
||||
}
|
||||
actionsToApplets.insert(choices->addAction(i18n("Icon")), "icon");
|
||||
|
||||
QHash<QAction *, QString> actionsToWallpapers;
|
||||
if (!wallpaperList.isEmpty()) {
|
||||
choices->addTitle(i18n("Wallpaper"));
|
||||
|
||||
QMap<QString, KPluginInfo> sorted;
|
||||
foreach (const KPluginInfo &info, appletList) {
|
||||
sorted.insert(info.name(), info);
|
||||
}
|
||||
|
||||
foreach (const KPluginInfo &info, wallpaperList) {
|
||||
QAction *action;
|
||||
if (!info.icon().isEmpty()) {
|
||||
action = choices->addAction(KDE::icon(info.icon()), info.name());
|
||||
} else {
|
||||
action = choices->addAction(info.name());
|
||||
}
|
||||
|
||||
actionsToWallpapers.insert(action, info.pluginName());
|
||||
}
|
||||
}
|
||||
|
||||
QAction *choice = choices->exec();
|
||||
if (choice) {
|
||||
// Put the job on hold so it can be recycled to fetch the actual content,
|
||||
// which is to be expected when something's dropped onto the desktop and
|
||||
// an applet is to be created with this URL
|
||||
if (!mimeType.isEmpty() && !tjob->error()) {
|
||||
tjob->putOnHold();
|
||||
KIO::Scheduler::publishSlaveOnHold();
|
||||
}
|
||||
QString plugin = actionsToApplets.value(choice);
|
||||
if (plugin.isEmpty()) {
|
||||
//set wallpapery stuff
|
||||
plugin = actionsToWallpapers.value(choice);
|
||||
if (!wallpaper || plugin != wallpaper->pluginName()) {
|
||||
//kDebug() << "Wallpaper dropped:" << tjob->url();
|
||||
q->setWallpaper(plugin);
|
||||
}
|
||||
|
||||
if (wallpaper) {
|
||||
//kDebug() << "Wallpaper dropped:" << tjob->url();
|
||||
wallpaper->addUrls(QList<QUrl>() << tjob->url());
|
||||
}
|
||||
} else {
|
||||
addApplet(actionsToApplets[choice], args, QRectF(posi, QSize()));
|
||||
}
|
||||
|
||||
clearDataForMimeJob(job);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// we can at least create an icon as a link to the URL
|
||||
addApplet("icon", args, QRectF(posi, QSize()));
|
||||
}
|
||||
}
|
||||
|
||||
clearDataForMimeJob(job);
|
||||
#endif // PLASMA_NO_KIO
|
||||
}
|
||||
|
||||
void DeclarativeContainmentPrivate::focusApplet(Plasma::Applet *applet)
|
||||
{
|
||||
if (focusedApplet == applet) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QWidget *> widgets = actions()->associatedWidgets();
|
||||
if (focusedApplet) {
|
||||
foreach (QWidget *w, widgets) {
|
||||
focusedApplet->removeAssociatedWidget(w);
|
||||
}
|
||||
}
|
||||
|
||||
if (applet && applets.contains(applet)) {
|
||||
//kDebug() << "switching to" << applet->name();
|
||||
focusedApplet = applet;
|
||||
foreach (QWidget *w, widgets) {
|
||||
focusedApplet->addAssociatedWidget(w);
|
||||
}
|
||||
|
||||
if (!focusedApplet->hasFocus()) {
|
||||
focusedApplet->setFocus(Qt::ShortcutFocusReason);
|
||||
}
|
||||
} else {
|
||||
focusedApplet = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarativeContainmentPrivate::remoteAppletReady(Plasma::AccessAppletJob *job)
|
||||
{
|
||||
QPointF pos = dropPoints.take(job);
|
||||
if (job->error()) {
|
||||
//TODO: nice user visible error handling (knotification probably?)
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "remote applet access failed: " << job->errorText();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (!job->applet()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "how did we end up here? if applet is null, the job->error should be nonzero";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
q->addApplet(job->applet(), pos);
|
||||
}
|
||||
|
||||
|
||||
}
|
102
plasma/intoDeclarativeEngine/declarativecontainment_p.h
Normal file
102
plasma/intoDeclarativeEngine/declarativecontainment_p.h
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
* Copyright 2012 by 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 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 DECLARATIVECONTAINMENT_P_H
|
||||
#define DECLARATIVECONTAINMENT_P_H
|
||||
|
||||
#include <kactioncollection.h>
|
||||
#include <kmenu.h>
|
||||
|
||||
#include "plasma.h"
|
||||
#include "applet.h"
|
||||
#include "corona.h"
|
||||
|
||||
|
||||
class KJob;
|
||||
|
||||
namespace KIO
|
||||
{
|
||||
class Job;
|
||||
}
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AccessAppletJob;
|
||||
class Containment;
|
||||
|
||||
class DeclarativeContainmentPrivate
|
||||
{
|
||||
public:
|
||||
DeclarativeContainmentPrivate(Containment *c)
|
||||
: q(c),
|
||||
focusedApplet(0),
|
||||
wallpaper(0),
|
||||
showDropZoneDelayTimer(0),
|
||||
dropZoneStarted(false),
|
||||
{
|
||||
}
|
||||
|
||||
~DeclarativeContainmentPrivate()
|
||||
{
|
||||
qDeleteAll(dropMenus);
|
||||
dropMenus.clear();
|
||||
}
|
||||
|
||||
|
||||
void clearDataForMimeJob(KIO::Job *job);
|
||||
void mimeTypeRetrieved(KIO::Job *job, const QString &mimetype);
|
||||
void dropJobResult(KJob *);
|
||||
void remoteAppletReady(Plasma::AccessAppletJob *job);
|
||||
|
||||
|
||||
/**
|
||||
* give keyboard focus to applet within this containment
|
||||
*/
|
||||
void focusApplet(Plasma::Applet *applet);
|
||||
|
||||
/**
|
||||
* Handles dropped/pasted mimetype data
|
||||
* @param screenPos screen-relative position
|
||||
* @param dropEvent the drop event (if null, the clipboard is used instead)
|
||||
*/
|
||||
void dropData(QPoint screenPos, QDropEvent *dropEvent = 0);
|
||||
|
||||
/**
|
||||
* Delayed drop zone display
|
||||
*/
|
||||
void showDropZoneDelayed();
|
||||
|
||||
DeclarativeContainment *q;
|
||||
Applet *focusedApplet;
|
||||
Plasma::Wallpaper *wallpaper;
|
||||
QHash<KJob*, QPointF> dropPoints;
|
||||
QHash<KJob*, KMenu*> dropMenus;
|
||||
QTimer *showDropZoneDelayTimer;
|
||||
bool dropZoneStarted : 1;
|
||||
|
||||
static const char defaultWallpaper[];
|
||||
static const char defaultWallpaperMode[];
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif
|
335
plasma/intoDeclarativeEngine/declarativewidget.cpp
Normal file
335
plasma/intoDeclarativeEngine/declarativewidget.cpp
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright 2010 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 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 "declarativewidget.h"
|
||||
|
||||
|
||||
#include <QDeclarativeComponent>
|
||||
#include <QDeclarativeItem>
|
||||
#include <QDeclarativeEngine>
|
||||
#include <QDeclarativeContext>
|
||||
#include <QScriptEngine>
|
||||
#include <QGraphicsLinearLayout>
|
||||
#include <QGraphicsScene>
|
||||
#include <QTimer>
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <kdeclarative.h>
|
||||
|
||||
|
||||
#include "private/declarative/declarativenetworkaccessmanagerfactory_p.h"
|
||||
#include "private/declarative/dataenginebindings_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DeclarativeWidgetPrivate
|
||||
{
|
||||
public:
|
||||
DeclarativeWidgetPrivate(DeclarativeWidget *parent)
|
||||
: q(parent),
|
||||
engine(0),
|
||||
scriptEngine(0),
|
||||
component(0),
|
||||
root(0),
|
||||
delay(false)
|
||||
{
|
||||
}
|
||||
|
||||
~DeclarativeWidgetPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
void errorPrint();
|
||||
void execute(const QString &fileName);
|
||||
void finishExecute();
|
||||
void scheduleExecutionEnd();
|
||||
void minimumWidthChanged();
|
||||
void minimumHeightChanged();
|
||||
void maximumWidthChanged();
|
||||
void maximumHeightChanged();
|
||||
void preferredWidthChanged();
|
||||
void preferredHeightChanged();
|
||||
|
||||
|
||||
DeclarativeWidget *q;
|
||||
|
||||
QString qmlPath;
|
||||
QDeclarativeEngine* engine;
|
||||
QScriptEngine *scriptEngine;
|
||||
QDeclarativeComponent* component;
|
||||
QObject *root;
|
||||
bool delay : 1;
|
||||
};
|
||||
|
||||
void DeclarativeWidgetPrivate::errorPrint()
|
||||
{
|
||||
QString errorStr = "Error loading QML file.\n";
|
||||
if(component->isError()){
|
||||
QList<QDeclarativeError> errors = component->errors();
|
||||
foreach (const QDeclarativeError &error, errors) {
|
||||
errorStr += (error.line()>0?QString(QString::number(error.line()) + QLatin1String(": ")):QLatin1String(""))
|
||||
+ error.description() + '\n';
|
||||
}
|
||||
}
|
||||
kWarning() << component->url().toString() + '\n' + errorStr;
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::execute(const QString &fileName)
|
||||
{
|
||||
if (fileName.isEmpty()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "File name empty!";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
KDeclarative kdeclarative;
|
||||
kdeclarative.setDeclarativeEngine(engine);
|
||||
kdeclarative.initialize();
|
||||
//binds things like kconfig and icons
|
||||
kdeclarative.setupBindings();
|
||||
|
||||
component->loadUrl(QUrl::fromLocalFile(fileName));
|
||||
|
||||
scriptEngine = kdeclarative.scriptEngine();
|
||||
registerDataEngineMetaTypes(scriptEngine);
|
||||
|
||||
if (delay) {
|
||||
QTimer::singleShot(0, q, SLOT(scheduleExecutionEnd()));
|
||||
} else {
|
||||
scheduleExecutionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::scheduleExecutionEnd()
|
||||
{
|
||||
if (component->isReady() || component->isError()) {
|
||||
finishExecute();
|
||||
} else {
|
||||
QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), q, SLOT(finishExecute()));
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::finishExecute()
|
||||
{
|
||||
if (component->isError()) {
|
||||
errorPrint();
|
||||
}
|
||||
|
||||
root = component->create();
|
||||
|
||||
if (!root) {
|
||||
errorPrint();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Execution of QML done!";
|
||||
#endif
|
||||
QGraphicsWidget *widget = dynamic_cast<QGraphicsWidget*>(root);
|
||||
QGraphicsObject *object = dynamic_cast<QGraphicsObject *>(root);
|
||||
|
||||
|
||||
if (object) {
|
||||
static_cast<QGraphicsItem *>(object)->setParentItem(q);
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
q->setPreferredSize(-1,-1);
|
||||
QGraphicsLinearLayout *lay = static_cast<QGraphicsLinearLayout *>(q->layout());
|
||||
if (!lay) {
|
||||
lay = new QGraphicsLinearLayout(q);
|
||||
lay->setContentsMargins(0, 0, 0, 0);
|
||||
}
|
||||
lay->addItem(widget);
|
||||
} else {
|
||||
q->setLayout(0);
|
||||
qreal minimumWidth = 0;
|
||||
qreal minimumHeight = 0;
|
||||
qreal maximumWidth = 0;
|
||||
qreal maximumHeight = 0;
|
||||
qreal preferredWidth = 0;
|
||||
qreal preferredHeight = 0;
|
||||
if (object) {
|
||||
object->setProperty("width", q->size().width());
|
||||
object->setProperty("height", q->size().height());
|
||||
|
||||
if (object->metaObject()->indexOfProperty("minimumWidth")>=0) {
|
||||
minimumWidth = object->property("minimumWidth").toReal();
|
||||
QObject::connect(object, SIGNAL(minimumWidthChanged()), q, SLOT(minimumWidthChanged()));
|
||||
}
|
||||
if (object->metaObject()->indexOfProperty("minimumHeight")>=0) {
|
||||
minimumHeight = object->property("minimumHeight").toReal();
|
||||
QObject::connect(object, SIGNAL(minimumHeightChanged()), q, SLOT(minimumHeightChanged()));
|
||||
}
|
||||
|
||||
if (object->metaObject()->indexOfProperty("maximumWidth")>=0) {
|
||||
maximumWidth = object->property("maximumWidth").toReal();
|
||||
QObject::connect(object, SIGNAL(maximumWidthChanged()), q, SLOT(maximumWidthChanged()));
|
||||
}
|
||||
if (object->metaObject()->indexOfProperty("maximumHeight")>=0) {
|
||||
maximumHeight = object->property("maximumHeight").toReal();
|
||||
QObject::connect(object, SIGNAL(maximumHeightChanged()), q, SLOT(maximumHeightChanged()));
|
||||
}
|
||||
|
||||
if (object->metaObject()->indexOfProperty("preferredWidth")>=0) {
|
||||
preferredWidth = object->property("preferredWidth").toReal();
|
||||
QObject::connect(object, SIGNAL(preferredWidthChanged()), q, SLOT(preferredWidthChanged()));
|
||||
}
|
||||
if (object->metaObject()->indexOfProperty("preferredHeight")>=0) {
|
||||
preferredHeight = object->property("preferredHeight").toReal();
|
||||
QObject::connect(object, SIGNAL(preferredHeightChanged()), q, SLOT(preferredHeightChanged()));
|
||||
}
|
||||
}
|
||||
|
||||
if (minimumWidth > 0 && minimumHeight > 0) {
|
||||
q->setMinimumSize(minimumWidth, minimumHeight);
|
||||
} else {
|
||||
q->setMinimumSize(-1, -1);
|
||||
}
|
||||
|
||||
if (maximumWidth > 0 && maximumHeight > 0) {
|
||||
q->setMaximumSize(maximumWidth, maximumHeight);
|
||||
} else {
|
||||
q->setMaximumSize(-1, -1);
|
||||
}
|
||||
|
||||
if (preferredWidth > 0 && preferredHeight > 0) {
|
||||
q->setPreferredSize(preferredWidth, preferredHeight);
|
||||
} else {
|
||||
q->setPreferredSize(-1, -1);
|
||||
}
|
||||
}
|
||||
emit q->finished();
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::minimumWidthChanged()
|
||||
{
|
||||
qreal minimumWidth = root->property("minimumWidth").toReal();
|
||||
q->setMinimumWidth(minimumWidth);
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::minimumHeightChanged()
|
||||
{
|
||||
qreal minimumHeight = root->property("minimumHeight").toReal();
|
||||
q->setMinimumHeight(minimumHeight);
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::maximumWidthChanged()
|
||||
{
|
||||
qreal maximumWidth = root->property("maximumWidth").toReal();
|
||||
q->setMaximumWidth(maximumWidth);
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::maximumHeightChanged()
|
||||
{
|
||||
qreal maximumHeight = root->property("maximumHeight").toReal();
|
||||
q->setMaximumHeight(maximumHeight);
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::preferredWidthChanged()
|
||||
{
|
||||
qreal preferredWidth = root->property("preferredWidth").toReal();
|
||||
q->setPreferredWidth(preferredWidth);
|
||||
}
|
||||
|
||||
void DeclarativeWidgetPrivate::preferredHeightChanged()
|
||||
{
|
||||
qreal preferredHeight = root->property("preferredHeight").toReal();
|
||||
q->setPreferredHeight(preferredHeight);
|
||||
}
|
||||
|
||||
DeclarativeWidget::DeclarativeWidget(QGraphicsWidget *parent)
|
||||
: QGraphicsWidget(parent),
|
||||
d(new DeclarativeWidgetPrivate(this))
|
||||
{
|
||||
setFlag(QGraphicsItem::ItemHasNoContents);
|
||||
|
||||
d->engine = new QDeclarativeEngine(this);
|
||||
d->engine->setNetworkAccessManagerFactory(new DeclarativeNetworkAccessManagerFactory);
|
||||
|
||||
d->component = new QDeclarativeComponent(d->engine, this);
|
||||
}
|
||||
|
||||
DeclarativeWidget::~DeclarativeWidget()
|
||||
{
|
||||
QDeclarativeNetworkAccessManagerFactory *factory = d->engine->networkAccessManagerFactory();
|
||||
d->engine->setNetworkAccessManagerFactory(0);
|
||||
delete factory;
|
||||
delete d;
|
||||
}
|
||||
|
||||
void DeclarativeWidget::setQmlPath(const QString &path)
|
||||
{
|
||||
d->qmlPath = path;
|
||||
d->execute(path);
|
||||
}
|
||||
|
||||
QString DeclarativeWidget::qmlPath() const
|
||||
{
|
||||
return d->qmlPath;
|
||||
}
|
||||
|
||||
void DeclarativeWidget::setInitializationDelayed(const bool delay)
|
||||
{
|
||||
d->delay = delay;
|
||||
}
|
||||
|
||||
bool DeclarativeWidget::isInitializationDelayed() const
|
||||
{
|
||||
return d->delay;
|
||||
}
|
||||
|
||||
QDeclarativeEngine* DeclarativeWidget::engine()
|
||||
{
|
||||
return d->engine;
|
||||
}
|
||||
|
||||
QScriptEngine *DeclarativeWidget::scriptEngine() const
|
||||
{
|
||||
return d->scriptEngine;
|
||||
}
|
||||
|
||||
QObject *DeclarativeWidget::rootObject() const
|
||||
{
|
||||
return d->root;
|
||||
}
|
||||
|
||||
QDeclarativeComponent *DeclarativeWidget::mainComponent() const
|
||||
{
|
||||
return d->component;
|
||||
}
|
||||
|
||||
void DeclarativeWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
|
||||
{
|
||||
QGraphicsWidget::resizeEvent(event);
|
||||
|
||||
if (d->root) {
|
||||
d->root->setProperty("width", size().width());
|
||||
d->root->setProperty("height", size().height());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
|
||||
|
||||
|
||||
#include "moc_declarativewidget.cpp"
|
142
plasma/intoDeclarativeEngine/declarativewidget.h
Normal file
142
plasma/intoDeclarativeEngine/declarativewidget.h
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2010 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 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 PLASMA_DECLARATIVEWIDGET_H
|
||||
#define PLASMA_DECLARATIVEWIDGET_H
|
||||
|
||||
#include <QGraphicsWidget>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
class QDeclarativeEngine;
|
||||
class QDeclarativeComponent;
|
||||
class QScriptEngine;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DeclarativeWidgetPrivate;
|
||||
|
||||
/**
|
||||
* @class DeclarativeWidget plasma/declarativewidget.h <Plasma/DeclarativeWidget>
|
||||
*
|
||||
* @author Marco Martin <mart@kde.org>
|
||||
*
|
||||
* @short A widget that contains an entire QML context, with its own declarative engine
|
||||
*
|
||||
* Plasma::DeclarativeWidget provides a class for conveniently use QML based
|
||||
* declarative user interfaces inside Plasma widgets.
|
||||
* To one DeclarativeWidget corresponds one QML file (that can eventually include others)
|
||||
* tere will be its own QDeclarativeEngine with a single root object,
|
||||
* described in the QML file.
|
||||
*/
|
||||
class PLASMA_EXPORT DeclarativeWidget : public QGraphicsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString qmlPath READ qmlPath WRITE setQmlPath)
|
||||
Q_PROPERTY(bool initializationDelayed READ isInitializationDelayed WRITE setInitializationDelayed)
|
||||
Q_PROPERTY(QObject * rootObject READ rootObject)
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a new DeclarativeWidget
|
||||
*
|
||||
* @param parent the parent of this widget
|
||||
*/
|
||||
explicit DeclarativeWidget(QGraphicsWidget *parent = 0);
|
||||
~DeclarativeWidget();
|
||||
|
||||
/**
|
||||
* Sets the path of the QML file to parse and execute
|
||||
*
|
||||
* @param path the absolute path of a QML file
|
||||
*/
|
||||
void setQmlPath(const QString &path);
|
||||
|
||||
/**
|
||||
* @return the absolute path of the current QML file
|
||||
*/
|
||||
QString qmlPath() const;
|
||||
|
||||
/**
|
||||
* Sets whether the execution of the QML file has to be delayed later in the event loop. It has to be called before setQmlPath().
|
||||
* In this case will be possible to assign new objects in the main engine context
|
||||
* before the main component gets initialized.
|
||||
* So it will be possible to access it immediately from the QML code.
|
||||
*
|
||||
* @param delay if true the initialization of the QML file will be delayed
|
||||
* at the end of the event loop
|
||||
*/
|
||||
void setInitializationDelayed(const bool delay);
|
||||
|
||||
/**
|
||||
* @return true if the initialization of the QML file will be delayed
|
||||
* at the end of the event loop
|
||||
*/
|
||||
bool isInitializationDelayed() const;
|
||||
|
||||
/**
|
||||
* @return the declarative engine that runs the qml file assigned to this widget.
|
||||
*/
|
||||
QDeclarativeEngine* engine();
|
||||
|
||||
/**
|
||||
* @return the script engine used by the declarative engine
|
||||
* @since 4.7
|
||||
*/
|
||||
QScriptEngine *scriptEngine() const;
|
||||
|
||||
/**
|
||||
* @return the root object of the declarative object tree
|
||||
*/
|
||||
QObject *rootObject() const;
|
||||
|
||||
/**
|
||||
* @return the main QDeclarativeComponent of the engine
|
||||
*/
|
||||
QDeclarativeComponent *mainComponent() const;
|
||||
|
||||
protected:
|
||||
void resizeEvent(QGraphicsSceneResizeEvent *event);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emitted when the parsing and execution of the QML file is terminated
|
||||
*/
|
||||
void finished();
|
||||
|
||||
private:
|
||||
friend class DeclarativeWidgetPrivate;
|
||||
DeclarativeWidgetPrivate * const d;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void finishExecute())
|
||||
Q_PRIVATE_SLOT(d, void scheduleExecutionEnd())
|
||||
Q_PRIVATE_SLOT(d, void minimumWidthChanged())
|
||||
Q_PRIVATE_SLOT(d, void minimumHeightChanged())
|
||||
Q_PRIVATE_SLOT(d, void maximumWidthChanged())
|
||||
Q_PRIVATE_SLOT(d, void maximumHeightChanged())
|
||||
Q_PRIVATE_SLOT(d, void preferredWidthChanged())
|
||||
Q_PRIVATE_SLOT(d, void preferredHeightChanged())
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif // multiple inclusion guard
|
777
plasma/package.cpp
Normal file
777
plasma/package.cpp
Normal file
@ -0,0 +1,777 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org> *
|
||||
* Copyright 2010 by Marco Martin <notmart@gmail.com> *
|
||||
* Copyright 2010 by Kevin Ottens <ervin@kde.org> *
|
||||
* Copyright 2009 by Rob Scheepmaker *
|
||||
* *
|
||||
* This library 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 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; see the file COPYING.LIB. If not, write to *
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
||||
* Boston, MA 02110-1301, USA. *
|
||||
*******************************************************************************/
|
||||
|
||||
#include "package.h"
|
||||
|
||||
#include <qtemporarydir.h>
|
||||
|
||||
#include <karchive.h>
|
||||
#include <kdebug.h>
|
||||
#include <kdesktopfile.h>
|
||||
#include <kservicetypetrader.h>
|
||||
#include <kstandarddirs.h>
|
||||
#include <ktar.h>
|
||||
#include <kzip.h>
|
||||
|
||||
#include "config-plasma.h"
|
||||
|
||||
#include <qstandardpaths.h>
|
||||
#include <qmimedatabase.h>
|
||||
|
||||
#include "packagestructure.h"
|
||||
#include "pluginloader.h"
|
||||
#include "private/package_p.h"
|
||||
#include "private/packages_p.h"
|
||||
#include "private/packagejob_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
Package::Package(PackageStructure *structure)
|
||||
: d(new PackagePrivate())
|
||||
{
|
||||
d->structure = structure;
|
||||
if (d->structure) {
|
||||
d->structure.data()->initPackage(this);
|
||||
}
|
||||
}
|
||||
|
||||
Package::Package(const Package &other)
|
||||
: d(other.d)
|
||||
{
|
||||
}
|
||||
|
||||
Package::~Package()
|
||||
{
|
||||
}
|
||||
|
||||
Package &Package::operator=(const Package &rhs)
|
||||
{
|
||||
if (&rhs != this) {
|
||||
d = rhs.d;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Package::isValid() const
|
||||
{
|
||||
if (!d->valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//search for the file in all prefixes and in all possible paths for each prefix
|
||||
//even if it's a big nested loop, usually there is one prefix and one location
|
||||
//so shouldn't cause too much disk access
|
||||
QHashIterator<QByteArray, ContentStructure> it(d->contents);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (!it.value().required) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool failed = true;
|
||||
foreach (const QString &path, it.value().paths) {
|
||||
foreach (const QString &prefix, d->contentsPrefixPaths) {
|
||||
if (QFile::exists(d->path + prefix + path)) {
|
||||
failed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!failed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
kWarning() << "Could not find required" << (it.value().directory ? "directory" : "file") << it.key();
|
||||
d->valid = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Package::name(const char *key) const
|
||||
{
|
||||
#ifndef PLASMA_NO_PACKAGE_EXTRADATA
|
||||
QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constFind(key);
|
||||
if (it == d->contents.constEnd()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return it.value().name;
|
||||
#else
|
||||
Q_UNUSED(key);
|
||||
return QString();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Package::isRequired(const char *key) const
|
||||
{
|
||||
QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constFind(key);
|
||||
if (it == d->contents.constEnd()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return it.value().required;
|
||||
}
|
||||
|
||||
QStringList Package::mimeTypes(const char *key) const
|
||||
{
|
||||
#ifndef PLASMA_NO_PACKAGE_EXTRADATA
|
||||
QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constFind(key);
|
||||
if (it == d->contents.constEnd()) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
if (it.value().mimeTypes.isEmpty()) {
|
||||
return d->mimeTypes;
|
||||
}
|
||||
|
||||
return it.value().mimeTypes;
|
||||
#else
|
||||
return QStringList();
|
||||
#endif
|
||||
}
|
||||
|
||||
QString Package::defaultPackageRoot() const
|
||||
{
|
||||
return d->defaultPackageRoot;
|
||||
}
|
||||
|
||||
void Package::setDefaultPackageRoot(const QString &packageRoot)
|
||||
{
|
||||
d.detach();
|
||||
d->defaultPackageRoot = packageRoot;
|
||||
if (!d->defaultPackageRoot.isEmpty() && !d->defaultPackageRoot.endsWith('/')) {
|
||||
d->defaultPackageRoot.append('/');
|
||||
}
|
||||
}
|
||||
|
||||
QString Package::servicePrefix() const
|
||||
{
|
||||
return d->servicePrefix;
|
||||
}
|
||||
|
||||
void Package::setServicePrefix(const QString &servicePrefix)
|
||||
{
|
||||
d.detach();
|
||||
d->servicePrefix = servicePrefix;
|
||||
}
|
||||
|
||||
bool Package::allowExternalPaths() const
|
||||
{
|
||||
return d->externalPaths;
|
||||
}
|
||||
|
||||
void Package::setAllowExternalPaths(bool allow)
|
||||
{
|
||||
d.detach();
|
||||
d->externalPaths = allow;
|
||||
}
|
||||
|
||||
KPluginInfo Package::metadata() const
|
||||
{
|
||||
if (!d->metadata && !d->path.isEmpty()) {
|
||||
const QString metadataPath = filePath("metadata");
|
||||
if (!metadataPath.isEmpty()) {
|
||||
d->createPackageMetadata(metadataPath);
|
||||
} else {
|
||||
QFileInfo fileInfo(d->path);
|
||||
|
||||
if (fileInfo.isDir()) {
|
||||
d->createPackageMetadata(d->path);
|
||||
} else if (fileInfo.exists()) {
|
||||
KArchive *archive = 0;
|
||||
QMimeDatabase db;
|
||||
QMimeType mimeType = db.mimeTypeForFile(d->path);
|
||||
|
||||
if (mimeType.inherits("application/zip")) {
|
||||
archive = new KZip(d->path);
|
||||
} else if (mimeType.inherits("application/x-compressed-tar") || mimeType.inherits("application/x-gzip") ||
|
||||
mimeType.inherits("application/x-tar") || mimeType.inherits("application/x-bzip-compressed-tar") ||
|
||||
mimeType.inherits("application/x-xz") || mimeType.inherits("application/x-lzma")) {
|
||||
archive = new KTar(d->path);
|
||||
} else {
|
||||
kWarning() << "Could not open package file, unsupported archive format:" << d->path << mimeType.name();
|
||||
}
|
||||
|
||||
if (archive && archive->open(QIODevice::ReadOnly)) {
|
||||
const KArchiveDirectory *source = archive->directory();
|
||||
QTemporaryDir tempdir;
|
||||
source->copyTo(tempdir.path() + '/');
|
||||
d->createPackageMetadata(tempdir.path() + '/');
|
||||
} else {
|
||||
kWarning() << "Could not open package file:" << d->path;
|
||||
}
|
||||
|
||||
delete archive;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!d->metadata) {
|
||||
d->metadata = new KPluginInfo();
|
||||
}
|
||||
|
||||
return *d->metadata;
|
||||
}
|
||||
|
||||
QString Package::filePath(const char *fileType, const QString &filename) const
|
||||
{
|
||||
if (!d->valid) {
|
||||
//kDebug() << "package is not valid";
|
||||
return QString();
|
||||
}
|
||||
|
||||
const QString discoveryKey(fileType + filename);
|
||||
if (d->discoveries.contains(discoveryKey)) {
|
||||
//qDebug() << "looking for" << discoveryKey << d->discoveries.value(discoveryKey);
|
||||
return d->discoveries[discoveryKey];
|
||||
}
|
||||
|
||||
QStringList paths;
|
||||
|
||||
if (qstrlen(fileType) != 0) {
|
||||
if (!d->contents.contains(fileType)) {
|
||||
//kDebug() << "package does not contain" << fileType << filename;
|
||||
return QString();
|
||||
}
|
||||
|
||||
paths = d->contents[fileType].paths;
|
||||
|
||||
if (paths.isEmpty()) {
|
||||
//kDebug() << "no matching path came of it, while looking for" << fileType << filename;
|
||||
d->discoveries.insert(discoveryKey, QString());
|
||||
return QString();
|
||||
}
|
||||
} else {
|
||||
//when filetype is empty paths is always empty, so try with an empty string
|
||||
paths << QString();
|
||||
}
|
||||
|
||||
//Nested loop, but in the medium case resolves to just one iteration
|
||||
//kDebug() << "prefixes:" << prefixes.count() << prefixes;
|
||||
foreach (const QString &contentsPrefix, d->contentsPrefixPaths) {
|
||||
const QString prefix(d->path + contentsPrefix);
|
||||
|
||||
foreach (const QString &path, paths) {
|
||||
QString file = prefix + path;
|
||||
|
||||
if (!filename.isEmpty()) {
|
||||
file.append("/").append(filename);
|
||||
}
|
||||
|
||||
//kDebug() << "testing" << file << QFile::exists("/bin/ls") << QFile::exists(file);
|
||||
if (QFile::exists(file)) {
|
||||
if (d->externalPaths) {
|
||||
//kDebug() << "found" << file;
|
||||
d->discoveries.insert(discoveryKey, file);
|
||||
return file;
|
||||
}
|
||||
|
||||
// ensure that we don't return files outside of our base path
|
||||
// due to symlink or ../ games
|
||||
QDir dir(file);
|
||||
QString canonicalized = dir.canonicalPath() + QDir::separator();
|
||||
|
||||
//kDebug() << "testing that" << canonicalized << "is in" << d->path;
|
||||
if (canonicalized.startsWith(d->path)) {
|
||||
//kDebug() << "found" << file;
|
||||
d->discoveries.insert(discoveryKey, file);
|
||||
return file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//kDebug() << fileType << filename << "does not exist in" << prefixes << "at root" << d->path;
|
||||
return QString();
|
||||
}
|
||||
|
||||
QStringList Package::entryList(const char *key) const
|
||||
{
|
||||
if (!d->valid) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constFind(key);
|
||||
if (it == d->contents.constEnd()) {
|
||||
//kDebug() << "couldn't find" << key;
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
//kDebug() << "going to list" << key;
|
||||
QStringList list;
|
||||
foreach (const QString &prefix, d->contentsPrefixPaths) {
|
||||
//kDebug() << " looking in" << prefix;
|
||||
foreach (const QString &path, it.value().paths) {
|
||||
//kDebug() << " looking in" << path;
|
||||
if (it.value().directory) {
|
||||
//kDebug() << "it's a directory, so trying out" << d->path + prefix + path;
|
||||
QDir dir(d->path + prefix + path);
|
||||
|
||||
if (d->externalPaths) {
|
||||
list += dir.entryList(QDir::Files | QDir::Readable);
|
||||
} else {
|
||||
// ensure that we don't return files outside of our base path
|
||||
// due to symlink or ../ games
|
||||
QString canonicalized = dir.canonicalPath();
|
||||
if (canonicalized.startsWith(d->path)) {
|
||||
list += dir.entryList(QDir::Files | QDir::Readable);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const QString fullPath = d->path + prefix + path;
|
||||
//kDebug() << "it's a file at" << fullPath << QFile::exists(fullPath);
|
||||
if (!QFile::exists(fullPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (d->externalPaths) {
|
||||
list += fullPath;
|
||||
} else {
|
||||
QDir dir(fullPath);
|
||||
QString canonicalized = dir.canonicalPath() + QDir::separator();
|
||||
|
||||
//kDebug() << "testing that" << canonicalized << "is in" << d->path;
|
||||
if (canonicalized.startsWith(d->path)) {
|
||||
list += fullPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void Package::setPath(const QString &path)
|
||||
{
|
||||
kDebug() << "Package::setPath() " << path;
|
||||
if (path == d->path) {
|
||||
return;
|
||||
}
|
||||
|
||||
d.detach();
|
||||
d->discoveries.clear();
|
||||
if (path.isEmpty()) {
|
||||
d->path.clear();
|
||||
d->valid = false;
|
||||
|
||||
if (d->structure) {
|
||||
d->structure.data()->pathChanged(this);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dir(path);
|
||||
if (dir.isRelative()) {
|
||||
QString location;
|
||||
//kDebug() <<
|
||||
if (!d->defaultPackageRoot.isEmpty()) {
|
||||
dir.setPath(d->defaultPackageRoot);
|
||||
if (dir.isRelative()) {
|
||||
location = QStandardPaths::locate(QStandardPaths::GenericDataLocation, d->defaultPackageRoot + path, QStandardPaths::LocateDirectory);
|
||||
} else {
|
||||
location = d->defaultPackageRoot + path;
|
||||
}
|
||||
}
|
||||
if (location.isEmpty()) {
|
||||
location = QStandardPaths::locate(QStandardPaths::GenericDataLocation, path, QStandardPaths::LocateDirectory);
|
||||
|
||||
if (location.isEmpty()) {
|
||||
d->path.clear();
|
||||
d->valid = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
dir.setPath(location);
|
||||
}
|
||||
|
||||
QString basePath = dir.canonicalPath();
|
||||
bool valid = QFile::exists(basePath);
|
||||
|
||||
if (valid) {
|
||||
QFileInfo info(basePath);
|
||||
if (info.isDir() && !basePath.endsWith('/')) {
|
||||
basePath.append('/');
|
||||
}
|
||||
kDebug() << "basePath is" << basePath;
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << path << "invalid, basePath is" << basePath;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->path == basePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->path = basePath;
|
||||
delete d->metadata;
|
||||
d->metadata = 0;
|
||||
d->valid = !d->path.isEmpty();
|
||||
|
||||
if (d->structure) {
|
||||
d->structure.data()->pathChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
const QString Package::path() const
|
||||
{
|
||||
return d->path;
|
||||
}
|
||||
|
||||
QStringList Package::contentsPrefixPaths() const
|
||||
{
|
||||
return d->contentsPrefixPaths;
|
||||
}
|
||||
|
||||
void Package::setContentsPrefixPaths(const QStringList &prefixPaths)
|
||||
{
|
||||
d.detach();
|
||||
d->contentsPrefixPaths = prefixPaths;
|
||||
if (d->contentsPrefixPaths.isEmpty()) {
|
||||
d->contentsPrefixPaths << QString();
|
||||
} else {
|
||||
// the code assumes that the prefixes have a trailing slash
|
||||
// so let's make that true here
|
||||
QMutableStringListIterator it(d->contentsPrefixPaths);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
|
||||
if (!it.value().endsWith('/')) {
|
||||
it.setValue(it.value() % '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString Package::contentsHash() const
|
||||
{
|
||||
if (!d->valid) {
|
||||
kWarning() << "can not create hash due to Package being invalid";
|
||||
return QString();
|
||||
}
|
||||
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
QString metadataPath = d->path + "metadata.desktop";
|
||||
if (QFile::exists(metadataPath)) {
|
||||
QFile f(metadataPath);
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
while (!f.atEnd()) {
|
||||
hash.addData(f.read(1024));
|
||||
}
|
||||
} else {
|
||||
kWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading.";
|
||||
}
|
||||
} else {
|
||||
kWarning() << "no metadata at" << metadataPath;
|
||||
}
|
||||
|
||||
foreach (QString prefix, d->contentsPrefixPaths) {
|
||||
const QString basePath = d->path + prefix;
|
||||
QDir dir(basePath);
|
||||
|
||||
if (!dir.exists()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
d->updateHash(basePath, QString(), dir, hash);
|
||||
}
|
||||
|
||||
return hash.result().toHex();
|
||||
}
|
||||
|
||||
void Package::addDirectoryDefinition(const char *key, const QString &path, const QString &name)
|
||||
{
|
||||
ContentStructure s;
|
||||
|
||||
if (d->contents.contains(key)) {
|
||||
s = d->contents[key];
|
||||
}
|
||||
|
||||
#ifndef PLASMA_NO_PACKAGE_EXTRADATA
|
||||
if (!name.isEmpty()) {
|
||||
s.name = name;
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(name)
|
||||
#endif
|
||||
|
||||
s.paths.append(path);
|
||||
s.directory = true;
|
||||
|
||||
d->contents[key] = s;
|
||||
}
|
||||
|
||||
void Package::addFileDefinition(const char *key, const QString &path, const QString &name)
|
||||
{
|
||||
ContentStructure s;
|
||||
|
||||
if (d->contents.contains(key)) {
|
||||
s = d->contents[key];
|
||||
}
|
||||
|
||||
#ifndef PLASMA_NO_PACKAGE_EXTRADATA
|
||||
if (!name.isEmpty()) {
|
||||
s.name = name;
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(name)
|
||||
#endif
|
||||
|
||||
s.paths.append(path);
|
||||
s.directory = false;
|
||||
|
||||
d->contents[key] = s;
|
||||
}
|
||||
|
||||
void Package::removeDefinition(const char *key)
|
||||
{
|
||||
d->contents.remove(key);
|
||||
}
|
||||
|
||||
void Package::setRequired(const char *key, bool required)
|
||||
{
|
||||
QHash<QByteArray, ContentStructure>::iterator it = d->contents.find(key);
|
||||
if (it == d->contents.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
d.detach();
|
||||
it.value().required = required;
|
||||
}
|
||||
|
||||
void Package::setDefaultMimeTypes(QStringList mimeTypes)
|
||||
{
|
||||
#ifndef PLASMA_NO_PACKAGE_EXTRADATA
|
||||
d.detach();
|
||||
d->mimeTypes = mimeTypes;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Package::setMimeTypes(const char *key, QStringList mimeTypes)
|
||||
{
|
||||
#ifndef PLASMA_NO_PACKAGE_EXTRADATA
|
||||
QHash<QByteArray, ContentStructure>::iterator it = d->contents.find(key);
|
||||
if (it == d->contents.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
d.detach();
|
||||
it.value().mimeTypes = mimeTypes;
|
||||
#endif
|
||||
}
|
||||
|
||||
QList<const char*> Package::directories() const
|
||||
{
|
||||
QList<const char*> dirs;
|
||||
QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
|
||||
while (it != d->contents.constEnd()) {
|
||||
if (it.value().directory) {
|
||||
dirs << it.key();
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return dirs;
|
||||
}
|
||||
|
||||
QList<const char*> Package::requiredDirectories() const
|
||||
{
|
||||
QList<const char*> dirs;
|
||||
QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
|
||||
while (it != d->contents.constEnd()) {
|
||||
if (it.value().directory &&
|
||||
it.value().required) {
|
||||
dirs << it.key();
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return dirs;
|
||||
}
|
||||
|
||||
QList<const char*> Package::files() const
|
||||
{
|
||||
QList<const char*> files;
|
||||
QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
|
||||
while (it != d->contents.constEnd()) {
|
||||
if (!it.value().directory) {
|
||||
files << it.key();
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
QList<const char*> Package::requiredFiles() const
|
||||
{
|
||||
QList<const char*> files;
|
||||
QHash<QByteArray, ContentStructure>::const_iterator it = d->contents.constBegin();
|
||||
while (it != d->contents.constEnd()) {
|
||||
if (!it.value().directory && it.value().required) {
|
||||
files << it.key();
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
KJob* Package::install(const QString &sourcePackage, const QString &packageRoot)
|
||||
{
|
||||
const QString src = sourcePackage;
|
||||
const QString dest = packageRoot.isEmpty() ? defaultPackageRoot() : packageRoot;
|
||||
//kDebug() << "Source: " << src;
|
||||
//kDebug() << "PackageRoot: " << dest;
|
||||
d->path = packageRoot + "plasma-applet-org.kde.microblog-qml";
|
||||
KJob *j = d->structure.data()->install(this, src, dest);
|
||||
//connect(j, SIGNAL(finished(bool)), SLOT(installFinished(bool)));
|
||||
return j;
|
||||
}
|
||||
|
||||
KJob* Package::uninstall(const QString &packageName, const QString &packageRoot)
|
||||
{
|
||||
|
||||
const QString pname = metadata().pluginName();
|
||||
|
||||
QString proot = path();
|
||||
proot.replace(pname, "");
|
||||
kDebug() << "Package::uninstalling ... " << packageRoot << proot << pname << packageName;
|
||||
return d->structure.data()->uninstall(this, packageRoot);
|
||||
}
|
||||
|
||||
PackagePrivate::PackagePrivate()
|
||||
: QSharedData(),
|
||||
servicePrefix("plasma-applet-"),
|
||||
metadata(0),
|
||||
externalPaths(false),
|
||||
valid(false)
|
||||
{
|
||||
contentsPrefixPaths << "contents/";
|
||||
}
|
||||
|
||||
PackagePrivate::PackagePrivate(const PackagePrivate &other)
|
||||
: QSharedData()
|
||||
{
|
||||
*this = other;
|
||||
metadata = 0;
|
||||
}
|
||||
|
||||
PackagePrivate::~PackagePrivate()
|
||||
{
|
||||
delete metadata;
|
||||
}
|
||||
|
||||
PackagePrivate &PackagePrivate::operator=(const PackagePrivate &rhs)
|
||||
{
|
||||
if (&rhs == this) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
structure = rhs.structure;
|
||||
path = rhs.path;
|
||||
contentsPrefixPaths = rhs.contentsPrefixPaths;
|
||||
servicePrefix = rhs.servicePrefix;
|
||||
contents = rhs.contents;
|
||||
#ifndef PLASMA_NO_PACKAGE_EXTRADATA
|
||||
mimeTypes = rhs.mimeTypes;
|
||||
#endif
|
||||
defaultPackageRoot = rhs.defaultPackageRoot;
|
||||
servicePrefix = rhs.servicePrefix;
|
||||
metadata = 0;
|
||||
externalPaths = rhs.externalPaths;
|
||||
valid = rhs.valid;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void PackagePrivate::updateHash(const QString &basePath, const QString &subPath, const QDir &dir, QCryptographicHash &hash)
|
||||
{
|
||||
// hash is calculated as a function of:
|
||||
// * files ordered alphabetically by name, with each file's:
|
||||
// * path relative to the content root
|
||||
// * file data
|
||||
// * directories ordered alphabetically by name, with each dir's:
|
||||
// * path relative to the content root
|
||||
// * file listing (recursing)
|
||||
// symlinks (in both the file and dir case) are handled by adding
|
||||
// the name of the symlink itself and the abs path of what it points to
|
||||
|
||||
const QDir::SortFlags sorting = QDir::Name | QDir::IgnoreCase;
|
||||
const QDir::Filters filters = QDir::Hidden | QDir::System | QDir::NoDotAndDotDot;
|
||||
foreach (const QString &file, dir.entryList(QDir::Files | filters, sorting)) {
|
||||
if (!subPath.isEmpty()) {
|
||||
hash.addData(subPath.toUtf8());
|
||||
}
|
||||
|
||||
hash.addData(file.toUtf8());
|
||||
|
||||
QFileInfo info(dir.path() + '/' + file);
|
||||
if (info.isSymLink()) {
|
||||
hash.addData(info.symLinkTarget().toUtf8());
|
||||
} else {
|
||||
QFile f(info.filePath());
|
||||
if (f.open(QIODevice::ReadOnly)) {
|
||||
while (!f.atEnd()) {
|
||||
hash.addData(f.read(1024));
|
||||
}
|
||||
} else {
|
||||
kWarning() << "could not add" << f.fileName() << "to the hash; file could not be opened for reading. "
|
||||
<< "permissions fail?" << info.permissions() << info.isFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const QString &subDirPath, dir.entryList(QDir::Dirs | filters, sorting)) {
|
||||
const QString relativePath = subPath + subDirPath + '/';
|
||||
hash.addData(relativePath.toUtf8());
|
||||
|
||||
QDir subDir(dir.path());
|
||||
subDir.cd(subDirPath);
|
||||
|
||||
if (subDir.path() != subDir.canonicalPath()) {
|
||||
hash.addData(subDir.canonicalPath().toUtf8());
|
||||
} else {
|
||||
updateHash(basePath, relativePath, subDir, hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PackagePrivate::createPackageMetadata(const QString &path)
|
||||
{
|
||||
delete metadata;
|
||||
|
||||
QString metadataPath(path + "/metadata.desktop");
|
||||
if (!QFile::exists(metadataPath)) {
|
||||
kWarning() << "No metadata file in the package, expected it at:" << metadataPath;
|
||||
metadataPath.clear();
|
||||
}
|
||||
|
||||
metadata = new KPluginInfo(metadataPath);
|
||||
}
|
||||
|
||||
} // Namespace
|
329
plasma/package.h
Normal file
329
plasma/package.h
Normal file
@ -0,0 +1,329 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2007-2011 by Aaron Seigo <aseigo@kde.org> *
|
||||
* *
|
||||
* This library 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 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; see the file COPYING.LIB. If not, write to *
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
||||
* Boston, MA 02110-1301, USA. *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef PLASMA_PACKAGE_H
|
||||
#define PLASMA_PACKAGE_H
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
class KJob;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
/**
|
||||
* @class Package plasma/package.h <Plasma/Package>
|
||||
*
|
||||
* @short object representing an installed Plasma package
|
||||
*
|
||||
* Package defines what is in a package and provides easy access to the contents.
|
||||
*
|
||||
* To define a package, one might write the following code:
|
||||
*
|
||||
@code
|
||||
Package package;
|
||||
|
||||
package.addDirectoryDefinition("images", "pics/", i18n("Images"));
|
||||
QStringList mimeTypes;
|
||||
mimeTypes << "image/svg" << "image/png" << "image/jpeg";
|
||||
package.setMimeTypes("images", mimeTypes);
|
||||
|
||||
package.addDirectoryDefinition("scripts", "code/", i18n("Executable Scripts"));
|
||||
mimeTypes.clear();
|
||||
mimeTypes << "text/\*";
|
||||
package.setMimeTypes("scripts", mimeTypes);
|
||||
|
||||
package.addFileDefinition("mainscript", "code/main.js", i18n("Main Script File"));
|
||||
package.setRequired("mainscript", true);
|
||||
@endcode
|
||||
* One may also choose to create a subclass of PackageStructure and include the setup
|
||||
* in the constructor.
|
||||
*
|
||||
* Either way, Package creates a self-documenting contract between the packager and
|
||||
* the application without exposing package internals such as actual on-disk structure
|
||||
* of the package or requiring that all contents be explicitly known ahead of time.
|
||||
*
|
||||
* Subclassing PackageStructure does have provide a number of potential const benefits:
|
||||
* * the package can be notified of path changes via the virtual pathChanged() method
|
||||
* * the subclass may implement mechanisms to install and remove packages using the
|
||||
* virtual install and uninstall methods
|
||||
* * subclasses can be compiled as plugins for easy re-use
|
||||
**/
|
||||
//TODO: write documentation on USING a package
|
||||
|
||||
class PackagePrivate;
|
||||
class PackageStructure;
|
||||
|
||||
class PLASMA_EXPORT Package
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
* @arg structure if a NULL pointer is passed in, this will creates an empty (invalid) Package;
|
||||
* otherwise the structure is allowed to set up the Package's initial layout
|
||||
* @since 4.6
|
||||
*/
|
||||
explicit Package(PackageStructure *structure = 0);
|
||||
|
||||
/**
|
||||
* Copy constructore
|
||||
* @since 4.6
|
||||
*/
|
||||
Package(const Package &other);
|
||||
|
||||
~Package();
|
||||
|
||||
/**
|
||||
* Assignment operator
|
||||
* @since 4.6
|
||||
*/
|
||||
Package &operator=(const Package &rhs);
|
||||
|
||||
/**
|
||||
* @return true if all the required components exist
|
||||
**/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Sets the path to the root of this package
|
||||
* @param path an absolute path, or a relative path to the default package root
|
||||
* @since 4.3
|
||||
*/
|
||||
void setPath(const QString &path);
|
||||
|
||||
/**
|
||||
* @return the path to the root of this particular package
|
||||
*/
|
||||
const QString path() const;
|
||||
|
||||
/**
|
||||
* Get the path to a given file based on the key and an optional filename.
|
||||
* Example: finding the main script in a scripting package:
|
||||
* filePath("mainscript")
|
||||
*
|
||||
* Example: finding a specific image in the images directory:
|
||||
* filePath("images", "myimage.png")
|
||||
*
|
||||
* @param key the key of the file type to look for,
|
||||
* @param filename optional name of the file to locate within the package
|
||||
* @return path to the file on disk. QString() if not found.
|
||||
**/
|
||||
QString filePath(const char *key, const QString &filename = QString()) const;
|
||||
|
||||
/**
|
||||
* Get the list of files of a given type.
|
||||
*
|
||||
* @param fileType the type of file to look for, as defined in the
|
||||
* package structure.
|
||||
* @return list of files by name, suitable for passing to filePath
|
||||
**/
|
||||
QStringList entryList(const char *key) const;
|
||||
|
||||
/**
|
||||
* @return user visible name for the given entry
|
||||
**/
|
||||
QString name(const char *key) const;
|
||||
|
||||
/**
|
||||
* @return true if the item at path exists and is required
|
||||
**/
|
||||
bool isRequired(const char *key) const;
|
||||
|
||||
/**
|
||||
* @return the mimeTypes associated with the path, if any
|
||||
**/
|
||||
QStringList mimeTypes(const char *key) const;
|
||||
|
||||
/**
|
||||
* @return the prefix paths inserted between the base path and content entries, in order of priority.
|
||||
* When searching for a file, all paths will be tried in order.
|
||||
* @since 4.6
|
||||
*/
|
||||
QStringList contentsPrefixPaths() const;
|
||||
|
||||
/**
|
||||
* @return preferred package root. This defaults to plasma/plasmoids/
|
||||
*/
|
||||
QString defaultPackageRoot() const;
|
||||
|
||||
/**
|
||||
* @return service prefix used in desktop files. This defaults to plasma-applet-
|
||||
*/
|
||||
QString servicePrefix() const;
|
||||
|
||||
/**
|
||||
* @return true if paths/symlinks outside the package itself should be followed.
|
||||
* By default this is set to false for security reasons.
|
||||
*/
|
||||
bool allowExternalPaths() const;
|
||||
|
||||
/**
|
||||
* @return the package metadata object.
|
||||
*/
|
||||
KPluginInfo metadata() const;
|
||||
|
||||
/**
|
||||
* @return a SHA1 hash digest of the contents of the package in hexadecimal form
|
||||
* @since 4.4
|
||||
*/
|
||||
QString contentsHash() const;
|
||||
|
||||
/**
|
||||
* Adds a directory to the structure of the package. It is added as
|
||||
* a not-required element with no associated mimeTypes.
|
||||
*
|
||||
* Starting in 4.6, if an entry with the given key
|
||||
* already exists, the path is added to it as a search alternative.
|
||||
*
|
||||
* @param key used as an internal label for this directory
|
||||
* @param path the path within the package for this directory
|
||||
* @param name the user visible (translated) name for the directory
|
||||
**/
|
||||
void addDirectoryDefinition(const char *key, const QString &path, const QString &name);
|
||||
|
||||
/**
|
||||
* Adds a file to the structure of the package. It is added as
|
||||
* a not-required element with no associated mimeTypes.
|
||||
*
|
||||
* Starting in 4.6, if an entry with the given key
|
||||
* already exists, the path is added to it as a search alternative.
|
||||
*
|
||||
* @param key used as an internal label for this file
|
||||
* @param path the path within the package for this file
|
||||
* @param name the user visible (translated) name for the file
|
||||
**/
|
||||
void addFileDefinition(const char *key, const QString &path, const QString &name);
|
||||
|
||||
/**
|
||||
* Removes a definition from the structure of the package.
|
||||
* @since 4.6
|
||||
* @param key the internal label of the file or directory to remove
|
||||
*/
|
||||
void removeDefinition(const char *key);
|
||||
|
||||
/**
|
||||
* Sets whether or not a given part of the structure is required or not.
|
||||
* The path must already have been added using addDirectoryDefinition
|
||||
* or addFileDefinition.
|
||||
*
|
||||
* @param key the entry within the package
|
||||
* @param required true if this entry is required, false if not
|
||||
*/
|
||||
void setRequired(const char *key, bool required);
|
||||
|
||||
/**
|
||||
* Defines the default mimeTypes for any definitions that do not have
|
||||
* associated mimeTypes. Handy for packages with only one or predominantly
|
||||
* one file type.
|
||||
*
|
||||
* @param mimeTypes a list of mimeTypes
|
||||
**/
|
||||
void setDefaultMimeTypes(QStringList mimeTypes);
|
||||
|
||||
/**
|
||||
* Define mimeTypes for a given part of the structure
|
||||
* The path must already have been added using addDirectoryDefinition
|
||||
* or addFileDefinition.
|
||||
*
|
||||
* @param key the entry within the package
|
||||
* @param mimeTypes a list of mimeTypes
|
||||
**/
|
||||
void setMimeTypes(const char *key, QStringList mimeTypes);
|
||||
|
||||
/**
|
||||
* Sets the prefixes that all the contents in this package should
|
||||
* appear under. This defaults to "contents/" and is added automatically
|
||||
* between the base path and the entries as defined by the package
|
||||
* structure. Multiple entries can be added.
|
||||
* In this case each file request will be searched in all prefixes in order,
|
||||
* and the first found will be returned.
|
||||
*
|
||||
* @param prefix paths the directory prefix to use
|
||||
* @since 4.6
|
||||
*/
|
||||
void setContentsPrefixPaths(const QStringList &prefixPaths);
|
||||
|
||||
/**
|
||||
* Sets service prefix.
|
||||
*/
|
||||
void setServicePrefix(const QString &servicePrefix);
|
||||
|
||||
/**
|
||||
* Sets whether or not external paths/symlinks can be followed by a package
|
||||
* @param allow true if paths/symlinks outside of the package should be followed,
|
||||
* false if they should be rejected.
|
||||
*/
|
||||
void setAllowExternalPaths(bool allow);
|
||||
|
||||
/**
|
||||
* Sets preferred package root.
|
||||
*/
|
||||
void setDefaultPackageRoot(const QString &packageRoot);
|
||||
|
||||
// Content structure description methods
|
||||
/**
|
||||
* @return all directories registered as part of this Package's structure
|
||||
*/
|
||||
QList<const char*> directories() const;
|
||||
|
||||
/**
|
||||
* @return all directories registered as part of this Package's required structure
|
||||
*/
|
||||
QList<const char*> requiredDirectories() const;
|
||||
|
||||
/**
|
||||
* @return all files registered as part of this Package's structure
|
||||
*/
|
||||
QList<const char*> files() const;
|
||||
|
||||
/**
|
||||
* @return all files registered as part of this Package's required structure
|
||||
*/
|
||||
QList<const char*> requiredFiles() const;
|
||||
|
||||
/**
|
||||
* Installs a package matching this package structure. By default installs a
|
||||
* native Plasma::Package.
|
||||
*
|
||||
* @return KJob to track installation progress and result
|
||||
**/
|
||||
KJob* install(const QString &sourcePackage, const QString &packageRoot = QString());
|
||||
|
||||
/**
|
||||
* Uninstalls a package matching this package structure.
|
||||
*
|
||||
* @return KJob to track removal progress and result
|
||||
*/
|
||||
KJob* uninstall(const QString &packageName, const QString &packageRoot);
|
||||
|
||||
private:
|
||||
QExplicitlySharedDataPointer<PackagePrivate> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(Plasma::Package)
|
||||
#endif
|
||||
|
68
plasma/packagestructure.cpp
Normal file
68
plasma/packagestructure.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2011 by Aaron Seigo <aseigo@kde.org> *
|
||||
* *
|
||||
* This library 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 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; see the file COPYING.LIB. If not, write to *
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
||||
* Boston, MA 02110-1301, USA. *
|
||||
*******************************************************************************/
|
||||
|
||||
#include "packagestructure.h"
|
||||
#include <kdebug.h>
|
||||
#include <private/packagejob_p.h>
|
||||
#include "private/package_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
PackageStructure::PackageStructure(QObject *parent, const QVariantList &args)
|
||||
: QObject(parent),
|
||||
d(0)
|
||||
{
|
||||
Q_UNUSED(args)
|
||||
}
|
||||
|
||||
PackageStructure::~PackageStructure()
|
||||
{
|
||||
}
|
||||
|
||||
void PackageStructure::initPackage(Package *package)
|
||||
{
|
||||
Q_UNUSED(package)
|
||||
}
|
||||
|
||||
void PackageStructure::pathChanged(Package *package)
|
||||
{
|
||||
Q_UNUSED(package)
|
||||
}
|
||||
|
||||
KJob* PackageStructure::install(Package *package, const QString &archivePath, const QString &packageRoot)
|
||||
{
|
||||
PackageJob* j = new PackageJob(package->servicePrefix(), this);
|
||||
j->install(archivePath, packageRoot);
|
||||
return j;
|
||||
}
|
||||
|
||||
KJob* PackageStructure::uninstall(Package *package, const QString &packageRoot)
|
||||
{
|
||||
PackageJob* j = new PackageJob(package->servicePrefix(), this);
|
||||
kDebug() << "PS: " << package->path() << package->isValid();
|
||||
j->uninstall(package->path());
|
||||
return j;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "moc_packagestructure.cpp"
|
104
plasma/packagestructure.h
Normal file
104
plasma/packagestructure.h
Normal file
@ -0,0 +1,104 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2011 by Aaron Seigo <aseigo@kde.org> *
|
||||
* *
|
||||
* This library 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 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; see the file COPYING.LIB. If not, write to *
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
||||
* Boston, MA 02110-1301, USA. *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef PLASMA_PACKAGESTRUCTURE_H
|
||||
#define PLASMA_PACKAGESTRUCTURE_H
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
|
||||
#include <plasma/plasma.h>
|
||||
#include <plasma/plasma_export.h>
|
||||
#include <plasma/package.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class PackageStructurePrivate;
|
||||
|
||||
class PLASMA_EXPORT PackageStructure : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit PackageStructure(QObject *parent = 0, const QVariantList &args = QVariantList());
|
||||
|
||||
~PackageStructure();
|
||||
|
||||
/**
|
||||
* Called when a the PackageStructure should initialize a Package with the initial
|
||||
* structure. This allows setting paths before setPath is called.
|
||||
*
|
||||
* Note: one special value is "metadata" which can be set to the location of KPluginInfo
|
||||
* compatible .desktop file within the package. If not defined, it is assumed that this file
|
||||
* exists under the top level directory of the package.
|
||||
*
|
||||
* @arg package the Package to set up. The object is empty of all definition when
|
||||
* first passed in.
|
||||
*/
|
||||
virtual void initPackage(Package *package);
|
||||
|
||||
/**
|
||||
* Called whenever the path changes so that subclasses may take
|
||||
* package specific actions.
|
||||
*/
|
||||
virtual void pathChanged(Package *package);
|
||||
|
||||
/**
|
||||
* Installs a package matching this package structure. By default installs a
|
||||
* native Plasma::Package.
|
||||
*
|
||||
* @param package the instance of Package that is being used for the install; useful for
|
||||
* accessing file paths
|
||||
* @param archivePath path to the package archive file
|
||||
* @param packageRoot path to the directory where the package should be
|
||||
* installed to
|
||||
* @return KJob* to track the installation status
|
||||
**/
|
||||
virtual KJob* install(Package *package, const QString &archivePath, const QString &packageRoot);
|
||||
|
||||
/**
|
||||
* Uninstalls a package matching this package structure.
|
||||
*
|
||||
* @param package the instance of Package that is being used for the install; useful for
|
||||
* accessing file paths
|
||||
* @param packageName the name of the package to remove
|
||||
* @param packageRoot path to the directory where the package should be installed to
|
||||
* @return KJob* to track the installation status
|
||||
*/
|
||||
virtual KJob* uninstall(Package *package, const QString &packageRoot);
|
||||
|
||||
private:
|
||||
PackageStructurePrivate* d;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
/**
|
||||
* Register a Package class when it is contained in a loadable module
|
||||
*/
|
||||
#define K_EXPORT_PLASMA_PACKAGE(libname, classname) \
|
||||
K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
|
||||
K_EXPORT_PLUGIN(factory("plasma_packagestructure_" #libname)) \
|
||||
K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
|
||||
|
||||
#endif
|
||||
|
335
plasma/paintutils.cpp
Normal file
335
plasma/paintutils.cpp
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright 2005 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Andrew Lake <jamboarder@yahoo.com>
|
||||
*
|
||||
* 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 <paintutils.h>
|
||||
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <QPaintEngine>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "private/effects/blur.cpp"
|
||||
#include "private/effects/halopainter_p.h"
|
||||
#include "svg.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
namespace PaintUtils
|
||||
{
|
||||
|
||||
void shadowBlur(QImage &image, int radius, const QColor &color)
|
||||
{
|
||||
if (radius < 1) {
|
||||
return;
|
||||
}
|
||||
if (image.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
expblur<16, 7>(image, radius);
|
||||
|
||||
QPainter p(&image);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
p.fillRect(image.rect(), color);
|
||||
p.end();
|
||||
}
|
||||
|
||||
//TODO: we should have shadowText methods that paint the results directly into a QPainter passed in
|
||||
QPixmap shadowText(QString text, QColor textColor, QColor shadowColor, QPoint offset, int radius)
|
||||
{
|
||||
return shadowText(text, qApp->font(), textColor, shadowColor, offset, radius);
|
||||
}
|
||||
|
||||
QPixmap shadowText(QString text, const QFont &font, QColor textColor, QColor shadowColor, QPoint offset, int radius)
|
||||
{
|
||||
//don't try to paint stuff on a future null pixmap because the text is empty
|
||||
if (text.isEmpty()) {
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
// Draw text
|
||||
QFontMetrics fm(font);
|
||||
QRect textRect = fm.boundingRect(text);
|
||||
QPixmap textPixmap(textRect.width(), fm.height());
|
||||
textPixmap.fill(Qt::transparent);
|
||||
QPainter p(&textPixmap);
|
||||
p.setPen(textColor);
|
||||
p.setFont(font);
|
||||
// FIXME: the center alignment here is odd: the rect should be the size needed by
|
||||
// the text, but for some fonts and configurations this is off by a pixel or so
|
||||
// and "centering" the text painting 'fixes' that. Need to research why
|
||||
// this is the case and determine if we should be painting it differently here,
|
||||
// doing soething different with the boundingRect call or if it's a problem
|
||||
// in Qt itself
|
||||
p.drawText(textPixmap.rect(), Qt::AlignCenter, text);
|
||||
p.end();
|
||||
|
||||
//Draw blurred shadow
|
||||
QImage img(textRect.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied);
|
||||
img.fill(0);
|
||||
p.begin(&img);
|
||||
p.drawImage(QPoint(radius, radius), textPixmap.toImage());
|
||||
p.end();
|
||||
shadowBlur(img, radius, shadowColor);
|
||||
|
||||
//Compose text and shadow
|
||||
int addSizeX = qMax(0, qAbs(offset.x()) - radius);
|
||||
int addSizeY = qMax(0, qAbs(offset.y()) - radius);
|
||||
|
||||
QPixmap finalPixmap(img.size() + QSize(addSizeX, addSizeY));
|
||||
finalPixmap.fill(Qt::transparent);
|
||||
p.begin(&finalPixmap);
|
||||
p.drawImage(qMax(0, offset.x()), qMax(0, offset.y()), img);
|
||||
p.drawPixmap(radius + qMax(0, -offset.x()), radius + qMax(0, -offset.y()), textPixmap);
|
||||
p.end();
|
||||
|
||||
return finalPixmap;
|
||||
}
|
||||
|
||||
QPixmap texturedText(const QString &text, const QFont &font, Plasma::Svg *texture)
|
||||
{
|
||||
QFontMetrics fm(font);
|
||||
//the text will be moved a bit from contentsRect
|
||||
QRect contentsRect = fm.boundingRect(text).adjusted(0, 0, 2, 2);
|
||||
contentsRect.moveTo(0,0);
|
||||
|
||||
QPixmap pixmap(contentsRect.size());
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter buffPainter(&pixmap);
|
||||
buffPainter.setPen(Qt::black);
|
||||
|
||||
buffPainter.setFont(font);
|
||||
buffPainter.drawText(contentsRect, Qt::AlignCenter, text);
|
||||
buffPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
texture->paint(&buffPainter, contentsRect, "foreground");
|
||||
buffPainter.end();
|
||||
|
||||
//do the shadow
|
||||
QImage image(pixmap.size() + QSize(2, 2), QImage::Format_ARGB32_Premultiplied);
|
||||
image.fill(Qt::transparent);
|
||||
buffPainter.begin(&image);
|
||||
buffPainter.setFont(font);
|
||||
buffPainter.drawText(contentsRect.translated(1, 1), Qt::AlignCenter, text);
|
||||
buffPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
texture->paint(&buffPainter, contentsRect.adjusted(-1, -1, 1, 1), "shadow");
|
||||
buffPainter.end();
|
||||
|
||||
expblur<16, 7>(image, 1);
|
||||
//hole in the shadow
|
||||
buffPainter.begin(&image);
|
||||
buffPainter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
|
||||
buffPainter.setFont(font);
|
||||
buffPainter.drawText(contentsRect.translated(1, 1), Qt::AlignCenter, text);
|
||||
buffPainter.end();
|
||||
|
||||
QPixmap ret(image.size());
|
||||
ret.fill(Qt::transparent);
|
||||
buffPainter.begin(&ret);
|
||||
buffPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
buffPainter.drawImage(QPoint(0,0), image);
|
||||
buffPainter.drawPixmap(QPoint(1,1), pixmap);
|
||||
buffPainter.end();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void drawHalo(QPainter *painter, const QRectF &rect)
|
||||
{
|
||||
HaloPainter::instance()->drawHalo(painter, rect.toRect());
|
||||
}
|
||||
|
||||
QPainterPath roundedRectangle(const QRectF &rect, qreal radius)
|
||||
{
|
||||
QPainterPath path(QPointF(rect.left(), rect.top() + radius));
|
||||
path.quadTo(rect.left(), rect.top(), rect.left() + radius, rect.top()); // Top left corner
|
||||
path.lineTo(rect.right() - radius, rect.top()); // Top side
|
||||
path.quadTo(rect.right(), rect.top(), rect.right(), rect.top() + radius); // Top right corner
|
||||
path.lineTo(rect.right(), rect.bottom() - radius); // Right side
|
||||
path.quadTo(rect.right(), rect.bottom(), rect.right() - radius, rect.bottom()); // Bottom right corner
|
||||
path.lineTo(rect.left() + radius, rect.bottom()); // Bottom side
|
||||
path.quadTo(rect.left(), rect.bottom(), rect.left(), rect.bottom() - radius); // Bottom left corner
|
||||
path.closeSubpath();
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void centerPixmaps(QPixmap &from, QPixmap &to)
|
||||
{
|
||||
if (from.size() == to.size() && from.hasAlphaChannel() && to.hasAlphaChannel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QRect fromRect(from.rect());
|
||||
QRect toRect(to.rect());
|
||||
|
||||
QRect actualRect = QRect(QPoint(0,0), fromRect.size().expandedTo(toRect.size()));
|
||||
fromRect.moveCenter(actualRect.center());
|
||||
toRect.moveCenter(actualRect.center());
|
||||
|
||||
if (from.size() != actualRect.size() || !from.hasAlphaChannel()) {
|
||||
QPixmap result(actualRect.size());
|
||||
result.fill(Qt::transparent);
|
||||
QPainter p(&result);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
p.drawPixmap(fromRect.topLeft(), from);
|
||||
p.end();
|
||||
from = result;
|
||||
}
|
||||
|
||||
if (to.size() != actualRect.size() || !to.hasAlphaChannel()) {
|
||||
QPixmap result(actualRect.size());
|
||||
result.fill(Qt::transparent);
|
||||
QPainter p(&result);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
p.drawPixmap(toRect.topLeft(), to);
|
||||
p.end();
|
||||
to = result;
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
|
||||
{
|
||||
if (from.isNull() && to.isNull()) {
|
||||
return from;
|
||||
}
|
||||
|
||||
if (qFuzzyCompare(amount + 1, qreal(1.0))) {
|
||||
return from;
|
||||
}
|
||||
|
||||
QRect startRect(from.rect());
|
||||
QRect targetRect(to.rect());
|
||||
QSize pixmapSize = startRect.size().expandedTo(targetRect.size());
|
||||
QRect toRect = QRect(QPoint(0,0), pixmapSize);
|
||||
targetRect.moveCenter(toRect.center());
|
||||
startRect.moveCenter(toRect.center());
|
||||
|
||||
//paint to in the center of from
|
||||
QColor color;
|
||||
color.setAlphaF(amount);
|
||||
|
||||
// If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
|
||||
QPaintEngine *paintEngine = from.paintEngine();
|
||||
if (paintEngine &&
|
||||
paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
|
||||
paintEngine->hasFeature(QPaintEngine::BlendModes)) {
|
||||
QPixmap startPixmap(pixmapSize);
|
||||
startPixmap.fill(Qt::transparent);
|
||||
|
||||
QPixmap targetPixmap(pixmapSize);
|
||||
targetPixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter p;
|
||||
p.begin(&targetPixmap);
|
||||
p.drawPixmap(targetRect, to);
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
p.fillRect(targetRect, color);
|
||||
p.end();
|
||||
|
||||
p.begin(&startPixmap);
|
||||
p.drawPixmap(startRect, from);
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
|
||||
p.fillRect(startRect, color);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Plus);
|
||||
p.drawPixmap(targetRect, targetPixmap);
|
||||
p.end();
|
||||
|
||||
return startPixmap;
|
||||
}
|
||||
#warning Cannot use XRender with QPixmap anymore. Find equivalent with Qt API.
|
||||
#if 0 // HAVE_X11 && defined(HAVE_XRENDER)
|
||||
// We have Xrender support
|
||||
else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
|
||||
// QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
|
||||
// which we need to be able to do a transition from one pixmap to
|
||||
// another.
|
||||
//
|
||||
// In order to avoid the overhead of converting the pixmaps to images
|
||||
// and doing the operation entirely in software, this function has a
|
||||
// specialized path for X11 that uses Xrender directly to do the
|
||||
// transition. This operation can be fully accelerated in HW.
|
||||
//
|
||||
// This specialization can be removed when QX11PaintEngine supports
|
||||
// CompositionMode_Plus.
|
||||
QPixmap source(targetPixmap), destination(startPixmap);
|
||||
|
||||
source.detach();
|
||||
destination.detach();
|
||||
|
||||
Display *dpy = QX11Info::display();
|
||||
|
||||
XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
|
||||
XRenderPictureAttributes pa;
|
||||
pa.repeat = 1; // RepeatNormal
|
||||
|
||||
// Create a 1x1 8 bit repeating alpha picture
|
||||
Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
|
||||
Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
|
||||
XFreePixmap(dpy, pixmap);
|
||||
|
||||
// Fill the alpha picture with the opacity value
|
||||
XRenderColor xcolor;
|
||||
xcolor.alpha = quint16(0xffff * amount);
|
||||
XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
|
||||
|
||||
// Reduce the alpha of the destination with 1 - opacity
|
||||
XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
|
||||
0, 0, 0, 0, 0, 0, destination.width(), destination.height());
|
||||
|
||||
// Add source * opacity to the destination
|
||||
XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
|
||||
destination.x11PictureHandle(),
|
||||
toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
|
||||
|
||||
XRenderFreePicture(dpy, alpha);
|
||||
return destination;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
// Fall back to using QRasterPaintEngine to do the transition.
|
||||
QImage under(pixmapSize, QImage::Format_ARGB32_Premultiplied);
|
||||
under.fill(Qt::transparent);
|
||||
QImage over(pixmapSize, QImage::Format_ARGB32_Premultiplied);
|
||||
over.fill(Qt::transparent);
|
||||
|
||||
QPainter p;
|
||||
p.begin(&over);
|
||||
p.drawPixmap(targetRect, to);
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
p.fillRect(over.rect(), color);
|
||||
p.end();
|
||||
|
||||
p.begin(&under);
|
||||
p.drawPixmap(startRect, from);
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
|
||||
p.fillRect(startRect, color);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Plus);
|
||||
p.drawImage(toRect.topLeft(), over);
|
||||
p.end();
|
||||
|
||||
return QPixmap::fromImage(under);
|
||||
}
|
||||
}
|
||||
|
||||
} // PaintUtils namespace
|
||||
|
||||
} // Plasma namespace
|
||||
|
90
plasma/paintutils.h
Normal file
90
plasma/paintutils.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2005 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Andrew Lake <jamboarder@yahoo.com>
|
||||
*
|
||||
* 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 PLASMA_PAINTUTILS_H
|
||||
#define PLASMA_PAINTUTILS_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainterPath>
|
||||
#include <QColor>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
#include "theme.h"
|
||||
|
||||
/** @headerfile plasma/paintutils.h <Plasma/PaintUtils> */
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class Svg;
|
||||
|
||||
/**
|
||||
* Namespace for all Image Effects specific to Plasma
|
||||
**/
|
||||
namespace PaintUtils
|
||||
{
|
||||
|
||||
/**
|
||||
* Creates a blurred shadow of the supplied image.
|
||||
*/
|
||||
PLASMA_EXPORT void shadowBlur(QImage &image, int radius, const QColor &color);
|
||||
|
||||
/**
|
||||
* Returns a pixmap containing text with blurred shadow.
|
||||
* Text and shadow colors default to Plasma::Theme colors.
|
||||
*/
|
||||
PLASMA_EXPORT QPixmap shadowText(QString text,
|
||||
const QFont &font,
|
||||
QColor textColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor),
|
||||
QColor shadowColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor),
|
||||
QPoint offset = QPoint(1,1),
|
||||
int radius = 2);
|
||||
|
||||
PLASMA_EXPORT QPixmap shadowText(QString text,
|
||||
QColor textColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor),
|
||||
QColor shadowColor = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor),
|
||||
QPoint offset = QPoint(1,1),
|
||||
int radius = 2);
|
||||
|
||||
PLASMA_EXPORT QPixmap texturedText(const QString &text, const QFont &font, Plasma::Svg *texture);
|
||||
|
||||
PLASMA_EXPORT void drawHalo(QPainter *painter, const QRectF &rect);
|
||||
|
||||
/**
|
||||
* Returns a nicely rounded rectanglular path for painting.
|
||||
*/
|
||||
PLASMA_EXPORT QPainterPath roundedRectangle(const QRectF &rect, qreal radius);
|
||||
|
||||
/**
|
||||
* center two pixmap together in the biggest rectangle
|
||||
* @since 4.5
|
||||
*/
|
||||
PLASMA_EXPORT void centerPixmaps(QPixmap &from, QPixmap &to);
|
||||
|
||||
/**
|
||||
* Blends a pixmap into another
|
||||
*/
|
||||
PLASMA_EXPORT QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount);
|
||||
|
||||
} // PaintUtils namespace
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif
|
73
plasma/plasma.cpp
Normal file
73
plasma/plasma.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2005 by Aaron Seigo <aseigo@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 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 <plasma/plasma.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
||||
#include "containment.h"
|
||||
#include "private/packages_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
Direction locationToDirection(Location location)
|
||||
{
|
||||
switch (location) {
|
||||
case Floating:
|
||||
case Desktop:
|
||||
case TopEdge:
|
||||
case FullScreen:
|
||||
//TODO: should we be smarter for floating and planer?
|
||||
// perhaps we should take a QRect and/or QPos as well?
|
||||
return Down;
|
||||
case BottomEdge:
|
||||
return Up;
|
||||
case LeftEdge:
|
||||
return Right;
|
||||
case RightEdge:
|
||||
return Left;
|
||||
}
|
||||
|
||||
return Down;
|
||||
}
|
||||
|
||||
Direction locationToInverseDirection(Location location)
|
||||
{
|
||||
switch (location) {
|
||||
case Floating:
|
||||
case Desktop:
|
||||
case TopEdge:
|
||||
case FullScreen:
|
||||
//TODO: should we be smarter for floating and planer?
|
||||
// perhaps we should take a QRect and/or QPos as well?
|
||||
return Up;
|
||||
case BottomEdge:
|
||||
return Down;
|
||||
case LeftEdge:
|
||||
return Left;
|
||||
case RightEdge:
|
||||
return Right;
|
||||
}
|
||||
|
||||
return Up;
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
294
plasma/plasma.h
Normal file
294
plasma/plasma.h
Normal file
@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright 2005 by Aaron Seigo <aseigo@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 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 PLASMA_DEFS_H
|
||||
#define PLASMA_DEFS_H
|
||||
|
||||
/** @header plasma/plasma.h <Plasma/Plasma> */
|
||||
|
||||
#include <QPainterPath>
|
||||
|
||||
#include <plasma/plasma_export.h>
|
||||
|
||||
class QAction;
|
||||
|
||||
/**
|
||||
* Namespace for everything in libplasma
|
||||
*/
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
/**
|
||||
* The Constraint enumeration lists the various constraints that Plasma
|
||||
* objects have managed for them and which they may wish to react to,
|
||||
* for instance in Applet::constraintsUpdated
|
||||
*/
|
||||
enum Constraint {
|
||||
NoConstraint = 0, /**< No constraint; never passed in to Applet::constraintsEvent on its own */
|
||||
FormFactorConstraint = 1, /**< The FormFactor for an object */
|
||||
LocationConstraint = 2, /**< The Location of an object */
|
||||
ScreenConstraint = 4, /**< Which screen an object is on */
|
||||
SizeConstraint = 8, /**< the size of the applet was changed */
|
||||
ImmutableConstraint = 16, /**< the immutability (locked) nature of the applet changed */
|
||||
StartupCompletedConstraint = 32, /**< application startup has completed */
|
||||
ContextConstraint = 64, /**< the context (e.g. activity) has changed */
|
||||
PopupConstraint = 128, /**< the position of the popup needs to be recalculated*/
|
||||
AllConstraints = FormFactorConstraint | LocationConstraint | ScreenConstraint |
|
||||
SizeConstraint | ImmutableConstraint | PopupConstraint
|
||||
};
|
||||
Q_DECLARE_FLAGS(Constraints, Constraint)
|
||||
|
||||
/**
|
||||
* The FormFactor enumeration describes how a Plasma::Applet should arrange
|
||||
* itself. The value is derived from the container managing the Applet
|
||||
* (e.g. in Plasma, a Corona on the desktop or on a panel).
|
||||
**/
|
||||
enum FormFactor {
|
||||
Planar = 0, /**< The applet lives in a plane and has two
|
||||
degrees of freedom to grow. Optimize for
|
||||
desktop, laptop or tablet usage: a high
|
||||
resolution screen 1-3 feet distant from the
|
||||
viewer. */
|
||||
MediaCenter, /**< As with Planar, the applet lives in a plane
|
||||
but the interface should be optimized for
|
||||
medium-to-high resolution screens that are
|
||||
5-15 feet distant from the viewer. Sometimes
|
||||
referred to as a "ten foot interface".*/
|
||||
Horizontal, /**< The applet is constrained vertically, but
|
||||
can expand horizontally. */
|
||||
Vertical, /**< The applet is constrained horizontally, but
|
||||
can expand vertically. */
|
||||
Application /**< The Applet lives in a plane and should be optimized to look as a full application,
|
||||
for the desktop or the particular device. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The Direction enumeration describes in which direction, relative to the
|
||||
* Applet (and its managing container), popup menus, expanders, balloons,
|
||||
* message boxes, arrows and other such visually associated widgets should
|
||||
* appear in. This is usually the oposite of the Location.
|
||||
**/
|
||||
enum Direction {
|
||||
Down = 0, /**< Display downards */
|
||||
Up, /**< Display upwards */
|
||||
Left, /**< Display to the left */
|
||||
Right /**< Display to the right */
|
||||
};
|
||||
|
||||
/**
|
||||
* The Location enumeration describes where on screen an element, such as an
|
||||
* Applet or its managing container, is positioned on the screen.
|
||||
**/
|
||||
enum Location {
|
||||
Floating = 0, /**< Free floating. Neither geometry or z-ordering
|
||||
is described precisely by this value. */
|
||||
Desktop, /**< On the planar desktop layer, extending across
|
||||
the full screen from edge to edge */
|
||||
FullScreen, /**< Full screen */
|
||||
TopEdge, /**< Along the top of the screen*/
|
||||
BottomEdge, /**< Along the bottom of the screen*/
|
||||
LeftEdge, /**< Along the left side of the screen */
|
||||
RightEdge /**< Along the right side of the screen */
|
||||
};
|
||||
|
||||
/**
|
||||
* The position enumeration
|
||||
*
|
||||
**/
|
||||
enum Position {
|
||||
LeftPositioned, /**< Positioned left */
|
||||
RightPositioned, /**< Positioned right */
|
||||
TopPositioned, /**< Positioned top */
|
||||
BottomPositioned, /**< Positioned bottom */
|
||||
CenterPositioned /**< Positioned in the center */
|
||||
};
|
||||
|
||||
/**
|
||||
* The popup position enumeration relatively to his attached widget
|
||||
*
|
||||
**/
|
||||
|
||||
enum PopupPlacement {
|
||||
FloatingPopup = 0, /**< Free floating, non attached popup */
|
||||
TopPosedLeftAlignedPopup, /**< Popup positioned on the top, aligned
|
||||
to the left of the wigdet */
|
||||
TopPosedRightAlignedPopup, /**< Popup positioned on the top, aligned
|
||||
to the right of the widget */
|
||||
LeftPosedTopAlignedPopup, /**< Popup positioned on the left, aligned
|
||||
to the right of the wigdet */
|
||||
LeftPosedBottomAlignedPopup, /**< Popup positioned on the left, aligned
|
||||
to the bottom of the widget */
|
||||
BottomPosedLeftAlignedPopup, /**< Popup positioned on the bottom, aligned
|
||||
to the left of the wigdet */
|
||||
BottomPosedRightAlignedPopup, /**< Popup positioned on the bottom, aligned
|
||||
to the right of the widget */
|
||||
RightPosedTopAlignedPopup, /**< Popup positioned on the right, aligned
|
||||
to the top of the wigdet */
|
||||
RightPosedBottomAlignedPopup /**< Popup positioned on the right, aligned
|
||||
to the bottom of the widget */
|
||||
};
|
||||
|
||||
/**
|
||||
* Flip enumeration
|
||||
*/
|
||||
enum FlipDirection {
|
||||
NoFlip = 0, /**< Do not flip */
|
||||
HorizontalFlip = 1, /**< Flip horizontally */
|
||||
VerticalFlip = 2 /**< Flip vertically */
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flip, FlipDirection)
|
||||
|
||||
/**
|
||||
* Possible timing alignments
|
||||
**/
|
||||
enum IntervalAlignment {
|
||||
NoAlignment = 0, /**< No alignment **/
|
||||
AlignToMinute, /**< Align to the minute **/
|
||||
AlignToHour /**< Align to the hour **/
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the immutability of items like applets, corona and containments
|
||||
* they can be free to modify, locked down by the user or locked down by the
|
||||
* system (e.g. kiosk setups).
|
||||
*/
|
||||
enum ImmutabilityType {
|
||||
Mutable = 1, /**< The item can be modified in any way **/
|
||||
UserImmutable = 2, /**< The user has requested a lock down, and can undo
|
||||
the lock down at any time **/
|
||||
SystemImmutable = 4 /**< the item is locked down by the system, the user
|
||||
can't unlock it **/
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines the aspect ratio used when resizing an applet
|
||||
*/
|
||||
enum AspectRatioMode {
|
||||
InvalidAspectRatioMode = -1, /**< Unset mode used for dev convenience
|
||||
when there is a need to store the
|
||||
aspectRatioMode somewhere */
|
||||
IgnoreAspectRatio = 0, /**< The applet can be freely resized */
|
||||
KeepAspectRatio = 1, /**< The applet keeps a fixed aspect ratio */
|
||||
Square = 2, /**< The applet is always a square */
|
||||
ConstrainedSquare = 3, /**< The applet is no wider (in horizontal
|
||||
formfactors) or no higher (in vertical
|
||||
ones) than a square */
|
||||
FixedSize = 4 /** The applet cannot be resized */
|
||||
};
|
||||
|
||||
/**
|
||||
* The ComonentType enumeration refers to the various types of components,
|
||||
* or plugins, supported by plasma.
|
||||
*/
|
||||
enum ComponentType {
|
||||
AppletComponent = 1, /**< Plasma::Applet based plugins **/
|
||||
DataEngineComponent = 2, /**< Plasma::DataEngine based plugins **/
|
||||
RunnerComponent = 4, /**< Plasma::AbstractRunner based plugsin **/
|
||||
AnimatorComponent = 8, /**< Plasma::Animator based plugins **/
|
||||
ContainmentComponent = 16,/**< Plasma::Containment based plugins **/
|
||||
WallpaperComponent = 32, /**< Plasma::Wallpaper based plugins **/
|
||||
GenericComponent = 64 /** Generic repositories of files, usually they keep QML files and their assets **/
|
||||
};
|
||||
Q_DECLARE_FLAGS(ComponentTypes, ComponentType)
|
||||
|
||||
enum MarginEdge {
|
||||
TopMargin = 0, /**< The top margin **/
|
||||
BottomMargin, /**< The bottom margin **/
|
||||
LeftMargin, /**< The left margin **/
|
||||
RightMargin /**< The right margin **/
|
||||
};
|
||||
|
||||
enum MessageButton {
|
||||
ButtonNone = 0, /**< None **/
|
||||
ButtonOk = 1, /**< OK Button **/
|
||||
ButtonYes = 2, /**< Yes Button **/
|
||||
ButtonNo = 4, /**< No Button **/
|
||||
ButtonCancel = 8 /**< Cancel Button **/
|
||||
};
|
||||
Q_DECLARE_FLAGS(MessageButtons, MessageButton)
|
||||
|
||||
/**
|
||||
* Status of an applet
|
||||
* @since 4.3
|
||||
*/
|
||||
enum ItemStatus {
|
||||
UnknownStatus = 0, /**< The status is unknown **/
|
||||
PassiveStatus = 1, /**< The Item is passive **/
|
||||
ActiveStatus = 2, /**< The Item is active **/
|
||||
NeedsAttentionStatus = 3, /**< The Item needs attention **/
|
||||
AcceptingInputStatus = 4 /**< The Item is accepting input **/
|
||||
};
|
||||
Q_ENUMS(ItemStatus)
|
||||
|
||||
enum AnnouncementMethod {
|
||||
NoAnnouncement = 0, /**< No announcements **/
|
||||
ZeroconfAnnouncement = 1 /**< Announcements via ZeroConf **/
|
||||
};
|
||||
Q_DECLARE_FLAGS(AnnouncementMethods, AnnouncementMethod)
|
||||
|
||||
enum TrustLevel {
|
||||
UnverifiableTrust = 0, /**< The trust of the object can not be verified, usually because no
|
||||
trust information (e.g. a cryptographic signature) was provided */
|
||||
CompletelyUntrusted, /**< The signature is broken/expired/false */
|
||||
UnknownTrusted, /**< The signature is valid, but the key is unknown */
|
||||
UserTrusted, /**< The signature is valid and made with a key signed by one of the
|
||||
user's own keys*/
|
||||
SelfTrusted, /**< The signature is valid and made with one of the user's own keys*/
|
||||
FullyTrusted, /**< The signature is valid and made with a key signed by the vendor's key*/
|
||||
UltimatelyTrusted /**< The signature is valid and made with the vendor's key*/
|
||||
};
|
||||
Q_ENUMS(TrustLevel)
|
||||
|
||||
/**
|
||||
* Description on how draw a background for the applet
|
||||
*/
|
||||
enum BackgroundHints {
|
||||
NoBackground = 0, /**< Not drawing a background under the applet, the applet has its own implementation */
|
||||
StandardBackground = 1, /**< The standard background from the theme is drawn */
|
||||
TranslucentBackground = 2, /**< An alternate version of the background is drawn, usually more translucent */
|
||||
DefaultBackground = StandardBackground /**< Default settings: both standard background */
|
||||
};
|
||||
Q_ENUMS(BackgroundHints)
|
||||
|
||||
/**
|
||||
* Converts a location to a direction. Handy for figuring out which way to send a popup based on
|
||||
* location or to point arrows and other directional items.
|
||||
*
|
||||
* @param location the location of the container the element will appear in
|
||||
* @return the visual direction the element should be oriented in
|
||||
**/
|
||||
PLASMA_EXPORT Direction locationToDirection(Location location);
|
||||
|
||||
/**
|
||||
* Converts a location to the direction facing it. Handy for figuring out which way to collapse
|
||||
* a popup or to point arrows at the item itself.
|
||||
*
|
||||
* @param location the location of the container the element will appear in
|
||||
* @return the visual direction the element should be oriented in
|
||||
**/
|
||||
PLASMA_EXPORT Direction locationToInverseDirection(Location location);
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::Constraints)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::Flip)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::ComponentTypes)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Plasma::MessageButtons)
|
||||
|
||||
#endif // multiple inclusion guard
|
595
plasma/pluginloader.cpp
Normal file
595
plasma/pluginloader.cpp
Normal file
@ -0,0 +1,595 @@
|
||||
/*
|
||||
* Copyright 2010 Ryan Rix <ry@n.rix.si>
|
||||
*
|
||||
* 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 "pluginloader.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <kservice.h>
|
||||
#include <kservicetypetrader.h>
|
||||
#include <kstandarddirs.h>
|
||||
#include <kglobal.h>
|
||||
#include <kplugininfo.h>
|
||||
|
||||
#include "config-plasma.h"
|
||||
|
||||
#if !PLASMA_NO_KIO
|
||||
#include <kio/job.h>
|
||||
#endif
|
||||
|
||||
#include "applet.h"
|
||||
#include "abstractrunner.h"
|
||||
#include "containment.h"
|
||||
#include "containmentactions.h"
|
||||
#include "dataengine.h"
|
||||
#include "package.h"
|
||||
#include "private/applet_p.h"
|
||||
#include "private/packages_p.h"
|
||||
#include "private/service_p.h" // for NullService
|
||||
#include "private/storage_p.h"
|
||||
|
||||
namespace Plasma {
|
||||
|
||||
static PluginLoader *s_pluginLoader = 0;
|
||||
|
||||
class PluginLoaderPrivate
|
||||
{
|
||||
public:
|
||||
QHash<QString, QWeakPointer<PackageStructure> > structures;
|
||||
bool isDefaultLoader;
|
||||
};
|
||||
|
||||
PluginLoader::PluginLoader()
|
||||
: d(new PluginLoaderPrivate)
|
||||
{
|
||||
d->isDefaultLoader = false;
|
||||
}
|
||||
|
||||
PluginLoader::~PluginLoader()
|
||||
{
|
||||
typedef QWeakPointer<PackageStructure> pswp;
|
||||
foreach (pswp wp, d->structures) {
|
||||
delete wp.data();
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
|
||||
void PluginLoader::setPluginLoader(PluginLoader* loader)
|
||||
{
|
||||
if (!s_pluginLoader) {
|
||||
s_pluginLoader = loader;
|
||||
} else {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Cannot set pluginLoader, already set!" << s_pluginLoader;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
PluginLoader *PluginLoader::self()
|
||||
{
|
||||
if (!s_pluginLoader) {
|
||||
// we have been called before any PluginLoader was set, so just use the default
|
||||
// implementation. this prevents plugins from nefariously injecting their own
|
||||
// plugin loader if the app doesn't
|
||||
s_pluginLoader = new PluginLoader;
|
||||
s_pluginLoader->d->isDefaultLoader = true;
|
||||
}
|
||||
|
||||
return s_pluginLoader;
|
||||
}
|
||||
|
||||
Applet *PluginLoader::loadApplet(const QString &name, uint appletId, const QVariantList &args)
|
||||
{
|
||||
// the application-specific appletLoader failed to create an applet, here we try with our own logic.
|
||||
if (name.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Applet *applet = d->isDefaultLoader ? 0 : internalLoadApplet(name, appletId, args);
|
||||
if (applet) {
|
||||
return applet;
|
||||
}
|
||||
|
||||
const QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
|
||||
|
||||
bool isContainment = false;
|
||||
if (offers.isEmpty()) {
|
||||
//TODO: what would be -really- cool is offer to try and download the applet
|
||||
// from the network at this point
|
||||
offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
|
||||
if (offers.count() > 0) {
|
||||
isContainment = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (offers.count() > 1) {
|
||||
kDebug() << "hey! we got more than one! let's blindly take the first one";
|
||||
}
|
||||
#endif
|
||||
|
||||
AppletPrivate::filterOffers(offers);
|
||||
if (offers.isEmpty()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "offers is empty for " << name;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
KService::Ptr offer = offers.first();
|
||||
|
||||
if (appletId == 0) {
|
||||
appletId = ++AppletPrivate::s_maxAppletId;
|
||||
}
|
||||
|
||||
QVariantList allArgs;
|
||||
allArgs << offer->storageId() << appletId << args;
|
||||
|
||||
if (!offer->property("X-Plasma-API").toString().isEmpty()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "we have a script using the"
|
||||
<< offer->property("X-Plasma-API").toString() << "API";
|
||||
#endif
|
||||
if (isContainment) {
|
||||
return new Containment(0, allArgs);
|
||||
} else {
|
||||
if (offer->serviceTypes().contains("Plasma/Containment")) {
|
||||
return new Containment(0, allArgs);
|
||||
} else {
|
||||
return new Applet(0, allArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KPluginLoader plugin(*offer);
|
||||
|
||||
if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
QString error;
|
||||
applet = offer->createInstance<Plasma::Applet>(0, allArgs, &error);
|
||||
|
||||
if (!applet) {
|
||||
kWarning() << "Could not load applet" << name << "! reason given:" << error;
|
||||
}
|
||||
|
||||
return applet;
|
||||
}
|
||||
|
||||
DataEngine *PluginLoader::loadDataEngine(const QString &name)
|
||||
{
|
||||
DataEngine *engine = d->isDefaultLoader ? 0 : internalLoadDataEngine(name);
|
||||
if (engine) {
|
||||
return engine;
|
||||
}
|
||||
|
||||
// load the engine, add it to the engines
|
||||
QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine",
|
||||
constraint);
|
||||
QString error;
|
||||
|
||||
if (offers.isEmpty()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "offers are empty for " << name << " with constraint " << constraint;
|
||||
#endif
|
||||
} else {
|
||||
QVariantList allArgs;
|
||||
allArgs << offers.first()->storageId();
|
||||
QString api = offers.first()->property("X-Plasma-API").toString();
|
||||
if (api.isEmpty()) {
|
||||
if (offers.first()) {
|
||||
KPluginLoader plugin(*offers.first());
|
||||
if (Plasma::isPluginVersionCompatible(plugin.pluginVersion())) {
|
||||
engine = offers.first()->createInstance<Plasma::DataEngine>(0, allArgs, &error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
engine = new DataEngine(0, offers.first());
|
||||
}
|
||||
}
|
||||
|
||||
if (!engine) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Couldn't load engine \"" << name << "\". Error given: " << error;
|
||||
#endif
|
||||
}
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
AbstractRunner *PluginLoader::loadRunner(const QString &name)
|
||||
{
|
||||
// FIXME: RunnerManager is all wrapped around runner loading; that should be sorted out
|
||||
// and the actual plugin loading added here
|
||||
return d->isDefaultLoader ? 0 : internalLoadRunner(name);
|
||||
}
|
||||
|
||||
Service *PluginLoader::loadService(const QString &name, const QVariantList &args, QObject *parent)
|
||||
{
|
||||
Service *service = d->isDefaultLoader ? 0 : internalLoadService(name, args, parent);
|
||||
if (service) {
|
||||
return service;
|
||||
}
|
||||
|
||||
//TODO: scripting API support
|
||||
if (name.isEmpty()) {
|
||||
return new NullService(QString(), parent);
|
||||
} else if (name == "org.kde.servicestorage") {
|
||||
return new Storage(parent);
|
||||
}
|
||||
|
||||
QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Service", constraint);
|
||||
|
||||
if (offers.isEmpty()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "offers is empty for " << name;
|
||||
#endif
|
||||
return new NullService(name, parent);
|
||||
}
|
||||
|
||||
KService::Ptr offer = offers.first();
|
||||
QString error;
|
||||
|
||||
if (Plasma::isPluginVersionCompatible(KPluginLoader(*offer).pluginVersion())) {
|
||||
service = offer->createInstance<Plasma::Service>(parent, args, &error);
|
||||
}
|
||||
|
||||
if (!service) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Couldn't load Service \"" << name << "\"! reason given: " << error;
|
||||
#endif
|
||||
return new NullService(name, parent);
|
||||
}
|
||||
|
||||
if (service->name().isEmpty()) {
|
||||
service->setName(name);
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
ContainmentActions *PluginLoader::loadContainmentActions(Containment *parent, const QString &name, const QVariantList &args)
|
||||
{
|
||||
if (name.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ContainmentActions *actions = d->isDefaultLoader ? 0 : internalLoadContainmentActions(parent, name, args);
|
||||
if (actions) {
|
||||
return actions;
|
||||
}
|
||||
|
||||
QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(name);
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/ContainmentActions", constraint);
|
||||
|
||||
if (offers.isEmpty()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "offers is empty for " << name;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
KService::Ptr offer = offers.first();
|
||||
KPluginLoader plugin(*offer);
|
||||
|
||||
if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion())) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
QVariantList allArgs;
|
||||
allArgs << offer->storageId() << args;
|
||||
QString error;
|
||||
actions = offer->createInstance<Plasma::ContainmentActions>(parent, allArgs, &error);
|
||||
|
||||
if (!actions) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Couldn't load containmentActions \"" << name << "\"! reason given: " << error;
|
||||
#endif
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
Package PluginLoader::loadPackage(const QString &packageFormat, const QString &specialization)
|
||||
{
|
||||
if (!d->isDefaultLoader) {
|
||||
Package p = internalLoadPackage(packageFormat, specialization);
|
||||
if (p.isValid()) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
if (packageFormat.isEmpty()) {
|
||||
return Package();
|
||||
}
|
||||
|
||||
const QString hashkey = packageFormat + '%' + specialization;
|
||||
PackageStructure *structure = d->structures.value(hashkey).data();
|
||||
if (structure) {
|
||||
return Package(structure);
|
||||
}
|
||||
|
||||
if (!specialization.isEmpty()) {
|
||||
QRegExp re("[^a-zA-Z0-9\\-_]");
|
||||
// check that the provided strings are safe to use in a ServiceType query
|
||||
if (re.indexIn(specialization) == -1 && re.indexIn(packageFormat) == -1) {
|
||||
// FIXME: The query below is rather spepcific to script engines. generify if possible
|
||||
const QString component = packageFormat.right(packageFormat.size() - packageFormat.lastIndexOf('/') - 1);
|
||||
const QString constraint = QString("[X-Plasma-API] == '%1' and " "'%2' in [X-Plasma-ComponentTypes]").arg(specialization, component);
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/ScriptEngine", constraint);
|
||||
|
||||
if (!offers.isEmpty()) {
|
||||
KService::Ptr offer = offers.first();
|
||||
QString packageFormat = offer->property("X-Plasma-PackageFormat").toString();
|
||||
if (!packageFormat.isEmpty()) {
|
||||
return loadPackage(packageFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (packageFormat.startsWith("Plasma")) {
|
||||
if (packageFormat.endsWith("/Applet")) {
|
||||
structure = new PlasmoidPackage();
|
||||
} else if (packageFormat.endsWith("/DataEngine")) {
|
||||
structure = new DataEnginePackage();
|
||||
} else if (packageFormat.endsWith("/Runner")) {
|
||||
structure = new RunnerPackage();
|
||||
} else if (packageFormat.endsWith("/Theme")) {
|
||||
structure = new ThemePackage();
|
||||
} else if (packageFormat.endsWith("/ContainmentActions")) {
|
||||
structure = new ContainmentActionsPackage();
|
||||
} else if (packageFormat.endsWith("/Generic")) {
|
||||
structure = new GenericPackage();
|
||||
}
|
||||
|
||||
if (structure) {
|
||||
d->structures.insert(hashkey, structure);
|
||||
return Package(structure);
|
||||
}
|
||||
}
|
||||
|
||||
// first we check for plugins in sycoca
|
||||
QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(packageFormat);
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/PackageStructure", constraint);
|
||||
|
||||
QVariantList args;
|
||||
QString error;
|
||||
foreach (const KService::Ptr &offer, offers) {
|
||||
structure = qobject_cast<PackageStructure *>(offer->createInstance<PackageStructure>(0, args, &error));
|
||||
|
||||
if (structure) {
|
||||
d->structures.insert(hashkey, structure);
|
||||
return Package(structure);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Couldn't load Package for" << packageFormat << "! reason given: " << error;
|
||||
#endif
|
||||
}
|
||||
|
||||
return Package();
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::listAppletInfo(const QString &category, const QString &parentApp)
|
||||
{
|
||||
KPluginInfo::List list;
|
||||
|
||||
if (!d->isDefaultLoader && (parentApp.isEmpty() || parentApp == QCoreApplication::instance()->applicationName())) {
|
||||
list = internalAppletInfo(category);
|
||||
}
|
||||
|
||||
QString constraint = AppletPrivate::parentAppConstraint(parentApp);
|
||||
|
||||
//note: constraint guaranteed non-empty from here down
|
||||
if (category.isEmpty()) { //use all but the excluded categories
|
||||
KConfigGroup group(KSharedConfig::openConfig(), "General");
|
||||
QStringList excluded = group.readEntry("ExcludeCategories", QStringList());
|
||||
foreach (const QString &category, excluded) {
|
||||
constraint.append(" and [X-KDE-PluginInfo-Category] != '").append(category).append("'");
|
||||
}
|
||||
} else { //specific category (this could be an excluded one - is that bad?)
|
||||
constraint.append(" and ").append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
|
||||
if (category == "Miscellaneous") {
|
||||
constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
|
||||
}
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
|
||||
|
||||
//now we have to do some manual filtering because the constraint can't handle everything
|
||||
AppletPrivate::filterOffers(offers);
|
||||
|
||||
//kDebug() << "Applet::listAppletInfo constraint was '" << constraint
|
||||
// << "' which got us " << offers.count() << " matches";
|
||||
return KPluginInfo::fromServices(offers);
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::listDataEngineInfo(const QString &parentApp)
|
||||
{
|
||||
KPluginInfo::List list;
|
||||
|
||||
if (!d->isDefaultLoader && (parentApp.isEmpty() || parentApp == QCoreApplication::instance()->applicationName())) {
|
||||
list = internalDataEngineInfo();
|
||||
}
|
||||
|
||||
QString constraint;
|
||||
if (parentApp.isEmpty()) {
|
||||
constraint.append("not exist [X-KDE-ParentApp]");
|
||||
} else {
|
||||
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/DataEngine", constraint);
|
||||
return list + KPluginInfo::fromServices(offers);
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::listRunnerInfo(const QString &parentApp)
|
||||
{
|
||||
KPluginInfo::List list;
|
||||
|
||||
if (!d->isDefaultLoader && (parentApp.isEmpty() || parentApp == QCoreApplication::instance()->applicationName())) {
|
||||
list = internalRunnerInfo();
|
||||
}
|
||||
|
||||
QString constraint;
|
||||
if (parentApp.isEmpty()) {
|
||||
constraint.append("not exist [X-KDE-ParentApp]");
|
||||
} else {
|
||||
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/Runner", constraint);
|
||||
return list + KPluginInfo::fromServices(offers);
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::listContainmentActionsInfo(const QString &parentApp)
|
||||
{
|
||||
KPluginInfo::List list;
|
||||
|
||||
if (!d->isDefaultLoader && (parentApp.isEmpty() || parentApp == QCoreApplication::instance()->applicationName())) {
|
||||
list = internalContainmentActionsInfo();
|
||||
}
|
||||
|
||||
QString constraint;
|
||||
if (parentApp.isEmpty()) {
|
||||
constraint.append("not exist [X-KDE-ParentApp]");
|
||||
} else {
|
||||
constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
|
||||
}
|
||||
|
||||
KService::List offers = KServiceTypeTrader::self()->query("Plasma/ContainmentActions", constraint);
|
||||
return KPluginInfo::fromServices(offers);
|
||||
}
|
||||
|
||||
Applet* PluginLoader::internalLoadApplet(const QString &name, uint appletId, const QVariantList &args)
|
||||
{
|
||||
Q_UNUSED(name)
|
||||
Q_UNUSED(appletId)
|
||||
Q_UNUSED(args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataEngine *PluginLoader::internalLoadDataEngine(const QString &name)
|
||||
{
|
||||
Q_UNUSED(name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
AbstractRunner *PluginLoader::internalLoadRunner(const QString &name)
|
||||
{
|
||||
Q_UNUSED(name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ContainmentActions *PluginLoader::internalLoadContainmentActions(Containment *containment, const QString &name, const QVariantList &args)
|
||||
{
|
||||
Q_UNUSED(containment)
|
||||
Q_UNUSED(name)
|
||||
Q_UNUSED(args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Service *PluginLoader::internalLoadService(const QString &name, const QVariantList &args, QObject *parent)
|
||||
{
|
||||
Q_UNUSED(name)
|
||||
Q_UNUSED(args)
|
||||
Q_UNUSED(parent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Package PluginLoader::internalLoadPackage(const QString &name, const QString &specialization)
|
||||
{
|
||||
Q_UNUSED(name);
|
||||
Q_UNUSED(specialization);
|
||||
return Package();
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::internalAppletInfo(const QString &category) const
|
||||
{
|
||||
Q_UNUSED(category)
|
||||
return KPluginInfo::List();
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::internalDataEngineInfo() const
|
||||
{
|
||||
return KPluginInfo::List();
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::internalRunnerInfo() const
|
||||
{
|
||||
return KPluginInfo::List();
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::internalServiceInfo() const
|
||||
{
|
||||
return KPluginInfo::List();
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::internalContainmentActionsInfo() const
|
||||
{
|
||||
return KPluginInfo::List();
|
||||
}
|
||||
|
||||
static KPluginInfo::List standardInternalInfo(const QString &type, const QString &category = QString())
|
||||
{
|
||||
QStringList files = KGlobal::dirs()->findAllResources("appdata", "plasma/internal/" + type + "/*.desktop", KStandardDirs::NoDuplicates);
|
||||
|
||||
KPluginInfo::List allInfo = KPluginInfo::fromFiles(files);
|
||||
|
||||
if (category.isEmpty() || allInfo.isEmpty()) {
|
||||
return allInfo;
|
||||
}
|
||||
|
||||
KPluginInfo::List matchingInfo;
|
||||
foreach (const KPluginInfo &info, allInfo) {
|
||||
if (info.category().compare(category, Qt::CaseInsensitive) == 0) {
|
||||
matchingInfo << info;
|
||||
}
|
||||
}
|
||||
|
||||
return matchingInfo;
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::standardInternalAppletInfo(const QString &category) const
|
||||
{
|
||||
return standardInternalInfo("applets", category);
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::standardInternalDataEngineInfo() const
|
||||
{
|
||||
return standardInternalInfo("dataengines");
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::standardInternalRunnerInfo() const
|
||||
{
|
||||
return standardInternalInfo("runners");
|
||||
}
|
||||
|
||||
KPluginInfo::List PluginLoader::standardInternalServiceInfo() const
|
||||
{
|
||||
return standardInternalInfo("services");
|
||||
}
|
||||
|
||||
} // Plasma Namespace
|
||||
|
386
plasma/pluginloader.h
Normal file
386
plasma/pluginloader.h
Normal file
@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright 2010 by Ryan Rix <ry@n.rix.si>
|
||||
*
|
||||
* 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 PLUGIN_LOADER_H
|
||||
#define PLUGIN_LOADER_H
|
||||
|
||||
#include <plasma/package.h>
|
||||
#include <plasma/plasma.h>
|
||||
#include <kplugininfo.h>
|
||||
|
||||
namespace Plasma {
|
||||
|
||||
class AbstractRunner;
|
||||
class Applet;
|
||||
class Containment;
|
||||
class ContainmentActions;
|
||||
class DataEngine;
|
||||
class Service;
|
||||
|
||||
class PluginLoaderPrivate;
|
||||
|
||||
//TODO:
|
||||
// * add loadWallpaper
|
||||
// * add KPluginInfo listing support for Containments (already loaded via the applet loading code)
|
||||
|
||||
/**
|
||||
* This is an abstract base class which defines an interface to which Plasma's
|
||||
* Applet Loading logic can communicate with a parent application. The plugin loader
|
||||
* must be set before any plugins are loaded, otherwise (for safety reasons), the
|
||||
* default PluginLoader implementation will be used. The reimplemented version should
|
||||
* not do more than simply returning a loaded plugin. It should not init() it, and it should not
|
||||
* hang on to it. The associated methods will be called only when a component of Plasma
|
||||
* needs to load a _new_ plugin. (e.g. DataEngine does its own caching).
|
||||
*
|
||||
* @author Ryan Rix <ry@n.rix.si>
|
||||
* @since 4.6
|
||||
**/
|
||||
class PLASMA_EXPORT PluginLoader
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Load an Applet plugin.
|
||||
*
|
||||
* @param name the plugin name, as returned by KPluginInfo::pluginName()
|
||||
* @param appletId unique ID to assign the applet, or zero to have one
|
||||
* assigned automatically.
|
||||
* @param args to send the applet extra arguments
|
||||
* @return a pointer to the loaded applet, or 0 on load failure
|
||||
**/
|
||||
Applet *loadApplet(const QString &name, uint appletId = 0,
|
||||
const QVariantList &args = QVariantList());
|
||||
|
||||
/**
|
||||
* Load a DataEngine plugin.
|
||||
*
|
||||
* @param name the name of the engine
|
||||
* @return the DataEngine that was loaded, or the NullEngine on failure.
|
||||
**/
|
||||
DataEngine *loadDataEngine(const QString &name);
|
||||
|
||||
/**
|
||||
* Load a Runner plugin
|
||||
*
|
||||
* @return the Runner that was loaded, or 0 on failure.
|
||||
*/
|
||||
AbstractRunner *loadRunner(const QString &name);
|
||||
|
||||
/**
|
||||
* Load a Service plugin.
|
||||
*
|
||||
* @param name the plugin name of the service to load
|
||||
* @param args a list of arguments to supply to the service plugin when loading it
|
||||
* @param parent the parent object, if any, for the service
|
||||
*
|
||||
* @return a Service object, unlike Plasma::Service::loadService, this can return null.
|
||||
**/
|
||||
Service *loadService(const QString &name, const QVariantList &args, QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* Load a ContainmentActions plugin.
|
||||
*
|
||||
* Returns a pointer to the containmentactions if successful.
|
||||
* The caller takes responsibility for the containmentactions, including
|
||||
* deleting it when no longer needed.
|
||||
*
|
||||
* @param parent the parent containment. @since 4.6 null is allowed.
|
||||
* @param name the plugin name, as returned by KPluginInfo::pluginName()
|
||||
* @param args to send the containmentactions extra arguments
|
||||
* @return a ContaimentActions object
|
||||
**/
|
||||
ContainmentActions *loadContainmentActions(Containment *parent, const QString &containmentActionsName,
|
||||
const QVariantList &args = QVariantList());
|
||||
|
||||
/**
|
||||
* Load a Package plugin.
|
||||
*
|
||||
* @param name the plugin name of the package to load
|
||||
* @param specialization used to find script extensions for the given format, e.g. "QML" for "Plasma/Applet"
|
||||
*
|
||||
* @return a Package object matching name, or an invalid package on failure
|
||||
**/
|
||||
Package loadPackage(const QString &packageFormat, const QString &specialization = QString());
|
||||
|
||||
/**
|
||||
* Returns a list of all known applets.
|
||||
* This may skip applets based on security settings and ExcludeCategories in the application's config.
|
||||
*
|
||||
* @param category Only applets matchin this category will be returned.
|
||||
* Useful in conjunction with knownCategories.
|
||||
* If "Misc" is passed in, then applets without a
|
||||
* Categories= entry are also returned.
|
||||
* If an empty string is passed in, all applets are
|
||||
* returned.
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of applets
|
||||
**/
|
||||
KPluginInfo::List listAppletInfo(const QString &category, const QString &parentApp = QString());
|
||||
|
||||
/**
|
||||
* Returns a list of all known DataEngines.
|
||||
*
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of DataEngines
|
||||
**/
|
||||
KPluginInfo::List listDataEngineInfo(const QString &parentApp = QString());
|
||||
|
||||
/**
|
||||
* Returns a list of all known Runner implementations
|
||||
*
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of AbstractRunners
|
||||
**/
|
||||
KPluginInfo::List listRunnerInfo(const QString &parentApp = QString());
|
||||
|
||||
/**
|
||||
* Returns a list of all known ContainmentActions.
|
||||
*
|
||||
* @param parentApp the application to filter applets on. Uses the
|
||||
* X-KDE-ParentApp entry (if any) in the plugin info.
|
||||
* The default value of QString() will result in a
|
||||
* list containing only applets not specifically
|
||||
* registered to an application.
|
||||
* @return list of applets
|
||||
**/
|
||||
KPluginInfo::List listContainmentActionsInfo(const QString &parentApp);
|
||||
|
||||
/**
|
||||
* Set the plugin loader which will be queried for all loads.
|
||||
*
|
||||
* @param loader A subclass of PluginLoader which will be supplied
|
||||
* by the application
|
||||
**/
|
||||
static void setPluginLoader(PluginLoader* loader);
|
||||
|
||||
/**
|
||||
* Return the active plugin loader
|
||||
**/
|
||||
static PluginLoader *self();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A re-implementable method that allows subclasses to override
|
||||
* the default behaviour of loadApplet. If the applet requested is not recognized,
|
||||
* then the implementation should return a NULL pointer. This method is called
|
||||
* by loadApplet prior to attempting to load an applet using the standard Plasma
|
||||
* plugin mechanisms.
|
||||
*
|
||||
* @param name the plugin name, as returned by KPluginInfo::pluginName()
|
||||
* @param appletId unique ID to assign the applet, or zero to have one
|
||||
* assigned automatically.
|
||||
* @param args to send the applet extra arguments
|
||||
* @return a pointer to the loaded applet, or 0 on load failure
|
||||
**/
|
||||
virtual Applet *internalLoadApplet(const QString &name, uint appletId = 0,
|
||||
const QVariantList &args = QVariantList());
|
||||
|
||||
/**
|
||||
* A re-implementable method that allows subclasses to override
|
||||
* the default behaviour of loadRunner. If the runner requested is not recognized,
|
||||
* then the implementation should return a NULL pointer. This method is called
|
||||
* by loadRunner prior to attempting to load a DataEgine using the standard Plasma
|
||||
* plugin mechanisms.
|
||||
*
|
||||
* @param name the name of the engine
|
||||
* @return the data engine that was loaded, or the NullEngine on failure.
|
||||
**/
|
||||
virtual AbstractRunner *internalLoadRunner(const QString &name);
|
||||
|
||||
/**
|
||||
* A re-implementable method that allows subclasses to override
|
||||
* the default behaviour of loadDataEngine. If the engine requested is not recognized,
|
||||
* then the implementation should return a NULL pointer. This method is called
|
||||
* by loadDataEngine prior to attempting to load a DataEgine using the standard Plasma
|
||||
* plugin mechanisms.
|
||||
*
|
||||
* @param name the name of the engine
|
||||
* @return the data engine that was loaded, or the NullEngine on failure.
|
||||
**/
|
||||
virtual DataEngine *internalLoadDataEngine(const QString &name);
|
||||
|
||||
/**
|
||||
* A re-implementable method that allows subclasses to override
|
||||
* the default behaviour of loadService. If the service requested is not recognized,
|
||||
* then the implementation should return a NULL pointer. This method is called
|
||||
* by loadService prior to attempting to load a Service using the standard Plasma
|
||||
* plugin mechanisms.
|
||||
*
|
||||
* @param name the plugin name of the service to load
|
||||
* @param args a list of arguments to supply to the service plugin when loading it
|
||||
* @param parent the parent object, if any, for the service
|
||||
*
|
||||
* @return a Service object, unlike Plasma::Service::loadService, this can return null.
|
||||
**/
|
||||
virtual Service *internalLoadService(const QString &name, const QVariantList &args, QObject *parent = 0);
|
||||
|
||||
/**
|
||||
* A re-implementable method that allows subclasses to override
|
||||
* the default behaviour of loadContainmentActions. If the Containments Action requested is not recognized,
|
||||
* then the implementation should return a NULL pointer. This method is called
|
||||
* by loadService prior to attempting to load a Service using the standard Plasma
|
||||
* plugin mechanisms.
|
||||
*
|
||||
* Returns a pointer to the containmentactions if successful.
|
||||
* The caller takes responsibility for the containmentactions, including
|
||||
* deleting it when no longer needed.
|
||||
*
|
||||
* @param parent the parent containment. @since 4.6 null is allowed.
|
||||
* @param name the plugin name, as returned by KPluginInfo::pluginName()
|
||||
* @param args to send the containmentactions extra arguments
|
||||
* @return a ContaimentActions object
|
||||
**/
|
||||
virtual ContainmentActions *internalLoadContainmentActions(Containment *parent, const QString &containmentActionsName, const QVariantList &args);
|
||||
|
||||
/**
|
||||
* A re-implementable method that allows subclasses to override
|
||||
* the default behaviour of loadPackage. If the service requested is not recognized,
|
||||
* then the implementation should return a NULL pointer. This method is called
|
||||
* by loadService prior to attempting to load a Service using the standard Plasma
|
||||
* plugin mechanisms.
|
||||
*
|
||||
* @param name the plugin name of the service to load
|
||||
* @param args a list of arguments to supply to the service plugin when loading it
|
||||
* @param parent the parent object, if any, for the service
|
||||
*
|
||||
* @return a Service object, unlike Plasma::Service::loadService, this can return null.
|
||||
**/
|
||||
virtual Package internalLoadPackage(const QString &name, const QString &specialization);
|
||||
|
||||
/**
|
||||
* A re-implementable method that allows subclasses to provide additional applets
|
||||
* for listAppletInfo. If the application has no applets to give to the application,
|
||||
* then the implementation should return an empty list.
|
||||
*
|
||||
* This method is called by listAppletInfo prior to generating the list of applets installed
|
||||
* on the system using the standard Plasma plugin mechanisms, and will try to find .desktop
|
||||
* files for your applets.
|
||||
*
|
||||
* @param category Only applets matching this category will be returned.
|
||||
* Useful in conjunction with knownCategories.
|
||||
* If "Misc" is passed in, then applets without a
|
||||
* Categories= entry are also returned.
|
||||
* If an empty string is passed in, all applets are
|
||||
* returned.
|
||||
* @return list of applets
|
||||
**/
|
||||
virtual KPluginInfo::List internalAppletInfo(const QString &category) const;
|
||||
|
||||
/**
|
||||
* A re-implementable method that allows subclasses to provide additional DataEngines
|
||||
* for DataEngine::listDataEngines.
|
||||
*
|
||||
* @return list of DataEngines info, or an empty list if none
|
||||
**/
|
||||
virtual KPluginInfo::List internalDataEngineInfo() const;
|
||||
|
||||
/**
|
||||
* Returns a list of all known Runner implementations
|
||||
*
|
||||
* @return list of AbstractRunners info, or an empty list if none
|
||||
*/
|
||||
virtual KPluginInfo::List internalRunnerInfo() const;
|
||||
|
||||
/**
|
||||
* Returns a list of all known Runner implementations
|
||||
*
|
||||
* @return list of AbstractRunners info, or an empty list if none
|
||||
*/
|
||||
virtual KPluginInfo::List internalServiceInfo() const;
|
||||
|
||||
/**
|
||||
* Returns a list of all known Runner implementations
|
||||
*
|
||||
* @return list of ContainmentActions info, or an empty list if none
|
||||
*/
|
||||
virtual KPluginInfo::List internalContainmentActionsInfo() const;
|
||||
|
||||
/**
|
||||
* Standardized mechanism for providing internal Applets by install .desktop files
|
||||
* in $APPPDATA/plasma/internal/applets/
|
||||
*
|
||||
* For applications that do this, internalAppletInfo can be implemented as a one-liner
|
||||
* call to this method.
|
||||
*
|
||||
* @param category Only applets matching this category will be returned.
|
||||
* Useful in conjunction with knownCategories.
|
||||
* If "Misc" is passed in, then applets without a
|
||||
* Categories= entry are also returned.
|
||||
* If an empty string is passed in, all applets are
|
||||
* returned.
|
||||
* @return list of Applets, or an empty list if none
|
||||
*/
|
||||
KPluginInfo::List standardInternalAppletInfo(const QString &category) const;
|
||||
|
||||
/**
|
||||
* Standardized mechanism for providing internal Applets by install .desktop files
|
||||
* in $APPPDATA/plasma/internal/dataengines/
|
||||
*
|
||||
* For applications that do this, internalDataEngineInfo can be implemented as a one-liner
|
||||
* call to this method.
|
||||
*
|
||||
* @return list of applets
|
||||
*/
|
||||
KPluginInfo::List standardInternalDataEngineInfo() const;
|
||||
|
||||
/**
|
||||
* Standardized mechanism for providing internal Applets by install .desktop files
|
||||
* in $APPPDATA/plasma/internal/runners/
|
||||
*
|
||||
* For applications that do this, internalRunnerInfo can be implemented as a one-liner
|
||||
* call to this method.
|
||||
*
|
||||
* @return list of applets
|
||||
*/
|
||||
KPluginInfo::List standardInternalRunnerInfo() const;
|
||||
|
||||
/**
|
||||
* Standardized mechanism for providing internal Applets by install .desktop files
|
||||
* in $APPPDATA/plasma/internal/services/
|
||||
*
|
||||
* For applications that do this, internalRunnerInfo can be implemented as a one-liner
|
||||
* call to this method.
|
||||
*
|
||||
* @return list of applets
|
||||
*/
|
||||
KPluginInfo::List standardInternalServiceInfo() const;
|
||||
|
||||
PluginLoader();
|
||||
virtual ~PluginLoader();
|
||||
|
||||
private:
|
||||
PluginLoaderPrivate * const d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(Plasma::PluginLoader*)
|
||||
|
||||
#endif
|
61
plasma/private/abstractrunner_p.h
Normal file
61
plasma/private/abstractrunner_p.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2006-2009 Aaron Seigo <aseigo@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 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 ABSTRACTRUNNER_P_H
|
||||
#define ABSTRACTRUNNER_P_H
|
||||
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include "dataengineconsumer.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AbstractRunner;
|
||||
|
||||
class AbstractRunnerPrivate : public DataEngineConsumer
|
||||
{
|
||||
public:
|
||||
AbstractRunnerPrivate(AbstractRunner *r);
|
||||
~AbstractRunnerPrivate();
|
||||
void init(const KService::Ptr service);
|
||||
void init(const QString &path);
|
||||
void prepScripting(const QString &path, const QString &api);
|
||||
void setupScriptSupport();
|
||||
|
||||
AbstractRunner::Priority priority;
|
||||
AbstractRunner::Speed speed;
|
||||
RunnerContext::Types blackListed;
|
||||
RunnerScript *script;
|
||||
KPluginInfo runnerDescription;
|
||||
AbstractRunner *runner;
|
||||
int fastRuns;
|
||||
QReadWriteLock speedLock;
|
||||
Package *package;
|
||||
QHash<QString, QAction*> actions;
|
||||
QList<RunnerSyntax> syntaxes;
|
||||
RunnerSyntax *defaultSyntax;
|
||||
bool hasRunOptions : 1;
|
||||
bool suspendMatching : 1;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
#endif
|
||||
|
||||
|
54
plasma/private/accessmanager_p.h
Normal file
54
plasma/private/accessmanager_p.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2009 by Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ACCESSMANAGER_P_H
|
||||
#define ACCESSMANAGER_P_H
|
||||
|
||||
#include <dnssd/remoteservice.h>
|
||||
|
||||
#include "../remote/accessmanager.h"
|
||||
|
||||
class KJob;
|
||||
|
||||
namespace DNSSD
|
||||
{
|
||||
class ServiceBrowser;
|
||||
}
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AccessManagerPrivate
|
||||
{
|
||||
public:
|
||||
AccessManagerPrivate(AccessManager *manager);
|
||||
~AccessManagerPrivate();
|
||||
void slotJobFinished(KJob *job);
|
||||
void slotAddService(DNSSD::RemoteService::Ptr service);
|
||||
void slotRemoveService(DNSSD::RemoteService::Ptr service);
|
||||
|
||||
AccessManager *q;
|
||||
DNSSD::ServiceBrowser *browser;
|
||||
QMap<QString, RemoteObjectDescription> services;
|
||||
QMap<QString, DNSSD::RemoteService::Ptr> zeroconfServices;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
100
plasma/private/actionwidgetinterface_p.h
Normal file
100
plasma/private/actionwidgetinterface_p.h
Normal file
@ -0,0 +1,100 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2009 by Aaron Seigo <aseigo@kde.org> *
|
||||
* *
|
||||
* This library 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 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 library; see the file COPYING.LIB. If not, write to *
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
|
||||
* Boston, MA 02110-1301, USA. *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef ACTIONWIDGETINTERFACE_P_H
|
||||
#define ACTIONWIDGETINTERFACE_P_H
|
||||
|
||||
#include <QAction>
|
||||
|
||||
#include "private/themedwidgetinterface_p.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
template <class T>
|
||||
class ActionWidgetInterface : public ThemedWidgetInterface<T>
|
||||
{
|
||||
public:
|
||||
ActionWidgetInterface(T *parent)
|
||||
: ThemedWidgetInterface<T>(parent),
|
||||
action(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ActionWidgetInterface()
|
||||
{
|
||||
setAction(0);
|
||||
}
|
||||
|
||||
virtual void changed()
|
||||
{
|
||||
}
|
||||
|
||||
void clearAction()
|
||||
{
|
||||
action = 0;
|
||||
syncToAction();
|
||||
changed();
|
||||
}
|
||||
|
||||
void syncToAction()
|
||||
{
|
||||
if (!action) {
|
||||
this->q->setIcon(QIcon());
|
||||
this->q->setText(QString());
|
||||
this->q->setEnabled(false);
|
||||
return;
|
||||
}
|
||||
//we don't get told *what* changed, just that something changed
|
||||
//so we update everything we care about
|
||||
this->q->setIcon(action->icon());
|
||||
this->q->setText(action->iconText());
|
||||
this->q->setEnabled(action->isEnabled());
|
||||
this->q->setVisible(action->isVisible());
|
||||
|
||||
if (!this->q->toolTip().isEmpty()) {
|
||||
this->q->setToolTip(action->text());
|
||||
}
|
||||
|
||||
changed();
|
||||
}
|
||||
|
||||
void setAction(QAction *a)
|
||||
{
|
||||
if (action) {
|
||||
QObject::disconnect(action, 0, this->q, 0);
|
||||
QObject::disconnect(this->q, 0, action, 0);
|
||||
}
|
||||
|
||||
action = a;
|
||||
|
||||
if (action) {
|
||||
QObject::connect(action, SIGNAL(changed()), this->q, SLOT(syncToAction()));
|
||||
QObject::connect(action, SIGNAL(destroyed(QObject*)), this->q, SLOT(clearAction()));
|
||||
QObject::connect(this->q, SIGNAL(clicked()), action, SLOT(trigger()));
|
||||
syncToAction();
|
||||
}
|
||||
}
|
||||
|
||||
QAction *action;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
#endif
|
||||
|
719
plasma/private/applet_p.cpp
Normal file
719
plasma/private/applet_p.cpp
Normal file
@ -0,0 +1,719 @@
|
||||
/*
|
||||
* Copyright 2005 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
* Copyright (c) 2009 Chani Armitage <chani@kde.org>
|
||||
* Copyright 2012 by 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 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 "private/applet_p.h"
|
||||
|
||||
#include <config-plasma.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QHostInfo>
|
||||
#include <qstandardpaths.h>
|
||||
|
||||
#include <kaction.h>
|
||||
#include <kdebug.h>
|
||||
#include <kiconloader.h>
|
||||
#include <klocale.h>
|
||||
#include <kkeysequencewidget.h>
|
||||
#include <kstandarddirs.h>
|
||||
#include <kglobal.h>
|
||||
|
||||
#include "containment.h"
|
||||
#include "corona.h"
|
||||
#include "pluginloader.h"
|
||||
#include "scripting/scriptengine.h"
|
||||
#include "scripting/appletscript.h"
|
||||
#include "private/containment_p.h"
|
||||
|
||||
#if ENABLE_REMOTE_WIDGETS
|
||||
#include "remote/authorizationmanager.h"
|
||||
#include "remote/authorizationmanager_p.h"
|
||||
#include "remote/authorizationrule.h"
|
||||
#endif
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
AppletPrivate::AppletPrivate(KService::Ptr service, const KPluginInfo *info, int uniqueID, Applet *applet)
|
||||
: appletId(uniqueID),
|
||||
q(applet),
|
||||
remotingService(0),
|
||||
backgroundHints(StandardBackground),
|
||||
aspectRatioMode(Plasma::KeepAspectRatio),
|
||||
immutability(Mutable),
|
||||
appletDescription(info ? *info : KPluginInfo(service)),
|
||||
mainConfig(0),
|
||||
pendingConstraints(NoConstraint),
|
||||
script(0),
|
||||
package(0),
|
||||
configLoader(0),
|
||||
actions(AppletPrivate::defaultActions(applet)),
|
||||
activationAction(0),
|
||||
itemStatus(UnknownStatus),
|
||||
preferredSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored),
|
||||
modificationsTimer(0),
|
||||
hasConfigurationInterface(false),
|
||||
failed(false),
|
||||
isContainment(false),
|
||||
transient(false),
|
||||
needsConfig(false),
|
||||
started(false)
|
||||
{
|
||||
if (appletId == 0) {
|
||||
appletId = ++s_maxAppletId;
|
||||
} else if (appletId > s_maxAppletId) {
|
||||
s_maxAppletId = appletId;
|
||||
}
|
||||
}
|
||||
|
||||
AppletPrivate::~AppletPrivate()
|
||||
{
|
||||
if (activationAction && activationAction->isGlobalShortcutEnabled()) {
|
||||
//kDebug() << "reseting global action for" << q->name() << activationAction->objectName();
|
||||
activationAction->forgetGlobalShortcut();
|
||||
}
|
||||
|
||||
delete script;
|
||||
script = 0;
|
||||
delete package;
|
||||
package = 0;
|
||||
delete configLoader;
|
||||
configLoader = 0;
|
||||
delete mainConfig;
|
||||
mainConfig = 0;
|
||||
delete modificationsTimer;
|
||||
}
|
||||
|
||||
void AppletPrivate::init(const QString &packagePath)
|
||||
{
|
||||
// WARNING: do not access config() OR globalConfig() in this method!
|
||||
// that requires a scene, which is not available at this point
|
||||
|
||||
//set a default size before any saved settings are read
|
||||
QSize size(200, 200);
|
||||
q->setBackgroundHints(DefaultBackground);
|
||||
q->setHasConfigurationInterface(true); //FIXME why not default it to true in the constructor?
|
||||
|
||||
QAction *closeApplet = actions->action("remove");
|
||||
if (closeApplet) {
|
||||
closeApplet->setText(i18nc("%1 is the name of the applet", "Remove this %1", q->name()));
|
||||
}
|
||||
|
||||
QAction *configAction = actions->action("configure");
|
||||
if (configAction) {
|
||||
configAction->setText(i18nc("%1 is the name of the applet", "%1 Settings", q->name()));
|
||||
}
|
||||
|
||||
QObject::connect(q, SIGNAL(activate()), q, SLOT(setFocus()));
|
||||
if (!appletDescription.isValid()) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Check your constructor! "
|
||||
<< "You probably want to be passing in a Service::Ptr "
|
||||
<< "or a QVariantList with a valid storageid as arg[0].";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
QVariant s = appletDescription.property("X-Plasma-DefaultSize");
|
||||
if (s.isValid()) {
|
||||
size = s.toSize();
|
||||
}
|
||||
//kDebug() << "size" << size;
|
||||
|
||||
QString api = appletDescription.property("X-Plasma-API").toString();
|
||||
|
||||
// we have a scripted plasmoid
|
||||
if (api.isEmpty()) {
|
||||
q->setFailedToLaunch(true, i18n("The %2 widget did not define which ScriptEngine to use.", appletDescription.name()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
package = new Package(PluginLoader::self()->loadPackage("Plasma/Applet", api));
|
||||
|
||||
// find where the Package is
|
||||
QString path = packagePath;
|
||||
if (path.isEmpty()) {
|
||||
const QString subPath = package->defaultPackageRoot() + appletDescription.pluginName() + '/';
|
||||
path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, subPath + "metadata.desktop");
|
||||
if (path.isEmpty()) {
|
||||
path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, subPath);
|
||||
} else {
|
||||
path.remove(QString("metadata.desktop"));
|
||||
}
|
||||
} else if (!path.endsWith('/')) {
|
||||
path.append('/');
|
||||
}
|
||||
|
||||
if (path.isEmpty()) {
|
||||
delete package;
|
||||
package = 0;
|
||||
q->setFailedToLaunch(true,
|
||||
i18nc("Package file, name of the widget",
|
||||
"Could not locate the %1 package required for the %2 widget.",
|
||||
appletDescription.pluginName(), appletDescription.name()));
|
||||
return;
|
||||
}
|
||||
|
||||
package->setPath(path);
|
||||
if (!package->isValid()) {
|
||||
delete package;
|
||||
package = 0;
|
||||
q->setFailedToLaunch(true, i18nc("Package file, name of the widget",
|
||||
"Could not open the %1 package required for the %2 widget.",
|
||||
appletDescription.pluginName(), appletDescription.name()));
|
||||
return;
|
||||
}
|
||||
|
||||
// create the package and see if we have something real
|
||||
//kDebug() << "trying for" << path;
|
||||
|
||||
// now we try and set up the script engine.
|
||||
// it will be parented to this applet and so will get
|
||||
// deleted when the applet does
|
||||
|
||||
script = Plasma::loadScriptEngine(api, q);
|
||||
if (!script) {
|
||||
delete package;
|
||||
package = 0;
|
||||
q->setFailedToLaunch(true,
|
||||
i18nc("API or programming language the widget was written in, name of the widget",
|
||||
"Could not create a %1 ScriptEngine for the %2 widget.",
|
||||
api, appletDescription.name()));
|
||||
}
|
||||
}
|
||||
|
||||
void AppletPrivate::cleanUpAndDelete()
|
||||
{
|
||||
// reimplemented in the UI specific library
|
||||
}
|
||||
|
||||
void AppletPrivate::showConfigurationRequiredMessage(bool show, const QString &reason)
|
||||
{
|
||||
// reimplemented in the UI specific library
|
||||
Q_UNUSED(show)
|
||||
Q_UNUSED(reason)
|
||||
}
|
||||
|
||||
void AppletPrivate::showMessage(const QIcon &icon, const QString &message, const MessageButtons buttons)
|
||||
{
|
||||
// reimplemented in the UI specific library
|
||||
Q_UNUSED(icon)
|
||||
Q_UNUSED(message)
|
||||
Q_UNUSED(buttons)
|
||||
}
|
||||
|
||||
void AppletPrivate::positionMessageOverlay()
|
||||
{
|
||||
// reimplemented in the UI specific library
|
||||
}
|
||||
|
||||
void AppletPrivate::setBusy(bool busy)
|
||||
{
|
||||
// reimplemented in the UI specific library
|
||||
Q_UNUSED(busy)
|
||||
}
|
||||
|
||||
bool AppletPrivate::isBusy() const
|
||||
{
|
||||
// reimplemented in the UI specific library
|
||||
return false;
|
||||
}
|
||||
|
||||
void AppletPrivate::updateFailedToLaunch(const QString &reason)
|
||||
{
|
||||
// reimplemented in the UI specific library
|
||||
Q_UNUSED(reason)
|
||||
}
|
||||
|
||||
void AppletPrivate::globalShortcutChanged()
|
||||
{
|
||||
if (!activationAction) {
|
||||
return;
|
||||
}
|
||||
|
||||
KConfigGroup shortcutConfig(mainConfigGroup(), "Shortcuts");
|
||||
shortcutConfig.writeEntry("global", activationAction->globalShortcut().toString());
|
||||
scheduleModificationNotification();
|
||||
//kDebug() << "after" << shortcut.primary() << d->activationAction->globalShortcut().primary();
|
||||
}
|
||||
|
||||
KActionCollection* AppletPrivate::defaultActions(QObject *parent)
|
||||
{
|
||||
KActionCollection *actions = new KActionCollection(parent);
|
||||
actions->setConfigGroup("Shortcuts-Applet");
|
||||
|
||||
KAction *configAction = actions->addAction("configure");
|
||||
configAction->setAutoRepeat(false);
|
||||
configAction->setText(i18n("Widget Settings"));
|
||||
configAction->setIcon(KDE::icon("configure"));
|
||||
configAction->setShortcut(KShortcut("alt+d, s"));
|
||||
configAction->setData(Containment::ConfigureTool);
|
||||
|
||||
KAction *closeApplet = actions->addAction("remove");
|
||||
closeApplet->setAutoRepeat(false);
|
||||
closeApplet->setText(i18n("Remove this Widget"));
|
||||
closeApplet->setIcon(KDE::icon("edit-delete"));
|
||||
closeApplet->setShortcut(KShortcut("alt+d, r"));
|
||||
closeApplet->setData(Containment::DestructiveTool);
|
||||
|
||||
KAction *runAssociatedApplication = actions->addAction("run associated application");
|
||||
runAssociatedApplication->setAutoRepeat(false);
|
||||
runAssociatedApplication->setText(i18n("Run the Associated Application"));
|
||||
runAssociatedApplication->setIcon(KDE::icon("system-run"));
|
||||
runAssociatedApplication->setShortcut(KShortcut("alt+d, t"));
|
||||
runAssociatedApplication->setVisible(false);
|
||||
runAssociatedApplication->setEnabled(false);
|
||||
runAssociatedApplication->setData(Containment::ControlTool);
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
QString AppletPrivate::configDialogId() const
|
||||
{
|
||||
return QString("%1settings%2").arg(appletId).arg(q->name());
|
||||
}
|
||||
|
||||
QString AppletPrivate::configWindowTitle() const
|
||||
{
|
||||
return i18nc("@title:window", "%1 Settings", q->name());
|
||||
}
|
||||
|
||||
QSet<QString> AppletPrivate::knownCategories()
|
||||
{
|
||||
// this is to trick the tranlsation tools into making the correct
|
||||
// strings for translation
|
||||
QSet<QString> categories = s_customCategories;
|
||||
categories << QString(I18N_NOOP("Accessibility")).toLower()
|
||||
<< QString(I18N_NOOP("Application Launchers")).toLower()
|
||||
<< QString(I18N_NOOP("Astronomy")).toLower()
|
||||
<< QString(I18N_NOOP("Date and Time")).toLower()
|
||||
<< QString(I18N_NOOP("Development Tools")).toLower()
|
||||
<< QString(I18N_NOOP("Education")).toLower()
|
||||
<< QString(I18N_NOOP("Environment and Weather")).toLower()
|
||||
<< QString(I18N_NOOP("Examples")).toLower()
|
||||
<< QString(I18N_NOOP("File System")).toLower()
|
||||
<< QString(I18N_NOOP("Fun and Games")).toLower()
|
||||
<< QString(I18N_NOOP("Graphics")).toLower()
|
||||
<< QString(I18N_NOOP("Language")).toLower()
|
||||
<< QString(I18N_NOOP("Mapping")).toLower()
|
||||
<< QString(I18N_NOOP("Miscellaneous")).toLower()
|
||||
<< QString(I18N_NOOP("Multimedia")).toLower()
|
||||
<< QString(I18N_NOOP("Online Services")).toLower()
|
||||
<< QString(I18N_NOOP("Productivity")).toLower()
|
||||
<< QString(I18N_NOOP("System Information")).toLower()
|
||||
<< QString(I18N_NOOP("Utilities")).toLower()
|
||||
<< QString(I18N_NOOP("Windows and Tasks")).toLower();
|
||||
return categories;
|
||||
}
|
||||
|
||||
KConfigDialog *AppletPrivate::generateGenericConfigDialog()
|
||||
{
|
||||
KConfigSkeleton *nullManager = new KConfigSkeleton(0);
|
||||
KConfigDialog *dialog = new AppletConfigDialog(0, configDialogId(), nullManager);
|
||||
nullManager->setParent(dialog);
|
||||
dialog->setFaceType(KPageDialog::Auto);
|
||||
dialog->setWindowTitle(configWindowTitle());
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
q->createConfigurationInterface(dialog);
|
||||
dialog->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel);
|
||||
QObject::connect(dialog->button(QDialogButtonBox::Apply), SIGNAL(clicked()), q, SLOT(configDialogFinished()));
|
||||
QObject::connect(dialog->button(QDialogButtonBox::Ok), SIGNAL(clicked()), q, SLOT(configDialogFinished()));
|
||||
return dialog;
|
||||
}
|
||||
|
||||
void AppletPrivate::addStandardConfigurationPages(KConfigDialog *dialog)
|
||||
{
|
||||
addGlobalShortcutsPage(dialog);
|
||||
addPublishPage(dialog);
|
||||
}
|
||||
|
||||
void AppletPrivate::addGlobalShortcutsPage(KConfigDialog *dialog)
|
||||
{
|
||||
#if !PLASMA_NO_GLOBAL_SHORTCUTS
|
||||
if (isContainment) {
|
||||
return;
|
||||
}
|
||||
|
||||
QWidget *page = new QWidget;
|
||||
QVBoxLayout *layout = new QVBoxLayout(page);
|
||||
|
||||
if (!shortcutEditor) {
|
||||
shortcutEditor = new KKeySequenceWidget(page);
|
||||
QObject::connect(shortcutEditor.data(), SIGNAL(keySequenceChanged(QKeySequence)), dialog, SLOT(settingsModified()));
|
||||
}
|
||||
|
||||
shortcutEditor.data()->setKeySequence(q->globalShortcut().primary());
|
||||
layout->addWidget(shortcutEditor.data());
|
||||
layout->addStretch();
|
||||
dialog->addPage(page, i18n("Keyboard Shortcut"), "preferences-desktop-keyboard");
|
||||
|
||||
QObject::connect(dialog, SIGNAL(applyClicked()), q, SLOT(configDialogFinished()), Qt::UniqueConnection);
|
||||
QObject::connect(dialog, SIGNAL(okClicked()), q, SLOT(configDialogFinished()), Qt::UniqueConnection);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppletPrivate::addPublishPage(KConfigDialog *dialog)
|
||||
{
|
||||
#if ENABLE_REMOTE_WIDGETS
|
||||
QWidget *page = new QWidget;
|
||||
publishUI.setupUi(page);
|
||||
publishUI.publishCheckbox->setChecked(q->isPublished());
|
||||
QObject::connect(publishUI.publishCheckbox, SIGNAL(clicked(bool)), dialog, SLOT(settingsModified()));
|
||||
publishUI.allUsersCheckbox->setEnabled(q->isPublished());
|
||||
QObject::connect(publishUI.allUsersCheckbox, SIGNAL(clicked(bool)), dialog, SLOT(settingsModified()));
|
||||
|
||||
QString resourceName =
|
||||
i18nc("%1 is the name of a plasmoid, %2 the name of the machine that plasmoid is published on",
|
||||
"%1 on %2", q->name(), QHostInfo::localHostName());
|
||||
if (AuthorizationManager::self()->d->matchingRule(resourceName, Credentials())) {
|
||||
publishUI.allUsersCheckbox->setChecked(true);
|
||||
} else {
|
||||
publishUI.allUsersCheckbox->setChecked(false);
|
||||
}
|
||||
|
||||
q->connect(publishUI.publishCheckbox, SIGNAL(stateChanged(int)),
|
||||
q, SLOT(publishCheckboxStateChanged(int)));
|
||||
dialog->addPage(page, i18n("Share"), "applications-internet");
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppletPrivate::publishCheckboxStateChanged(int state)
|
||||
{
|
||||
if (state == Qt::Checked) {
|
||||
publishUI.allUsersCheckbox->setEnabled(true);
|
||||
} else {
|
||||
publishUI.allUsersCheckbox->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AppletPrivate::configDialogFinished()
|
||||
{
|
||||
if (shortcutEditor) {
|
||||
QKeySequence sequence = shortcutEditor.data()->keySequence();
|
||||
if (sequence != q->globalShortcut().primary()) {
|
||||
q->setGlobalShortcut(KShortcut(sequence));
|
||||
emit q->configNeedsSaving();
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_REMOTE_WIDGETS
|
||||
if (KConfigDialog::exists(configDialogId()) && publishUI.publishCheckbox) {
|
||||
q->config().writeEntry("Share", publishUI.publishCheckbox->isChecked());
|
||||
|
||||
if (publishUI.publishCheckbox->isChecked()) {
|
||||
QString resourceName =
|
||||
i18nc("%1 is the name of a plasmoid, %2 the name of the machine that plasmoid is published on",
|
||||
"%1 on %2", q->name(), QHostInfo::localHostName());
|
||||
q->publish(Plasma::ZeroconfAnnouncement, resourceName);
|
||||
if (publishUI.allUsersCheckbox->isChecked()) {
|
||||
if (!AuthorizationManager::self()->d->matchingRule(resourceName, Credentials())) {
|
||||
AuthorizationRule *rule = new AuthorizationRule(resourceName, "");
|
||||
rule->setPolicy(AuthorizationRule::Allow);
|
||||
rule->setTargets(AuthorizationRule::AllUsers);
|
||||
AuthorizationManager::self()->d->rules.append(rule);
|
||||
}
|
||||
} else {
|
||||
AuthorizationRule *matchingRule =
|
||||
AuthorizationManager::self()->d->matchingRule(resourceName, Credentials());
|
||||
if (matchingRule) {
|
||||
AuthorizationManager::self()->d->rules.removeAll(matchingRule);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
q->unpublish();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!configLoader) {
|
||||
// the config loader will trigger this for us, so we don't need to.
|
||||
propagateConfigChanged();
|
||||
if (KConfigDialog *dialog = qobject_cast<KConfigDialog *>(q->sender())) {
|
||||
dialog->button(QDialogButtonBox::Apply)->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppletPrivate::updateShortcuts()
|
||||
{
|
||||
if (isContainment) {
|
||||
//a horrible hack to avoid clobbering corona settings
|
||||
//we pull them out, then read, then put them back
|
||||
QList<QString> names;
|
||||
QList<QAction*> qactions;
|
||||
names << "add sibling containment" << "configure shortcuts" << "lock widgets";
|
||||
foreach (const QString &name, names) {
|
||||
QAction *a = actions->action(name);
|
||||
actions->takeAction(a); //FIXME this is stupid, KActionCollection needs a takeAction(QString) method
|
||||
qactions << a;
|
||||
}
|
||||
|
||||
actions->readSettings();
|
||||
|
||||
for (int i = 0; i < names.size(); ++i) {
|
||||
QAction *a = qactions.at(i);
|
||||
if (a) {
|
||||
actions->addAction(names.at(i), a);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
actions->readSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void AppletPrivate::propagateConfigChanged()
|
||||
{
|
||||
if (isContainment) {
|
||||
Containment *c = qobject_cast<Containment *>(q);
|
||||
if (c) {
|
||||
c->d->configChanged();
|
||||
}
|
||||
}
|
||||
|
||||
q->configChanged();
|
||||
}
|
||||
|
||||
void AppletPrivate::filterOffers(QList<KService::Ptr> &offers)
|
||||
{
|
||||
KConfigGroup constraintGroup(KSharedConfig::openConfig(), "Constraints");
|
||||
foreach (const QString &key, constraintGroup.keyList()) {
|
||||
//kDebug() << "security constraint" << key;
|
||||
if (constraintGroup.readEntry(key, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//ugh. a qlist of ksharedptr<kservice>
|
||||
QMutableListIterator<KService::Ptr> it(offers);
|
||||
while (it.hasNext()) {
|
||||
KService::Ptr p = it.next();
|
||||
QString prop = QString("X-Plasma-Requires-").append(key);
|
||||
QVariant req = p->property(prop, QVariant::String);
|
||||
//valid values: Required/Optional/Unused
|
||||
QString reqValue;
|
||||
if (req.isValid()) {
|
||||
reqValue = req.toString();
|
||||
} else if (p->property("X-Plasma-API").toString().toLower() == "javascript") {
|
||||
//TODO: be able to check whether or not a script engine provides "controled"
|
||||
//bindings; for now we just give a pass to the qscript ones
|
||||
reqValue = "Unused";
|
||||
}
|
||||
|
||||
if (!(reqValue == "Optional" || reqValue == "Unused")) {
|
||||
//if (reqValue == "Required") {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString AppletPrivate::parentAppConstraint(const QString &parentApp)
|
||||
{
|
||||
if (parentApp.isEmpty()) {
|
||||
QCoreApplication *app = QCoreApplication::instance();
|
||||
if (!app) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString("((not exist [X-KDE-ParentApp] or [X-KDE-ParentApp] == '') or [X-KDE-ParentApp] == '%1')")
|
||||
.arg(app->applicationName());
|
||||
}
|
||||
|
||||
return QString("[X-KDE-ParentApp] == '%1'").arg(parentApp);
|
||||
}
|
||||
|
||||
void AppletPrivate::setIsContainment(bool nowIsContainment, bool forceUpdate)
|
||||
{
|
||||
if (isContainment == nowIsContainment && !forceUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
isContainment = nowIsContainment;
|
||||
//FIXME I do not like this function.
|
||||
//currently it's only called before ctmt/applet init, with (true,true), and I'm going to assume it stays that way.
|
||||
//if someone calls it at some other time it'll cause headaches. :P
|
||||
|
||||
delete mainConfig;
|
||||
mainConfig = 0;
|
||||
|
||||
Containment *c = q->containment();
|
||||
if (c) {
|
||||
c->d->checkContainmentFurniture();
|
||||
}
|
||||
}
|
||||
|
||||
// put all setup routines for script here. at this point we can assume that
|
||||
// package exists and that we have a script engine
|
||||
void AppletPrivate::setupScriptSupport()
|
||||
{
|
||||
if (!package) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "setting up script support, package is in" << package->path()
|
||||
<< ", main script is" << package->filePath("mainscript");
|
||||
#endif
|
||||
|
||||
const QString translationsPath = package->filePath("translations");
|
||||
if (!translationsPath.isEmpty()) {
|
||||
KGlobal::dirs()->addResourceDir("locale", translationsPath);
|
||||
KLocalizedString::insertCatalog(appletDescription.pluginName());
|
||||
}
|
||||
|
||||
const QString xmlPath = package->filePath("mainconfigxml");
|
||||
if (!xmlPath.isEmpty()) {
|
||||
QFile file(xmlPath);
|
||||
KConfigGroup config = q->config();
|
||||
configLoader = new ConfigLoader(&config, &file);
|
||||
QObject::connect(configLoader, SIGNAL(configChanged()), q, SLOT(propagateConfigChanged()));
|
||||
}
|
||||
|
||||
if (!package->filePath("mainconfigui").isEmpty()) {
|
||||
q->setHasConfigurationInterface(true);
|
||||
}
|
||||
}
|
||||
|
||||
QString AppletPrivate::globalName() const
|
||||
{
|
||||
if (!appletDescription.isValid()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return appletDescription.service()->library();
|
||||
}
|
||||
|
||||
QString AppletPrivate::instanceName()
|
||||
{
|
||||
if (!appletDescription.isValid()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return appletDescription.service()->library() + QString::number(appletId);
|
||||
}
|
||||
|
||||
void AppletPrivate::scheduleConstraintsUpdate(Plasma::Constraints c)
|
||||
{
|
||||
// Don't start up a timer if we're just starting up
|
||||
// flushPendingConstraints will be called by Corona
|
||||
if (started && !constraintsTimer.isActive() && !(c & Plasma::StartupCompletedConstraint)) {
|
||||
constraintsTimer.start(0, q);
|
||||
}
|
||||
|
||||
if (c & Plasma::StartupCompletedConstraint) {
|
||||
started = true;
|
||||
}
|
||||
|
||||
pendingConstraints |= c;
|
||||
}
|
||||
|
||||
void AppletPrivate::scheduleModificationNotification()
|
||||
{
|
||||
// modificationsTimer is not allocated until we get our notice of being started
|
||||
if (modificationsTimer) {
|
||||
// schedule a save
|
||||
if (modificationsTimer->isActive()) {
|
||||
modificationsTimer->stop();
|
||||
}
|
||||
|
||||
modificationsTimer->start(1000, q);
|
||||
}
|
||||
}
|
||||
|
||||
KConfigGroup *AppletPrivate::mainConfigGroup()
|
||||
{
|
||||
if (mainConfig) {
|
||||
return mainConfig;
|
||||
}
|
||||
|
||||
if (isContainment) {
|
||||
Corona *corona = static_cast<Containment*>(q)->corona();
|
||||
KConfigGroup containmentConfig;
|
||||
//kDebug() << "got a corona, baby?" << (QObject*)corona << (QObject*)q;
|
||||
|
||||
if (corona) {
|
||||
containmentConfig = KConfigGroup(corona->config(), "Containments");
|
||||
} else {
|
||||
containmentConfig = KConfigGroup(KSharedConfig::openConfig(), "Containments");
|
||||
}
|
||||
|
||||
mainConfig = new KConfigGroup(&containmentConfig, QString::number(appletId));
|
||||
} else {
|
||||
KConfigGroup appletConfig;
|
||||
|
||||
Containment *c = q->containment();
|
||||
Applet *parentApplet = qobject_cast<Applet *>(q->parent());
|
||||
if (parentApplet && parentApplet != static_cast<Applet *>(c)) {
|
||||
// this applet is nested inside another applet! use it's config
|
||||
// as the parent group in the config
|
||||
appletConfig = parentApplet->config();
|
||||
appletConfig = KConfigGroup(&appletConfig, "Applets");
|
||||
} else if (c) {
|
||||
// applet directly in a Containment, as usual
|
||||
appletConfig = c->config();
|
||||
appletConfig = KConfigGroup(&appletConfig, "Applets");
|
||||
} else {
|
||||
kWarning() << "requesting config for" << q->name() << "without a containment!";
|
||||
appletConfig = KConfigGroup(KSharedConfig::openConfig(), "Applets");
|
||||
}
|
||||
|
||||
mainConfig = new KConfigGroup(&appletConfig, QString::number(appletId));
|
||||
}
|
||||
|
||||
return mainConfig;
|
||||
}
|
||||
|
||||
QString AppletPrivate::visibleFailureText(const QString &reason)
|
||||
{
|
||||
QString text;
|
||||
|
||||
if (reason.isEmpty()) {
|
||||
text = i18n("This object could not be created.");
|
||||
} else {
|
||||
text = i18n("This object could not be created for the following reason:<p><b>%1</b></p>", reason);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
void AppletPrivate::resetConfigurationObject()
|
||||
{
|
||||
// make sure mainConfigGroup exists in all cases
|
||||
mainConfigGroup();
|
||||
|
||||
mainConfig->deleteGroup();
|
||||
delete mainConfig;
|
||||
mainConfig = 0;
|
||||
|
||||
if (!q->containment()) {
|
||||
return;
|
||||
}
|
||||
Corona * corona = q->containment()->corona();
|
||||
if (corona) {
|
||||
corona->requireConfigSync();
|
||||
}
|
||||
}
|
||||
|
||||
uint AppletPrivate::s_maxAppletId = 0;
|
||||
QSet<QString> AppletPrivate::s_customCategories;
|
||||
|
||||
} //namespace Plasma
|
188
plasma/private/applet_p.h
Normal file
188
plasma/private/applet_p.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2005 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
*
|
||||
* 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 PLASMA_APPLET_P_H
|
||||
#define PLASMA_APPLET_P_H
|
||||
|
||||
#include <QBasicTimer>
|
||||
|
||||
#include <kactioncollection.h>
|
||||
#include <kconfigdialog.h>
|
||||
#include <kconfigskeleton.h>
|
||||
#include <kservice.h>
|
||||
#include <kplugininfo.h>
|
||||
|
||||
#include "plasma/applet.h"
|
||||
#include "plasma/dataengineconsumer.h"
|
||||
#include "plasma/ui_publish.h"
|
||||
|
||||
class KKeySequenceWidget;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class Dialog;
|
||||
class FrameSvg;
|
||||
class AppletScript;
|
||||
class Wallpaper;
|
||||
class BusyWidget;
|
||||
class PushButton;
|
||||
class Service;
|
||||
|
||||
class AppletConfigDialog : public KConfigDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AppletConfigDialog(QWidget* parent, const QString &id, KConfigSkeleton *s)
|
||||
: KConfigDialog(parent, id, s),
|
||||
m_changed(false)
|
||||
{
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void settingsModified(bool modified = true)
|
||||
{
|
||||
m_changed = modified;
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
protected:
|
||||
bool hasChanged()
|
||||
{
|
||||
return m_changed || KConfigDialog::hasChanged();
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_changed;
|
||||
};
|
||||
|
||||
class PLASMA_EXPORT AppletPrivate : public DataEngineConsumer
|
||||
{
|
||||
public:
|
||||
AppletPrivate(KService::Ptr service, const KPluginInfo *info, int uniqueID, Applet *applet);
|
||||
virtual ~AppletPrivate();
|
||||
|
||||
void init(const QString &packagePath = QString());
|
||||
|
||||
// the interface
|
||||
virtual void showConfigurationRequiredMessage(bool show, const QString &reason);
|
||||
virtual void cleanUpAndDelete();
|
||||
virtual void showMessage(const QIcon &icon, const QString &message, const MessageButtons buttons);
|
||||
virtual void positionMessageOverlay();
|
||||
virtual void setBusy(bool busy);
|
||||
virtual bool isBusy() const;
|
||||
virtual void updateFailedToLaunch(const QString &reason);
|
||||
|
||||
// put all setup routines for script here. at this point we can assume that
|
||||
// package exists and that we have a script engin
|
||||
void setupScriptSupport();
|
||||
|
||||
/**
|
||||
* Sets whether or not this Applet is acting as a Containment
|
||||
*/
|
||||
void setIsContainment(bool isContainment, bool forceUpdate = false);
|
||||
|
||||
QString globalName() const;
|
||||
QString instanceName();
|
||||
void scheduleConstraintsUpdate(Plasma::Constraints c);
|
||||
void scheduleModificationNotification();
|
||||
KConfigGroup *mainConfigGroup();
|
||||
QString visibleFailureText(const QString &reason);
|
||||
void resetConfigurationObject();
|
||||
void addGlobalShortcutsPage(KConfigDialog *dialog);
|
||||
void addPublishPage(KConfigDialog *dialog);
|
||||
void configDialogFinished();
|
||||
KConfigDialog *generateGenericConfigDialog();
|
||||
void addStandardConfigurationPages(KConfigDialog *dialog);
|
||||
QString configDialogId() const;
|
||||
QString configWindowTitle() const;
|
||||
void updateShortcuts();
|
||||
void publishCheckboxStateChanged(int state);
|
||||
void globalShortcutChanged();
|
||||
void propagateConfigChanged();
|
||||
|
||||
static KActionCollection* defaultActions(QObject *parent);
|
||||
static QSet<QString> knownCategories();
|
||||
static void filterOffers(QList<KService::Ptr> &offers);
|
||||
static QString parentAppConstraint(const QString &parentApp = QString());
|
||||
|
||||
static uint s_maxAppletId;
|
||||
static QSet<QString> s_customCategories;
|
||||
|
||||
// number of members at this point.
|
||||
uint appletId;
|
||||
Applet *q;
|
||||
|
||||
// applet attributes
|
||||
Service *remotingService;
|
||||
BackgroundHints backgroundHints;
|
||||
AspectRatioMode aspectRatioMode;
|
||||
ImmutabilityType immutability;
|
||||
|
||||
// applet info we keep around in case its needed
|
||||
KPluginInfo appletDescription;
|
||||
QVariantList args;
|
||||
QString customName;
|
||||
|
||||
// bookkeeping
|
||||
KConfigGroup *mainConfig;
|
||||
Plasma::Constraints pendingConstraints;
|
||||
|
||||
// sripting and package stuff
|
||||
AppletScript *script;
|
||||
Package *package;
|
||||
ConfigLoader *configLoader;
|
||||
|
||||
// actions stuff; put activationAction into actions?
|
||||
KActionCollection *actions;
|
||||
KAction *activationAction;
|
||||
|
||||
// configuration
|
||||
QWeakPointer<KKeySequenceWidget> shortcutEditor; //TODO: subclass KConfigDialog and encapsulate this in there
|
||||
|
||||
ItemStatus itemStatus;
|
||||
KUrl remoteLocation;
|
||||
Ui::publishWidget publishUI;
|
||||
|
||||
// the applet can change size policy by itself, so save the old one for eventual restore
|
||||
QSizePolicy preferredSizePolicy;
|
||||
|
||||
//keep last sizes for formfactors, useful when the containment changes
|
||||
QHash<FormFactor, QSizeF> sizeForFormFactor;
|
||||
|
||||
// timerEvent bookkeeping
|
||||
QBasicTimer constraintsTimer;
|
||||
QBasicTimer *modificationsTimer;
|
||||
|
||||
// a great green field of booleans :)
|
||||
bool hasConfigurationInterface : 1;
|
||||
bool failed : 1;
|
||||
bool isContainment : 1;
|
||||
bool square : 1;
|
||||
bool transient : 1;
|
||||
bool needsConfig : 1;
|
||||
bool started : 1;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif
|
155
plasma/private/associatedapplicationmanager.cpp
Normal file
155
plasma/private/associatedapplicationmanager.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2009 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* 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 "associatedapplicationmanager_p.h"
|
||||
|
||||
#include "config-plasma.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QFile>
|
||||
|
||||
#include <qstandardpaths.h>
|
||||
#include <klocalizedstring.h>
|
||||
#include <kiconloader.h>
|
||||
|
||||
#if !PLASMA_NO_KIO
|
||||
#include <krun.h>
|
||||
#else
|
||||
#include <QProcess>
|
||||
#include <QDesktopServices>
|
||||
#endif
|
||||
|
||||
#include "plasma/applet.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AssociatedApplicationManagerPrivate
|
||||
{
|
||||
public:
|
||||
AssociatedApplicationManagerPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
~AssociatedApplicationManagerPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
void cleanupApplet(QObject *obj)
|
||||
{
|
||||
Plasma::Applet *applet = static_cast<Plasma::Applet *>(obj);
|
||||
applicationNames.remove(applet);
|
||||
urlLists.remove(applet);
|
||||
}
|
||||
|
||||
QHash<const Plasma::Applet *, QString> applicationNames;
|
||||
QHash<const Plasma::Applet *, QList<QUrl> > urlLists;
|
||||
};
|
||||
|
||||
class AssociatedApplicationManagerSingleton
|
||||
{
|
||||
public:
|
||||
AssociatedApplicationManager self;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(AssociatedApplicationManagerSingleton, privateAssociatedApplicationManagerSelf)
|
||||
|
||||
|
||||
AssociatedApplicationManager::AssociatedApplicationManager(QObject *parent)
|
||||
: QObject(parent),
|
||||
d(new AssociatedApplicationManagerPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
AssociatedApplicationManager::~AssociatedApplicationManager()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
AssociatedApplicationManager *AssociatedApplicationManager::self()
|
||||
{
|
||||
return &privateAssociatedApplicationManagerSelf()->self;
|
||||
}
|
||||
|
||||
void AssociatedApplicationManager::setApplication(Plasma::Applet *applet, const QString &application)
|
||||
{
|
||||
KService::Ptr service = KService::serviceByDesktopName(application);
|
||||
if (service || !QStandardPaths::findExecutable(application).isNull() || QFile::exists(application)) {
|
||||
d->applicationNames[applet] = application;
|
||||
if (!d->urlLists.contains(applet)) {
|
||||
connect(applet, SIGNAL(destroyed(QObject*)), this, SLOT(cleanupApplet(QObject*)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString AssociatedApplicationManager::application(const Plasma::Applet *applet) const
|
||||
{
|
||||
return d->applicationNames.value(applet);
|
||||
}
|
||||
|
||||
void AssociatedApplicationManager::setUrls(Plasma::Applet *applet, const QList<QUrl> &urls)
|
||||
{
|
||||
d->urlLists[applet] = urls;
|
||||
}
|
||||
|
||||
QList<QUrl> AssociatedApplicationManager::urls(const Plasma::Applet *applet) const
|
||||
{
|
||||
return d->urlLists.value(applet);
|
||||
}
|
||||
|
||||
void AssociatedApplicationManager::run(Plasma::Applet *applet)
|
||||
{
|
||||
if (d->applicationNames.contains(applet)) {
|
||||
#if !PLASMA_NO_KIO
|
||||
bool success = KRun::run(d->applicationNames.value(applet), d->urlLists.value(applet), 0);
|
||||
#else
|
||||
QString execCommand = d->applicationNames.value(applet);
|
||||
|
||||
// Clean-up the %u and friends from the exec command (KRun expect them, not QProcess)
|
||||
execCommand = execCommand.replace(QRegExp("%[a-z]"), QString());
|
||||
execCommand = execCommand.trimmed();
|
||||
|
||||
QStringList parameters = d->urlLists.value(applet).toStringList();
|
||||
bool success = QProcess::startDetached(execCommand, parameters);
|
||||
#endif
|
||||
|
||||
if (!success) {
|
||||
applet->showMessage(KDE::icon("application-exit"), i18n("There was an error attempting to exec the associated application with this widget."), ButtonOk);
|
||||
}
|
||||
|
||||
} else if (d->urlLists.contains(applet) && !d->urlLists.value(applet).isEmpty()) {
|
||||
#if !PLASMA_NO_KIO
|
||||
KRun *krun = new KRun(d->urlLists.value(applet).first(), 0);
|
||||
krun->setAutoDelete(true);
|
||||
#else
|
||||
QDesktopServices::openUrl(d->urlLists.value(applet).first());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool AssociatedApplicationManager::appletHasValidAssociatedApplication(const Plasma::Applet *applet) const
|
||||
{
|
||||
return (d->applicationNames.contains(applet) || d->urlLists.contains(applet));
|
||||
}
|
||||
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#include <moc_associatedapplicationmanager_p.cpp>
|
||||
|
67
plasma/private/associatedapplicationmanager_p.h
Normal file
67
plasma/private/associatedapplicationmanager_p.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2009 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* 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 PLASMA_ASSOCIATEDAPPLICATIONMANAGER_P_H
|
||||
#define PLASMA_ASSOCIATEDAPPLICATIONMANAGER_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <kurl.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
class Applet;
|
||||
|
||||
class AssociatedApplicationManagerPrivate;
|
||||
|
||||
class AssociatedApplicationManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static AssociatedApplicationManager *self();
|
||||
|
||||
//set an application name for an applet
|
||||
void setApplication(Plasma::Applet *applet, const QString &application);
|
||||
//returns the application name associated to an applet
|
||||
QString application(const Plasma::Applet *applet) const;
|
||||
|
||||
//sets the urls associated to an applet
|
||||
void setUrls(Plasma::Applet *applet, const QList<QUrl> &urls);
|
||||
//returns the urls associated to an applet
|
||||
QList<QUrl> urls(const Plasma::Applet *applet) const;
|
||||
|
||||
//run the associated application or the urls if no app is associated
|
||||
void run(Plasma::Applet *applet);
|
||||
//returns true if the applet has a valid associated application or urls
|
||||
bool appletHasValidAssociatedApplication(const Plasma::Applet *applet) const;
|
||||
|
||||
private:
|
||||
AssociatedApplicationManager(QObject *parent = 0);
|
||||
~AssociatedApplicationManager();
|
||||
|
||||
AssociatedApplicationManagerPrivate *const d;
|
||||
friend class AssociatedApplicationManagerSingleton;
|
||||
|
||||
Q_PRIVATE_SLOT(d, void cleanupApplet(QObject *obj))
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif // multiple inclusion guard
|
101
plasma/private/componentinstaller.cpp
Normal file
101
plasma/private/componentinstaller.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2011 Kevin Kofler <kevin.kofler@chello.at>
|
||||
*
|
||||
* 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 "private/componentinstaller_p.h"
|
||||
|
||||
#ifdef PLASMA_ENABLE_PACKAGEKIT_SUPPORT
|
||||
#include <QSet>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusPendingCall>
|
||||
#include <QWidget>
|
||||
#include <QLatin1String>
|
||||
#include <QStringList>
|
||||
#endif
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ComponentInstallerPrivate
|
||||
{
|
||||
public:
|
||||
#ifdef PLASMA_ENABLE_PACKAGEKIT_SUPPORT
|
||||
QSet<QString> alreadyPrompted;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ComponentInstallerSingleton
|
||||
{
|
||||
public:
|
||||
ComponentInstaller self;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(ComponentInstallerSingleton, privateComponentInstallerSelf)
|
||||
|
||||
ComponentInstaller *ComponentInstaller::self()
|
||||
{
|
||||
return &privateComponentInstallerSelf()->self;
|
||||
}
|
||||
|
||||
ComponentInstaller::ComponentInstaller()
|
||||
: d(new ComponentInstallerPrivate)
|
||||
{
|
||||
}
|
||||
|
||||
ComponentInstaller::~ComponentInstaller()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ComponentInstaller::installMissingComponent(const QString &type,
|
||||
const QString &name,
|
||||
QWidget *parent, bool force)
|
||||
{
|
||||
#ifdef PLASMA_ENABLE_PACKAGEKIT_SUPPORT
|
||||
QString searchString = type + '-' + name;
|
||||
|
||||
if (!force) {
|
||||
if (d->alreadyPrompted.contains(searchString)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
d->alreadyPrompted.insert(searchString);
|
||||
|
||||
QDBusInterface packageKit(QLatin1String("org.freedesktop.PackageKit"),
|
||||
QLatin1String("/org/freedesktop/PackageKit"),
|
||||
QLatin1String("org.freedesktop.PackageKit.Modify"));
|
||||
// We don't check packageKit.isValid() because the service is activated on
|
||||
// demand, so it will show up as "not valid".
|
||||
WId wid = 0;
|
||||
if (parent) {
|
||||
wid = parent->winId();
|
||||
}
|
||||
QStringList resources;
|
||||
resources.append(searchString);
|
||||
packageKit.asyncCall(QLatin1String("InstallResources"), (unsigned int) wid,
|
||||
QLatin1String("plasma-service"), resources, QString());
|
||||
#else
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(name);
|
||||
Q_UNUSED(parent);
|
||||
Q_UNUSED(force);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
94
plasma/private/componentinstaller_p.h
Normal file
94
plasma/private/componentinstaller_p.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2011 Kevin Kofler <kevin.kofler@chello.at>
|
||||
*
|
||||
* 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 PLASMA_COMPONENTINSTALLER_H
|
||||
#define PLASMA_COMPONENTINSTALLER_H
|
||||
|
||||
class QString;
|
||||
class QWidget;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ComponentInstallerPrivate;
|
||||
|
||||
/**
|
||||
* @class ComponentInstaller plasma/private/componentinstaller_p.h
|
||||
*
|
||||
* @short This class provides a generic API for installation of components.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* Plasma::ComponentInstaller allows searching for a missing data or script
|
||||
* engine by name, and allowing the user to install the missing service.
|
||||
* Currently, PackageKit is supported as the mechanism to install components,
|
||||
* but more mechanisms could be supported in the future through the same API.
|
||||
*
|
||||
* @since 4.8
|
||||
*/
|
||||
class ComponentInstaller
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Singleton pattern accessor.
|
||||
*/
|
||||
static ComponentInstaller *self();
|
||||
|
||||
/**
|
||||
* Installs a missing component asynchronously.
|
||||
*
|
||||
* By default, this method will cache requested components and not
|
||||
* prompt again for the same engine in the same session. The force
|
||||
* parameter can be used to disable this mechanism, e.g. when the user
|
||||
* just installed a new widget written in a scripting language, and so
|
||||
* is likely to want the script engine installed after all.
|
||||
*
|
||||
* In the case of on-demand installation, this will unfortunately not
|
||||
* allow the call which triggered the missing component lookup to
|
||||
* succeed, but we cannot afford to block all of Plasma until the
|
||||
* mechanism is done installing the service.
|
||||
*
|
||||
* This function does nothing if PackageKit integration was disabled at
|
||||
* compile time.
|
||||
*
|
||||
* @param type the type of the component, should be "scriptengine" or
|
||||
* "dataengine"
|
||||
* @param name the name of the component
|
||||
* @param parent a parent widget, used to set the wid for PackageKit
|
||||
* @param force whether to always prompt, even if recently prompted
|
||||
*/
|
||||
void installMissingComponent(const QString &type, const QString &name,
|
||||
QWidget *parent = 0, bool force = false);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Default constructor. The singleton method self() is the
|
||||
* preferred access mechanism.
|
||||
*/
|
||||
ComponentInstaller();
|
||||
~ComponentInstaller();
|
||||
|
||||
ComponentInstallerPrivate *const d;
|
||||
|
||||
friend class ComponentInstallerSingleton;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif // multiple inclusion guard
|
223
plasma/private/configloader_p.h
Normal file
223
plasma/private/configloader_p.h
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright 2007-2008 Aaron Seigo <aseigo@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 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 PLASMA_CONFIGLOADER_P_H
|
||||
#define PLASMA_CONFIGLOADER_P_H
|
||||
|
||||
#include <kurl.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ConfigLoaderPrivate
|
||||
{
|
||||
public:
|
||||
ConfigLoaderPrivate()
|
||||
: saveDefaults(false)
|
||||
{
|
||||
}
|
||||
|
||||
~ConfigLoaderPrivate()
|
||||
{
|
||||
qDeleteAll(bools);
|
||||
qDeleteAll(strings);
|
||||
qDeleteAll(stringlists);
|
||||
qDeleteAll(colors);
|
||||
qDeleteAll(fonts);
|
||||
qDeleteAll(ints);
|
||||
qDeleteAll(uints);
|
||||
qDeleteAll(urls);
|
||||
qDeleteAll(dateTimes);
|
||||
qDeleteAll(doubles);
|
||||
qDeleteAll(intlists);
|
||||
qDeleteAll(longlongs);
|
||||
qDeleteAll(points);
|
||||
qDeleteAll(rects);
|
||||
qDeleteAll(sizes);
|
||||
qDeleteAll(ulonglongs);
|
||||
qDeleteAll(urllists);
|
||||
}
|
||||
|
||||
bool *newBool()
|
||||
{
|
||||
bool *v = new bool;
|
||||
bools.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QString *newString()
|
||||
{
|
||||
QString *v = new QString;
|
||||
strings.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QStringList *newStringList()
|
||||
{
|
||||
QStringList *v = new QStringList;
|
||||
stringlists.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QColor *newColor()
|
||||
{
|
||||
QColor *v = new QColor;
|
||||
colors.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QFont *newFont()
|
||||
{
|
||||
QFont *v = new QFont;
|
||||
fonts.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
qint32 *newInt()
|
||||
{
|
||||
qint32 *v = new qint32;
|
||||
ints.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
quint32 *newUint()
|
||||
{
|
||||
quint32 *v = new quint32;
|
||||
uints.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
KUrl *newUrl()
|
||||
{
|
||||
KUrl *v = new KUrl;
|
||||
urls.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QDateTime *newDateTime()
|
||||
{
|
||||
QDateTime *v = new QDateTime;
|
||||
dateTimes.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
double *newDouble()
|
||||
{
|
||||
double *v = new double;
|
||||
doubles.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QList<qint32>* newIntList()
|
||||
{
|
||||
QList<qint32> *v = new QList<qint32>;
|
||||
intlists.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
qint64 *newLongLong()
|
||||
{
|
||||
qint64 *v = new qint64;
|
||||
longlongs.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QPoint *newPoint()
|
||||
{
|
||||
QPoint *v = new QPoint;
|
||||
points.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QRect *newRect()
|
||||
{
|
||||
QRect *v = new QRect;
|
||||
rects.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QSize *newSize()
|
||||
{
|
||||
QSize *v = new QSize;
|
||||
sizes.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
quint64 *newULongLong()
|
||||
{
|
||||
quint64 *v = new quint64;
|
||||
ulonglongs.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
QList<QUrl> *newUrlList()
|
||||
{
|
||||
QList<QUrl> *v = new QList<QUrl>();
|
||||
urllists.append(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
void parse(ConfigLoader *loader, QIODevice *xml);
|
||||
|
||||
/**
|
||||
* Whether or not to write out default values.
|
||||
*
|
||||
* @param writeDefaults true if defaults should be written out
|
||||
*/
|
||||
void setWriteDefaults(bool writeDefaults)
|
||||
{
|
||||
saveDefaults = writeDefaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if default values will also be written out
|
||||
*/
|
||||
bool writeDefaults() const
|
||||
{
|
||||
return saveDefaults;
|
||||
}
|
||||
|
||||
|
||||
QList<bool *> bools;
|
||||
QList<QString *> strings;
|
||||
QList<QStringList *> stringlists;
|
||||
QList<QColor *> colors;
|
||||
QList<QFont *> fonts;
|
||||
QList<qint32 *> ints;
|
||||
QList<quint32 *> uints;
|
||||
QList<KUrl *> urls;
|
||||
QList<QDateTime *> dateTimes;
|
||||
QList<double *> doubles;
|
||||
QList<QList<qint32> *> intlists;
|
||||
QList<qint64 *> longlongs;
|
||||
QList<QPoint *> points;
|
||||
QList<QRect *> rects;
|
||||
QList<QSize *> sizes;
|
||||
QList<quint64 *> ulonglongs;
|
||||
QList<QList<QUrl> *> urllists;
|
||||
QString baseGroup;
|
||||
QStringList groups;
|
||||
QHash<QString, QString> keysToNames;
|
||||
bool saveDefaults;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
500
plasma/private/containment_p.cpp
Normal file
500
plasma/private/containment_p.cpp
Normal file
@ -0,0 +1,500 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
* Copyright 2009 Chani Armitage <chani@kde.org>
|
||||
* Copyright 2012 Marco Martin <notmart@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 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 "private/containment_p.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QMimeData>
|
||||
#include <QMimeDatabase>
|
||||
#include <QDropEvent>
|
||||
#include <qtemporaryfile.h>
|
||||
|
||||
#include <kaction.h>
|
||||
#include <kactioncollection.h>
|
||||
#include <kcoreauthorized.h>
|
||||
#include <kiconloader.h>
|
||||
#include <klocale.h>
|
||||
#include <kurlmimedata.h>
|
||||
#include <kwindowsystem.h>
|
||||
|
||||
#include "config-plasma.h"
|
||||
|
||||
#if !PLASMA_NO_KIO
|
||||
#include "kio/jobclasses.h" // for KIO::JobFlags
|
||||
#include "kio/job.h"
|
||||
#include "kio/scheduler.h"
|
||||
#endif
|
||||
|
||||
#include "containmentactions.h"
|
||||
#include "containmentactionspluginsconfig.h"
|
||||
#include "corona.h"
|
||||
#include "pluginloader.h"
|
||||
#include "svg.h"
|
||||
|
||||
#include "remote/accessappletjob.h"
|
||||
#include "remote/accessmanager.h"
|
||||
|
||||
#include "private/applet_p.h"
|
||||
#include "private/containmentactionspluginsconfig_p.h"
|
||||
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
bool ContainmentPrivate::s_positioningPanels = false;
|
||||
QHash<QString, ContainmentActions*> ContainmentPrivate::globalActionPlugins;
|
||||
|
||||
const char ContainmentPrivate::defaultWallpaper[] = "image";
|
||||
const char ContainmentPrivate::defaultWallpaperMode[] = "SingleImage";
|
||||
|
||||
void ContainmentPrivate::addDefaultActions(KActionCollection *actions, Containment *c)
|
||||
{
|
||||
actions->setConfigGroup("Shortcuts-Containment");
|
||||
|
||||
//adjust applet actions
|
||||
KAction *appAction = qobject_cast<KAction*>(actions->action("remove"));
|
||||
appAction->setShortcut(KShortcut("alt+d, alt+r"));
|
||||
if (c && c->d->isPanelContainment()) {
|
||||
appAction->setText(i18n("Remove this Panel"));
|
||||
} else {
|
||||
appAction->setText(i18n("Remove this Activity"));
|
||||
}
|
||||
|
||||
appAction = qobject_cast<KAction*>(actions->action("configure"));
|
||||
if (appAction) {
|
||||
appAction->setShortcut(KShortcut("alt+d, alt+s"));
|
||||
appAction->setText(i18n("Activity Settings"));
|
||||
}
|
||||
|
||||
//add our own actions
|
||||
KAction *appletBrowserAction = actions->addAction("add widgets");
|
||||
appletBrowserAction->setAutoRepeat(false);
|
||||
appletBrowserAction->setText(i18n("Add Widgets..."));
|
||||
appletBrowserAction->setIcon(KDE::icon("list-add"));
|
||||
appletBrowserAction->setShortcut(KShortcut("alt+d, a"));
|
||||
appletBrowserAction->setData(Containment::AddTool);
|
||||
|
||||
KAction *action = actions->addAction("next applet");
|
||||
action->setText(i18n("Next Widget"));
|
||||
//no icon
|
||||
action->setShortcut(KShortcut("alt+d, n"));
|
||||
action->setData(Containment::ControlTool);
|
||||
|
||||
action = actions->addAction("previous applet");
|
||||
action->setText(i18n("Previous Widget"));
|
||||
//no icon
|
||||
action->setShortcut(KShortcut("alt+d, p"));
|
||||
action->setData(Containment::ControlTool);
|
||||
}
|
||||
|
||||
void ContainmentPrivate::initApplets()
|
||||
{
|
||||
foreach (Applet *applet, applets) {
|
||||
applet->restore(*applet->d->mainConfigGroup());
|
||||
applet->init();
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Applet" << applet->name();
|
||||
#endif
|
||||
}
|
||||
|
||||
q->flushPendingConstraintsEvents();
|
||||
|
||||
foreach (Applet *applet, applets) {
|
||||
applet->flushPendingConstraintsEvents();
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Containment's applets initialized" << q->name();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ContainmentPrivate::checkContainmentFurniture()
|
||||
{
|
||||
if (q->isContainment() &&
|
||||
(type == Containment::DesktopContainment || type == Containment::PanelContainment)) {
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentPrivate::addContainmentActions(KMenu &desktopMenu, QEvent *event)
|
||||
{
|
||||
if (q->corona()->immutability() != Mutable &&
|
||||
!KAuthorized::authorizeKAction("plasma/containment_actions")) {
|
||||
//kDebug() << "immutability";
|
||||
return;
|
||||
}
|
||||
|
||||
const QString trigger = ContainmentActions::eventToString(event);
|
||||
prepareContainmentActions(trigger, QPoint(), &desktopMenu);
|
||||
}
|
||||
|
||||
void ContainmentPrivate::addAppletActions(KMenu &desktopMenu, Applet *applet, QEvent *event)
|
||||
{
|
||||
foreach (QAction *action, applet->contextualActions()) {
|
||||
if (action) {
|
||||
desktopMenu.addAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
if (!applet->d->failed) {
|
||||
QAction *configureApplet = applet->d->actions->action("configure");
|
||||
if (configureApplet && configureApplet->isEnabled()) {
|
||||
desktopMenu.addAction(configureApplet);
|
||||
}
|
||||
|
||||
QAction *runAssociatedApplication = applet->d->actions->action("run associated application");
|
||||
if (runAssociatedApplication && runAssociatedApplication->isEnabled()) {
|
||||
desktopMenu.addAction(runAssociatedApplication);
|
||||
}
|
||||
}
|
||||
|
||||
KMenu *containmentMenu = new KMenu(i18nc("%1 is the name of the containment", "%1 Options", q->name()), &desktopMenu);
|
||||
addContainmentActions(*containmentMenu, event);
|
||||
if (!containmentMenu->isEmpty()) {
|
||||
int enabled = 0;
|
||||
//count number of real actions
|
||||
QListIterator<QAction *> actionsIt(containmentMenu->actions());
|
||||
while (enabled < 3 && actionsIt.hasNext()) {
|
||||
QAction *action = actionsIt.next();
|
||||
if (action->isVisible() && !action->isSeparator()) {
|
||||
++enabled;
|
||||
}
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
//if there is only one, don't create a submenu
|
||||
if (enabled < 2) {
|
||||
foreach (QAction *action, containmentMenu->actions()) {
|
||||
if (action->isVisible() && !action->isSeparator()) {
|
||||
desktopMenu.addAction(action);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
desktopMenu.addMenu(containmentMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (q->immutability() == Mutable) {
|
||||
QAction *closeApplet = applet->d->actions->action("remove");
|
||||
//kDebug() << "checking for removal" << closeApplet;
|
||||
if (closeApplet) {
|
||||
if (!desktopMenu.isEmpty()) {
|
||||
desktopMenu.addSeparator();
|
||||
}
|
||||
|
||||
//kDebug() << "adding close action" << closeApplet->isEnabled() << closeApplet->isVisible();
|
||||
desktopMenu.addAction(closeApplet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentPrivate::setScreen(int newScreen, int newDesktop, bool preventInvalidDesktops)
|
||||
{
|
||||
// What we want to do in here is:
|
||||
// * claim the screen as our own
|
||||
// * signal whatever may be watching this containment about the switch
|
||||
// * if we are a full screen containment, then:
|
||||
// * resize to match the screen if we're that kind of containment
|
||||
// * kick other full-screen containments off this screen
|
||||
// * if we had a screen, then give our screen to the containment
|
||||
// we kick out
|
||||
//
|
||||
// a screen of -1 means no associated screen.
|
||||
Corona *corona = q->corona();
|
||||
Q_ASSERT(corona);
|
||||
|
||||
//if it's an offscreen widget, don't allow to claim a screen, after all it's *off*screen
|
||||
//TODO: port away qgv
|
||||
/* should decide in a different way if this is a dashboard containment
|
||||
if (corona->offscreenWidgets().contains(q)) {
|
||||
return;
|
||||
}*/
|
||||
|
||||
if (newScreen < -1) {
|
||||
newScreen = -1;
|
||||
}
|
||||
|
||||
// -1 == All desktops
|
||||
if (newDesktop < -1 || (preventInvalidDesktops && newDesktop > KWindowSystem::numberOfDesktops() - 1)) {
|
||||
newDesktop = -1;
|
||||
}
|
||||
|
||||
//kDebug() << activity() << "setting screen to " << newScreen << newDesktop << "and type is" << type;
|
||||
|
||||
Containment *swapScreensWith(0);
|
||||
const bool isDesktopContainment = type == Containment::DesktopContainment ||
|
||||
type == Containment::CustomContainment;
|
||||
if (isDesktopContainment) {
|
||||
if (newScreen > -1) {
|
||||
// sanity check to make sure someone else doesn't have this screen already!
|
||||
Containment *currently = corona->containmentForScreen(newScreen, newDesktop);
|
||||
if (currently && currently != q) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "currently is on screen" << currently->screen()
|
||||
<< "desktop" << currently->desktop()
|
||||
<< "and is" << currently->activity()
|
||||
<< (QObject*)currently << "i'm" << (QObject*)q;
|
||||
#endif
|
||||
currently->setScreen(-1, currently->desktop());
|
||||
swapScreensWith = currently;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int oldDesktop = desktop;
|
||||
desktop = newDesktop;
|
||||
|
||||
int oldScreen = screen;
|
||||
screen = newScreen;
|
||||
|
||||
q->updateConstraints(Plasma::ScreenConstraint);
|
||||
|
||||
if (oldScreen != newScreen || oldDesktop != newDesktop) {
|
||||
/*
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "going to signal change for" << q
|
||||
#endif
|
||||
<< ", old screen & desktop:" << oldScreen << oldDesktop
|
||||
<< ", new:" << screen << desktop;
|
||||
*/
|
||||
KConfigGroup c = q->config();
|
||||
c.writeEntry("screen", screen);
|
||||
c.writeEntry("desktop", desktop);
|
||||
if (newScreen != -1) {
|
||||
lastScreen = newScreen;
|
||||
lastDesktop = newDesktop;
|
||||
c.writeEntry("lastScreen", lastScreen);
|
||||
c.writeEntry("lastDesktop", lastDesktop);
|
||||
}
|
||||
emit q->configNeedsSaving();
|
||||
emit q->screenChanged(oldScreen, newScreen, q);
|
||||
}
|
||||
|
||||
if (swapScreensWith) {
|
||||
//kDebug() << "setScreen due to swap, part 2";
|
||||
swapScreensWith->setScreen(oldScreen, oldDesktop);
|
||||
}
|
||||
|
||||
checkRemoveAction();
|
||||
|
||||
if (newScreen >= 0) {
|
||||
emit q->activate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KActionCollection* ContainmentPrivate::actions()
|
||||
{
|
||||
return static_cast<Applet*>(q)->d->actions;
|
||||
}
|
||||
|
||||
void ContainmentPrivate::configChanged()
|
||||
{
|
||||
if (drawWallpaper) {
|
||||
KConfigGroup group = q->config();
|
||||
q->setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper),
|
||||
group.readEntry("wallpaperpluginmode", defaultWallpaperMode));
|
||||
}
|
||||
}
|
||||
|
||||
void ContainmentPrivate::requestConfiguration()
|
||||
{
|
||||
emit q->configureRequested(q);
|
||||
}
|
||||
|
||||
void ContainmentPrivate::checkStatus(Plasma::ItemStatus appletStatus)
|
||||
{
|
||||
//kDebug() << "================== "<< appletStatus << q->status();
|
||||
if (appletStatus == q->status()) {
|
||||
emit q->newStatus(appletStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
if (appletStatus < q->status()) {
|
||||
// check to see if any other applet has a higher status, and stick with that
|
||||
// if we do
|
||||
foreach (Applet *applet, applets) {
|
||||
if (applet->status() > appletStatus) {
|
||||
appletStatus = applet->status();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
q->setStatus(appletStatus);
|
||||
}
|
||||
|
||||
void ContainmentPrivate::triggerShowAddWidgets()
|
||||
{
|
||||
emit q->showAddWidgetsInterface(QPointF());
|
||||
}
|
||||
|
||||
void ContainmentPrivate::containmentConstraintsEvent(Plasma::Constraints constraints)
|
||||
{
|
||||
if (!q->isContainment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//kDebug() << "got containmentConstraintsEvent" << constraints << (QObject*)toolBox;
|
||||
if (constraints & Plasma::ImmutableConstraint) {
|
||||
//update actions
|
||||
checkRemoveAction();
|
||||
const bool unlocked = q->immutability() == Mutable;
|
||||
q->enableAction("add widgets", unlocked);
|
||||
|
||||
// tell the applets too
|
||||
foreach (Applet *a, applets) {
|
||||
a->setImmutability(q->immutability());
|
||||
a->updateConstraints(ImmutableConstraint);
|
||||
}
|
||||
}
|
||||
|
||||
// pass on the constraints that are relevant here
|
||||
Constraints appletConstraints = NoConstraint;
|
||||
if (constraints & FormFactorConstraint) {
|
||||
appletConstraints |= FormFactorConstraint;
|
||||
}
|
||||
|
||||
if (constraints & ScreenConstraint) {
|
||||
appletConstraints |= ScreenConstraint;
|
||||
}
|
||||
|
||||
if (appletConstraints != NoConstraint) {
|
||||
foreach (Applet *applet, applets) {
|
||||
applet->updateConstraints(appletConstraints);
|
||||
}
|
||||
}
|
||||
|
||||
if (constraints & Plasma::StartupCompletedConstraint && type < Containment::CustomContainment) {
|
||||
q->addToolBoxAction(q->action("remove"));
|
||||
checkRemoveAction();
|
||||
}
|
||||
}
|
||||
|
||||
Applet *ContainmentPrivate::addApplet(const QString &name, const QVariantList &args,
|
||||
const QRectF &appletGeometry, uint id, bool delayInit)
|
||||
{
|
||||
if (!q->isContainment()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!delayInit && q->immutability() != Mutable) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "addApplet for" << name << "requested, but we're currently immutable!";
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
Applet *applet = PluginLoader::self()->loadApplet(name, id, args);
|
||||
|
||||
if (!applet) {
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Applet" << name << "could not be loaded.";
|
||||
#endif
|
||||
applet = new Applet(0, QString(), id);
|
||||
applet->setFailedToLaunch(true, i18n("Could not find requested component: %1", name));
|
||||
}
|
||||
|
||||
//kDebug() << applet->name() << "sizehint:" << applet->sizeHint() << "geometry:" << applet->geometry();
|
||||
|
||||
q->addApplet(applet, appletGeometry.topLeft(), delayInit);
|
||||
return applet;
|
||||
}
|
||||
|
||||
void ContainmentPrivate::appletDeleted(Plasma::Applet *applet)
|
||||
{
|
||||
applets.removeAll(applet);
|
||||
|
||||
emit q->appletRemoved(applet);
|
||||
emit q->configNeedsSaving();
|
||||
}
|
||||
|
||||
void ContainmentPrivate::appletAppeared(Applet *applet)
|
||||
{
|
||||
//kDebug() << type << Containment::DesktopContainment;
|
||||
KConfigGroup *cg = applet->d->mainConfigGroup();
|
||||
applet->save(*cg);
|
||||
emit q->configNeedsSaving();
|
||||
}
|
||||
|
||||
bool ContainmentPrivate::isPanelContainment() const
|
||||
{
|
||||
return type == Containment::PanelContainment || type == Containment::CustomPanelContainment;
|
||||
}
|
||||
|
||||
bool ContainmentPrivate::prepareContainmentActions(const QString &trigger, const QPoint &screenPos, KMenu *menu)
|
||||
{
|
||||
ContainmentActions *plugin = actionPlugins()->value(trigger);
|
||||
if (!plugin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plugin->containment() != q) {
|
||||
plugin->setContainment(q);
|
||||
|
||||
// now configure it
|
||||
KConfigGroup cfg = q->containmentActionsConfig();
|
||||
KConfigGroup pluginConfig = KConfigGroup(&cfg, trigger);
|
||||
plugin->restore(pluginConfig);
|
||||
}
|
||||
|
||||
if (plugin->configurationRequired()) {
|
||||
KMenu *localMenu = menu ? menu : new KMenu();
|
||||
|
||||
localMenu->addTitle(i18n("This plugin needs to be configured"));
|
||||
localMenu->addAction(q->action("configure"));
|
||||
|
||||
if (!menu) {
|
||||
localMenu->exec(screenPos);
|
||||
delete localMenu;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (menu) {
|
||||
QList<QAction*> actions = plugin->contextualActions();
|
||||
if (actions.isEmpty()) {
|
||||
//it probably didn't bother implementing the function. give the user a chance to set
|
||||
//a better plugin. note that if the user sets no-plugin this won't happen...
|
||||
if (!isPanelContainment() && q->action("configure")) {
|
||||
menu->addAction(q->action("configure"));
|
||||
}
|
||||
} else {
|
||||
menu->addActions(actions);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QHash<QString, ContainmentActions*> * ContainmentPrivate::actionPlugins()
|
||||
{
|
||||
switch (containmentActionsSource) {
|
||||
case Activity:
|
||||
//FIXME
|
||||
case Local:
|
||||
return &localActionPlugins;
|
||||
default:
|
||||
return &globalActionPlugins;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
155
plasma/private/containment_p.h
Normal file
155
plasma/private/containment_p.h
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2007 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
*
|
||||
* 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 CONTAINMENT_P_H
|
||||
#define CONTAINMENT_P_H
|
||||
|
||||
#include <kactioncollection.h>
|
||||
#include <kmenu.h>
|
||||
|
||||
#include "plasma.h"
|
||||
#include "applet.h"
|
||||
#include "corona.h"
|
||||
|
||||
static const int INTER_CONTAINMENT_MARGIN = 6;
|
||||
static const int CONTAINMENT_COLUMNS = 2;
|
||||
static const int VERTICAL_STACKING_OFFSET = 10000;
|
||||
|
||||
class KJob;
|
||||
|
||||
namespace KIO
|
||||
{
|
||||
class Job;
|
||||
}
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class AccessAppletJob;
|
||||
class Containment;
|
||||
|
||||
class ContainmentPrivate
|
||||
{
|
||||
public:
|
||||
ContainmentPrivate(Containment *c)
|
||||
: q(c),
|
||||
formFactor(Planar),
|
||||
location(Floating),
|
||||
screen(-1), // no screen
|
||||
lastScreen(-1),
|
||||
desktop(-1), // all desktops
|
||||
lastDesktop(-1),
|
||||
type(Containment::NoContainmentType),
|
||||
drawWallpaper(true),
|
||||
containmentActionsSource(Global)
|
||||
{
|
||||
}
|
||||
|
||||
~ContainmentPrivate()
|
||||
{
|
||||
// qDeleteAll is broken with Qt4.8, delete it by hand
|
||||
while (!applets.isEmpty()) {
|
||||
delete applets.first();
|
||||
}
|
||||
applets.clear();
|
||||
}
|
||||
|
||||
void triggerShowAddWidgets();
|
||||
void requestConfiguration();
|
||||
void checkStatus(Plasma::ItemStatus status);
|
||||
void setScreen(int newScreen, int newDesktop, bool preventInvalidDesktops = true);
|
||||
|
||||
/**
|
||||
* Called when constraints have been updated on this containment to provide
|
||||
* constraint services common to all containments. Containments should still
|
||||
* implement their own constraintsEvent method
|
||||
*/
|
||||
void containmentConstraintsEvent(Plasma::Constraints constraints);
|
||||
|
||||
void initApplets();
|
||||
void checkContainmentFurniture();
|
||||
bool isPanelContainment() const;
|
||||
void setLockToolText();
|
||||
void appletDeleted(Applet*);
|
||||
void appletAppeared(Applet*);
|
||||
void addContainmentActions(KMenu &desktopMenu, QEvent *event);
|
||||
void addAppletActions(KMenu &desktopMenu, Applet *applet, QEvent *event);
|
||||
void checkRemoveAction();
|
||||
void configChanged();
|
||||
|
||||
Applet *addApplet(const QString &name, const QVariantList &args = QVariantList(),
|
||||
const QRectF &geometry = QRectF(-1, -1, -1, -1), uint id = 0,
|
||||
bool delayedInit = false);
|
||||
|
||||
KActionCollection *actions();
|
||||
|
||||
/**
|
||||
* add the regular actions & keyboard shortcuts onto Applet's collection
|
||||
*/
|
||||
static void addDefaultActions(KActionCollection *actions, Containment *c = 0);
|
||||
|
||||
/**
|
||||
* inits the containmentactions if necessary
|
||||
* if it needs configuring, this warns the user and returns false
|
||||
* if a menu is passed in, then it populates that menu with the actions from the plugin
|
||||
* @param trigger the string to identify the correct plugin with
|
||||
* @param screenPos used to show the configure menu, only used if no menu is passed in
|
||||
* @param menu an optional menu to use to populate with actions, instead of triggering the
|
||||
* action directly
|
||||
* @return true if it's ok to run the action
|
||||
*/
|
||||
bool prepareContainmentActions(const QString &trigger, const QPoint &screenPos, KMenu *menu = 0);
|
||||
|
||||
|
||||
|
||||
QHash<QString, ContainmentActions*> *actionPlugins();
|
||||
|
||||
static bool s_positioningPanels;
|
||||
|
||||
Containment *q;
|
||||
FormFactor formFactor;
|
||||
Location location;
|
||||
Applet::List applets;
|
||||
QString wallpaper;
|
||||
QString wallpaperMode;
|
||||
QHash<QString, ContainmentActions*> localActionPlugins;
|
||||
int screen;
|
||||
int lastScreen;
|
||||
int desktop;
|
||||
int lastDesktop;
|
||||
QList<QAction *> toolBoxActions;
|
||||
QString activityId;
|
||||
Containment::Type type;
|
||||
bool drawWallpaper : 1;
|
||||
|
||||
enum ContainmentActionsSource {
|
||||
Global = 0,
|
||||
Activity,
|
||||
Local
|
||||
};
|
||||
ContainmentActionsSource containmentActionsSource;
|
||||
static QHash<QString, ContainmentActions*> globalActionPlugins;
|
||||
static const char defaultWallpaper[];
|
||||
static const char defaultWallpaperMode[];
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif
|
50
plasma/private/containmentactions_p.h
Normal file
50
plasma/private/containmentactions_p.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 PLASMA_CONTAINMENTACTIONSPRIVATE_H
|
||||
#define PLASMA_CONTAINMENTACTIONSPRIVATE_H
|
||||
|
||||
#include "dataengineconsumer.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ContainmentActionsPrivate : public DataEngineConsumer
|
||||
{
|
||||
public:
|
||||
ContainmentActionsPrivate(KService::Ptr service, ContainmentActions *containmentActions) :
|
||||
q(containmentActions),
|
||||
containmentActionsDescription(service),
|
||||
package(0),
|
||||
containment(0),
|
||||
needsConfig(false)
|
||||
{
|
||||
};
|
||||
|
||||
ContainmentActions *q;
|
||||
KPluginInfo containmentActionsDescription;
|
||||
Package *package;
|
||||
KServiceAction mode;
|
||||
Containment *containment;
|
||||
bool needsConfig;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
#endif //PLASMA_CONTAINMENTACTIONSPRIVATE_H
|
||||
|
47
plasma/private/containmentactionspluginsconfig_p.h
Normal file
47
plasma/private/containmentactionspluginsconfig_p.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Chani Armitage <chani@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 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 PLASMA_CONTAINMENTACTIONSPLUGINSCONFIGPRIVATE_H
|
||||
#define PLASMA_CONTAINMENTACTIONSPLUGINSCONFIGPRIVATE_H
|
||||
|
||||
#include <QHash>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class ContainmentActionsPluginsConfigPrivate
|
||||
{
|
||||
public:
|
||||
ContainmentActionsPluginsConfigPrivate(ContainmentActionsPluginsConfig *config)
|
||||
: q(config)
|
||||
{
|
||||
}
|
||||
|
||||
~ContainmentActionsPluginsConfigPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
ContainmentActionsPluginsConfig *q;
|
||||
//map trigger -> pluginname
|
||||
QHash<QString, QString> plugins;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
#endif
|
||||
|
76
plasma/private/corona_p.h
Normal file
76
plasma/private/corona_p.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2007-2011 Aaron Seigo <aseigo@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 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 PLASMA_CORONA_P_H
|
||||
#define PLASMA_CORONA_P_H
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include <kactioncollection.h>
|
||||
|
||||
class KShortcutsDialog;
|
||||
class QGraphicsWidget;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class Containment;
|
||||
|
||||
class CoronaPrivate
|
||||
{
|
||||
public:
|
||||
CoronaPrivate(Corona *corona);
|
||||
~CoronaPrivate();
|
||||
|
||||
void init();
|
||||
void showShortcutConfig();
|
||||
void toggleImmutability();
|
||||
void saveLayout(KSharedConfigPtr cg) const;
|
||||
void updateContainmentImmutability();
|
||||
void containmentDestroyed(QObject *obj);
|
||||
void syncConfig();
|
||||
Containment *addContainment(const QString &name, const QVariantList &args, uint id);
|
||||
void delayedContainmentInit();
|
||||
void offscreenWidgetDestroyed(QObject *);
|
||||
QList<Plasma::Containment *> importLayout(const KConfigGroup &conf, bool mergeConfig);
|
||||
|
||||
static bool s_positioningContainments;
|
||||
|
||||
Corona *q;
|
||||
ImmutabilityType immutability;
|
||||
QString mimetype;
|
||||
QString configName;
|
||||
QString defaultContainmentPlugin;
|
||||
KSharedConfigPtr config;
|
||||
QTimer *configSyncTimer;
|
||||
QTimer *delayedInitTimer;
|
||||
QList<Containment*> containments;
|
||||
QList<QWeakPointer<Containment> > containmentsNeedingInit;
|
||||
QHash<uint, QGraphicsWidget*> offscreenWidgets;
|
||||
KActionCollection actions;
|
||||
QMap<Containment::Type, ContainmentActionsPluginsConfig> containmentActionsDefaults;
|
||||
QWeakPointer<KShortcutsDialog> shortcutsDlg;
|
||||
QWeakPointer<AbstractDialogManager> dialogManager;
|
||||
QHash<Containment::Type, QString> toolBoxPlugins;
|
||||
QList<QWeakPointer<KActionCollection> > actionCollections;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
171
plasma/private/datacontainer_p.cpp
Normal file
171
plasma/private/datacontainer_p.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 "datacontainer.h" //krazy:exclude=includes
|
||||
#include "datacontainer_p.h" //krazy:exclude=includes
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
SignalRelay *DataContainerPrivate::signalRelay(const DataContainer *dc, QObject *visualization,
|
||||
uint pollingInterval,
|
||||
Plasma::IntervalAlignment align,
|
||||
bool immediateUpdate)
|
||||
{
|
||||
QMap<uint, SignalRelay *>::const_iterator relayIt = relays.constFind(pollingInterval);
|
||||
SignalRelay *relay = 0;
|
||||
|
||||
//FIXME what if we have two applets with the same interval and different alignment?
|
||||
if (relayIt == relays.constEnd()) {
|
||||
relay = new SignalRelay(const_cast<DataContainer*>(dc), this,
|
||||
pollingInterval, align, immediateUpdate);
|
||||
relays[pollingInterval] = relay;
|
||||
} else {
|
||||
relay = relayIt.value();
|
||||
}
|
||||
|
||||
relayObjects[visualization] = relay;
|
||||
return relay;
|
||||
}
|
||||
|
||||
bool DataContainerPrivate::hasUpdates()
|
||||
{
|
||||
if (cached) {
|
||||
// SignalRelay needs us to pretend we did an update
|
||||
cached = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return dirty;
|
||||
}
|
||||
|
||||
SignalRelay::SignalRelay(DataContainer *parent, DataContainerPrivate *data, uint ival,
|
||||
Plasma::IntervalAlignment align, bool immediateUpdate)
|
||||
: QObject(parent),
|
||||
dc(parent),
|
||||
d(data),
|
||||
m_interval(ival),
|
||||
m_align(align),
|
||||
m_resetTimer(true),
|
||||
m_queued(true)
|
||||
{
|
||||
//kDebug() << "signal relay with time of" << m_timerId << "being set up";
|
||||
m_timerId = startTimer(immediateUpdate ? 0 : m_interval);
|
||||
if (m_align != Plasma::NoAlignment) {
|
||||
checkAlignment();
|
||||
}
|
||||
}
|
||||
|
||||
int SignalRelay::receiverCount() const
|
||||
{
|
||||
return receivers(SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)));
|
||||
}
|
||||
|
||||
bool SignalRelay::isUnused() const
|
||||
{
|
||||
return receivers(SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data))) < 1;
|
||||
}
|
||||
|
||||
void SignalRelay::checkAlignment()
|
||||
{
|
||||
int newTime = 0;
|
||||
|
||||
QTime t = QTime::currentTime();
|
||||
if (m_align == Plasma::AlignToMinute) {
|
||||
int seconds = t.second();
|
||||
if (seconds > 2) {
|
||||
newTime = ((60 - seconds) * 1000) + 500;
|
||||
}
|
||||
} else if (m_align == Plasma::AlignToHour) {
|
||||
int minutes = t.minute();
|
||||
int seconds = t.second();
|
||||
if (minutes > 1 || seconds > 10) {
|
||||
newTime = ((60 - minutes) * 1000 * 60) +
|
||||
((60 - seconds) * 1000) + 500;
|
||||
}
|
||||
}
|
||||
|
||||
if (newTime) {
|
||||
killTimer(m_timerId);
|
||||
m_timerId = startTimer(newTime);
|
||||
m_resetTimer = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SignalRelay::checkQueueing()
|
||||
{
|
||||
//kDebug() << m_queued;
|
||||
if (m_queued) {
|
||||
emit dataUpdated(dc->objectName(), d->data);
|
||||
m_queued = false;
|
||||
//TODO: should we re-align our timer at this point, to avoid
|
||||
// constant queueing due to more-or-less constant time
|
||||
// async update time? this might make sense for
|
||||
// staggered accesses to the same source by multiple
|
||||
// visualizations causing a minimumPollingInterval violation.
|
||||
// it may not make sense for purely async-and-takes-a-while
|
||||
// type operations (e.g. network fetching).
|
||||
// we need more real world data before making such a change
|
||||
// change
|
||||
//
|
||||
// killTimer(m_timerId);
|
||||
// m_timerId = startTime(m_interval);
|
||||
}
|
||||
}
|
||||
|
||||
void SignalRelay::forceImmediateUpdate()
|
||||
{
|
||||
emit dataUpdated(dc->objectName(), d->data);
|
||||
}
|
||||
|
||||
void SignalRelay::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (event->timerId() != m_timerId) {
|
||||
QObject::timerEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_resetTimer) {
|
||||
killTimer(m_timerId);
|
||||
m_timerId = startTimer(m_interval);
|
||||
m_resetTimer = false;
|
||||
}
|
||||
|
||||
if (m_align != Plasma::NoAlignment) {
|
||||
checkAlignment();
|
||||
}
|
||||
|
||||
emit dc->updateRequested(dc);
|
||||
if (d->hasUpdates()) {
|
||||
//kDebug() << "emitting data updated directly" << d->data;
|
||||
emit dataUpdated(dc->objectName(), d->data);
|
||||
m_queued = false;
|
||||
} else {
|
||||
// the source wasn't actually updated; so let's put ourselves in the queue
|
||||
// so we get a dataUpdated() call when the data does arrive
|
||||
//kDebug() << "queued";
|
||||
m_queued = true;
|
||||
}
|
||||
}
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
|
||||
|
||||
#include "moc_datacontainer_p.cpp"
|
130
plasma/private/datacontainer_p.h
Normal file
130
plasma/private/datacontainer_p.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 PLASMA_DATACONTAINER_P_H
|
||||
#define PLASMA_DATACONTAINER_P_H
|
||||
|
||||
#include "servicejob.h"
|
||||
#include "storage_p.h"
|
||||
|
||||
#include <QtCore/QTimerEvent>
|
||||
#include <QtCore/QTime>
|
||||
#include <QtCore/QBasicTimer>
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
class ServiceJob;
|
||||
class SignalRelay;
|
||||
|
||||
class DataContainerPrivate
|
||||
{
|
||||
public:
|
||||
DataContainerPrivate(DataContainer *container)
|
||||
: q(container),
|
||||
storage(NULL),
|
||||
storageCount(0),
|
||||
dirty(false),
|
||||
cached(false),
|
||||
enableStorage(false),
|
||||
isStored(true)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the DataContainer is still in use.
|
||||
*
|
||||
* If not the signal "becameUnused" will be emitted.
|
||||
*
|
||||
* Warning: The DataContainer may be invalid after calling this function, because a listener
|
||||
* to becameUnused() may have deleted it.
|
||||
**/
|
||||
void checkUsage();
|
||||
|
||||
SignalRelay *signalRelay(const DataContainer *dc, QObject *visualization,
|
||||
uint pollingInterval, Plasma::IntervalAlignment align,
|
||||
bool immediateUpdate);
|
||||
|
||||
bool hasUpdates();
|
||||
|
||||
/**
|
||||
* Deletes the store member of DataContainerPrivate if
|
||||
* there are no more references to it.
|
||||
*/
|
||||
void storeJobFinished(KJob *job);
|
||||
|
||||
/**
|
||||
* Does the work of putting the data from disk into the DataContainer
|
||||
* after retrieve() sets it up.
|
||||
*/
|
||||
void populateFromStoredData(KJob *job);
|
||||
|
||||
void store();
|
||||
void retrieve();
|
||||
|
||||
DataContainer *q;
|
||||
DataEngine::Data data;
|
||||
QMap<QObject *, SignalRelay *> relayObjects;
|
||||
QMap<uint, SignalRelay *> relays;
|
||||
QTime updateTs;
|
||||
Storage* storage;
|
||||
QBasicTimer storageTimer;
|
||||
QBasicTimer checkUsageTimer;
|
||||
int storageCount;
|
||||
bool dirty : 1;
|
||||
bool cached : 1;
|
||||
bool enableStorage : 1;
|
||||
bool isStored : 1;
|
||||
};
|
||||
|
||||
class SignalRelay : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SignalRelay(DataContainer *parent, DataContainerPrivate *data,
|
||||
uint ival, Plasma::IntervalAlignment align, bool immediateUpdate);
|
||||
|
||||
int receiverCount() const;
|
||||
bool isUnused() const;
|
||||
|
||||
void checkAlignment();
|
||||
void checkQueueing();
|
||||
void forceImmediateUpdate();
|
||||
|
||||
DataContainer *dc;
|
||||
DataContainerPrivate *d;
|
||||
uint m_interval;
|
||||
Plasma::IntervalAlignment m_align;
|
||||
int m_timerId;
|
||||
bool m_resetTimer;
|
||||
bool m_queued;
|
||||
|
||||
signals:
|
||||
void dataUpdated(const QString &, const Plasma::DataEngine::Data &);
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *event);
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif // multiple inclusion guard
|
||||
|
122
plasma/private/dataengine_p.h
Normal file
122
plasma/private/dataengine_p.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 DATAENGINE_P_H
|
||||
#define DATAENGINE_P_H
|
||||
|
||||
#include <QTime>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
|
||||
class QTime;
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class Service;
|
||||
|
||||
class DataEnginePrivate
|
||||
{
|
||||
public:
|
||||
DataEnginePrivate(DataEngine *e, const KPluginInfo &info);
|
||||
~DataEnginePrivate();
|
||||
DataContainer *source(const QString &sourceName, bool createWhenMissing = true);
|
||||
void connectSource(DataContainer *s, QObject *visualization, uint pollingInterval,
|
||||
Plasma::IntervalAlignment align, bool immediateCall = true);
|
||||
DataContainer *requestSource(const QString &sourceName, bool *newSource = 0);
|
||||
void internalUpdateSource(DataContainer*);
|
||||
void setupScriptSupport();
|
||||
|
||||
/**
|
||||
* Reference counting method. Calling this method increases the count
|
||||
* by one.
|
||||
**/
|
||||
void ref();
|
||||
|
||||
/**
|
||||
* Reference counting method. Calling this method decreases the count
|
||||
* by one.
|
||||
**/
|
||||
void deref();
|
||||
|
||||
/**
|
||||
* Reference counting method. Used to determine if this DataEngine is
|
||||
* used.
|
||||
* @return true if the reference count is non-zero
|
||||
**/
|
||||
bool isUsed() const;
|
||||
|
||||
/**
|
||||
* @param methods ways to announce this engine on the network.
|
||||
*/
|
||||
void publish(AnnouncementMethods methods, const QString &name);
|
||||
|
||||
/**
|
||||
* remove this engine from the network.
|
||||
*/
|
||||
void unpublish(const QString &name = QString());
|
||||
|
||||
/**
|
||||
* @return whether or not this engine is published.
|
||||
*/
|
||||
bool isPublished() const;
|
||||
|
||||
/**
|
||||
* a datacontainer has been destroyed, clean up stuff
|
||||
*/
|
||||
void sourceDestroyed(QObject *object);
|
||||
|
||||
/**
|
||||
* stores the source
|
||||
* @param sourceName the name of the source to store
|
||||
*/
|
||||
void storeSource(DataContainer *source) const;
|
||||
|
||||
/**
|
||||
* stores all sources marked for storage
|
||||
*/
|
||||
void storeAllSources();
|
||||
|
||||
/**
|
||||
* retrieves source data
|
||||
* @param the data container to populate
|
||||
*/
|
||||
void retrieveStoredData(DataContainer *s);
|
||||
|
||||
DataEngine *q;
|
||||
KPluginInfo dataEngineDescription;
|
||||
int refCount;
|
||||
int checkSourcesTimerId;
|
||||
int updateTimerId;
|
||||
int minPollingInterval;
|
||||
QTime updateTimestamp;
|
||||
DataEngine::SourceDict sources;
|
||||
QString icon;
|
||||
bool valid;
|
||||
DataEngineScript *script;
|
||||
QString engineName;
|
||||
QString serviceName;
|
||||
Package *package;
|
||||
Service *publishedService;
|
||||
QString waitingSourceRequest;
|
||||
};
|
||||
|
||||
} // Plasma namespace
|
||||
|
||||
#endif // multiple inclusion guard
|
56
plasma/private/dataengineconsumer_p.h
Normal file
56
plasma/private/dataengineconsumer_p.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2005 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>
|
||||
* Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
|
||||
*
|
||||
* 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 PLASMA_DATAENGINECONSUMER_P_H
|
||||
#define PLASMA_DATAENGINECONSUMER_P_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QUrl>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataEngineConsumer;
|
||||
class RemoteDataEngine;
|
||||
class Service;
|
||||
class ServiceMonitor;
|
||||
class ServiceJob;
|
||||
|
||||
class DataEngineConsumerPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QSet<QString> loadedEngines;
|
||||
QMap<QPair<QString, QString>, RemoteDataEngine*> remoteEngines;
|
||||
QMap<Service*, QString> engineNameForService;
|
||||
DataEngine *remoteDataEngine(const QString &name, const QUrl &location);
|
||||
|
||||
public Q_SLOTS:
|
||||
void slotJobFinished(Plasma::ServiceJob *job);
|
||||
void slotServiceReady(Plasma::Service *service);
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
213
plasma/private/dataenginemanager.cpp
Normal file
213
plasma/private/dataenginemanager.cpp
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 "dataenginemanager_p.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <kdebug.h>
|
||||
#include <klocale.h>
|
||||
|
||||
#include <kservicetypetrader.h>
|
||||
#include <qstandardpaths.h>
|
||||
|
||||
#include "datacontainer.h"
|
||||
#include "pluginloader.h"
|
||||
#include "private/componentinstaller_p.h"
|
||||
#include "private/dataengine_p.h"
|
||||
#include "private/datacontainer_p.h"
|
||||
#include "scripting/scriptengine.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class NullEngine : public DataEngine
|
||||
{
|
||||
public:
|
||||
NullEngine(QObject *parent = 0)
|
||||
: DataEngine(parent)
|
||||
{
|
||||
setValid(false);
|
||||
|
||||
// ref() ourselves to ensure we never get deleted
|
||||
d->ref();
|
||||
}
|
||||
};
|
||||
|
||||
class DataEngineManagerPrivate
|
||||
{
|
||||
public:
|
||||
DataEngineManagerPrivate()
|
||||
: nullEng(0)
|
||||
{}
|
||||
|
||||
~DataEngineManagerPrivate()
|
||||
{
|
||||
foreach (Plasma::DataEngine *engine, engines) {
|
||||
delete engine;
|
||||
}
|
||||
engines.clear();
|
||||
delete nullEng;
|
||||
}
|
||||
|
||||
DataEngine *nullEngine()
|
||||
{
|
||||
if (!nullEng) {
|
||||
nullEng = new NullEngine;
|
||||
}
|
||||
|
||||
return nullEng;
|
||||
}
|
||||
|
||||
DataEngine::Dict engines;
|
||||
DataEngine *nullEng;
|
||||
};
|
||||
|
||||
class DataEngineManagerSingleton
|
||||
{
|
||||
public:
|
||||
DataEngineManager self;
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(DataEngineManagerSingleton, privateDataEngineManagerSelf)
|
||||
|
||||
DataEngineManager *DataEngineManager::self()
|
||||
{
|
||||
return &privateDataEngineManagerSelf()->self;
|
||||
}
|
||||
|
||||
DataEngineManager::DataEngineManager()
|
||||
: d(new DataEngineManagerPrivate)
|
||||
{
|
||||
//startTimer(30000);
|
||||
}
|
||||
|
||||
DataEngineManager::~DataEngineManager()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
Plasma::DataEngine *DataEngineManager::engine(const QString &name) const
|
||||
{
|
||||
if (name.isEmpty()) {
|
||||
return d->nullEngine();
|
||||
}
|
||||
|
||||
Plasma::DataEngine::Dict::const_iterator it = d->engines.constFind(name);
|
||||
if (it != d->engines.constEnd()) {
|
||||
// ref and return the engine
|
||||
//Plasma::DataEngine *engine = *it;
|
||||
return *it;
|
||||
}
|
||||
|
||||
return d->nullEngine();
|
||||
}
|
||||
|
||||
Plasma::DataEngine *DataEngineManager::loadEngine(const QString &name)
|
||||
{
|
||||
Plasma::DataEngine::Dict::const_iterator it = d->engines.constFind(name);
|
||||
|
||||
if (it != d->engines.constEnd()) {
|
||||
DataEngine *engine = *it;
|
||||
engine->d->ref();
|
||||
return engine;
|
||||
}
|
||||
|
||||
DataEngine *engine = PluginLoader::self()->loadDataEngine(name);
|
||||
if (!engine) {
|
||||
// Try installing the engine. However, it's too late for this request.
|
||||
ComponentInstaller::self()->installMissingComponent("dataengine", name);
|
||||
|
||||
return d->nullEngine();
|
||||
}
|
||||
|
||||
engine->init();
|
||||
d->engines[name] = engine;
|
||||
return engine;
|
||||
}
|
||||
|
||||
void DataEngineManager::unloadEngine(const QString &name)
|
||||
{
|
||||
Plasma::DataEngine::Dict::iterator it = d->engines.find(name);
|
||||
|
||||
if (it != d->engines.end()) {
|
||||
Plasma::DataEngine *engine = *it;
|
||||
engine->d->deref();
|
||||
|
||||
if (!engine->d->isUsed()) {
|
||||
d->engines.erase(it);
|
||||
delete engine;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngineManager::timerEvent(QTimerEvent *)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QLatin1Char('/') + "plasma_dataenginemanager_log";
|
||||
QFile f(path);
|
||||
if (!f.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
|
||||
kDebug() << "faild to open" << path;
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream out(&f);
|
||||
|
||||
QHashIterator<QString, DataEngine*> it(d->engines);
|
||||
out << "================================== " << KLocale::global()->formatDateTime(QDateTime::currentDateTime()) << endl;
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
DataEngine *engine = it.value();
|
||||
out << "DataEngine: " << it.key() << ' ' << engine << endl;
|
||||
out << " Claimed # of sources: " << engine->sources().count() << endl;
|
||||
out << " Actual # of sources: " << engine->containerDict().count() << endl;
|
||||
out << endl << " Source Details" << endl;
|
||||
|
||||
foreach (DataContainer *dc, engine->containerDict()) {
|
||||
out << " * " << dc->objectName() << endl;
|
||||
out << " Data count: " << dc->d->data.count() << endl;
|
||||
out << " Stored: " << dc->isStorageEnabled() << ' ' << endl;
|
||||
const int directs = dc->receivers(SIGNAL(dataUpdated(QString,Plasma::DataEngine::Data)));
|
||||
if (directs > 0) {
|
||||
out << " Direction Connections: " << directs << ' ' << endl;
|
||||
}
|
||||
|
||||
const int relays = dc->d->relays.count();
|
||||
if (relays > 0) {
|
||||
out << " Relays: " << dc->d->relays.count() << endl;
|
||||
QString times;
|
||||
foreach (SignalRelay *relay, dc->d->relays) {
|
||||
times.append(' ').append(QString::number(relay->m_interval));
|
||||
}
|
||||
out << " Relay Timeouts: " << times << ' ' << endl;
|
||||
}
|
||||
}
|
||||
|
||||
out << endl << "-----" << endl;
|
||||
}
|
||||
out << endl << endl;
|
||||
#endif
|
||||
// killTimer(event->timerId());
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
|
||||
#include "moc_dataenginemanager_p.cpp"
|
99
plasma/private/dataenginemanager_p.h
Normal file
99
plasma/private/dataenginemanager_p.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2006-2007 Aaron Seigo <aseigo@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 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 PLASMA_DATAENGINEMANAGER_H
|
||||
#define PLASMA_DATAENGINEMANAGER_H
|
||||
|
||||
#include <QtCore/QHash>
|
||||
|
||||
#include <kplugininfo.h>
|
||||
|
||||
#include <plasma/dataengine.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataEngineManagerPrivate;
|
||||
|
||||
/**
|
||||
* @class DataEngineManager plasma/dataenginemanager.h <Plasma/DataEngineManager>
|
||||
*
|
||||
* @short DataEngine loader and life time manager
|
||||
*
|
||||
* Plasma::DataEngineManager provides facilities for listing, loading and
|
||||
* according to reference count unloading of DataEngines.
|
||||
**/
|
||||
class PLASMA_EXPORT DataEngineManager: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* Singleton pattern accessor.
|
||||
*/
|
||||
static DataEngineManager *self();
|
||||
|
||||
/**
|
||||
* Returns a data engine object if one is loaded and available.
|
||||
* On failure, the fallback NullEngine (which does nothing and
|
||||
* !isValid()) is returned.
|
||||
*
|
||||
* @param name the name of the engine
|
||||
*/
|
||||
Plasma::DataEngine *engine(const QString &name) const;
|
||||
|
||||
/**
|
||||
* Loads a data engine and increases the reference count on it.
|
||||
* This should be called once per object (or set of objects) using the
|
||||
* DataEngine. Afterwards, dataEngine should be used or the return
|
||||
* value cached. Call unloadDataEngine when finished with the engine.
|
||||
*
|
||||
* @param name the name of the engine
|
||||
* @return the data engine that was loaded, or the NullEngine on failure.
|
||||
*/
|
||||
Plasma::DataEngine *loadEngine(const QString &name);
|
||||
|
||||
/**
|
||||
* Decreases the reference count on the engine. If the count reaches
|
||||
* zero, then the engine is deleted to save resources.
|
||||
*/
|
||||
void unloadEngine(const QString &name);
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Reimplemented from QObject
|
||||
**/
|
||||
void timerEvent(QTimerEvent *event);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Default constructor. The singleton method self() is the
|
||||
* preferred access mechanism.
|
||||
*/
|
||||
DataEngineManager();
|
||||
~DataEngineManager();
|
||||
|
||||
DataEngineManagerPrivate *const d;
|
||||
|
||||
friend class DataEngineManagerSingleton;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif // multiple inclusion guard
|
59
plasma/private/dataengineservice.cpp
Normal file
59
plasma/private/dataengineservice.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright © 2009 Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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 "dataengineservice_p.h"
|
||||
|
||||
#include "../dataengine.h"
|
||||
#include "getsource_p.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
DataEngineService::DataEngineService(DataEngine *engine)
|
||||
: Plasma::Service(engine),
|
||||
m_engine(engine)
|
||||
{
|
||||
setName("dataengineservice");
|
||||
engine->connectAllSources(this, 1000);
|
||||
connect(engine, SIGNAL(sourceAdded(QString)), this, SLOT(sourceAdded(QString)));
|
||||
}
|
||||
|
||||
Plasma::ServiceJob* DataEngineService::createJob(const QString& operation, QHash<QString,QVariant>& parameters)
|
||||
{
|
||||
return new GetSource(m_engine, operation, parameters, this);
|
||||
}
|
||||
|
||||
void DataEngineService::dataUpdated(QString source, Plasma::DataEngine::Data data)
|
||||
{
|
||||
if (data != m_data[source]) {
|
||||
m_data[source] = data;
|
||||
m_peersAlreadyUpdated[source] = QStringList();
|
||||
}
|
||||
}
|
||||
|
||||
void DataEngineService::sourceAdded(QString source)
|
||||
{
|
||||
m_engine->connectSource(source, this, 1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "moc_dataengineservice_p.cpp"
|
||||
|
60
plasma/private/dataengineservice_p.h
Normal file
60
plasma/private/dataengineservice_p.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright © 2009 Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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 PLASMA_DATAENGINESERVICE_P_H
|
||||
#define PLASMA_DATAENGINESERVICE_P_H
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#include "../dataengine.h"
|
||||
#include "../service.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataEngine;
|
||||
class GetSource;
|
||||
|
||||
class DataEngineService : public Plasma::Service
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DataEngineService(DataEngine *engine);
|
||||
|
||||
public Q_SLOTS:
|
||||
void dataUpdated(QString source, Plasma::DataEngine::Data data);
|
||||
|
||||
protected:
|
||||
Plasma::ServiceJob* createJob(const QString& operation,
|
||||
QHash<QString,QVariant>& parameters);
|
||||
|
||||
private Q_SLOTS:
|
||||
void sourceAdded(QString source);
|
||||
|
||||
private:
|
||||
DataEngine *m_engine;
|
||||
QHash<QString, QStringList> m_peersAlreadyUpdated;
|
||||
QHash<QString, DataEngine::Data> m_data;
|
||||
|
||||
friend class GetSource;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // PLASMA_DATAENGINESERVICE_P_H
|
66
plasma/private/declarative/dataenginebindings.cpp
Normal file
66
plasma/private/declarative/dataenginebindings.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2007 Richard J. Moore <rich@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 version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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 "dataenginebindings_p.h"
|
||||
|
||||
typedef Plasma::Service *ServicePtr;
|
||||
QScriptValue qScriptValueFromService(QScriptEngine *engine, const ServicePtr &service)
|
||||
{
|
||||
return engine->newQObject(const_cast<Plasma::Service *>(service), QScriptEngine::AutoOwnership, QScriptEngine::PreferExistingWrapperObject);
|
||||
}
|
||||
|
||||
void serviceFromQScriptValue(const QScriptValue &scriptValue, ServicePtr &service)
|
||||
{
|
||||
QObject *obj = scriptValue.toQObject();
|
||||
service = static_cast<Plasma::Service *>(obj);
|
||||
}
|
||||
|
||||
typedef Plasma::DataEngine *DataEnginePtr;
|
||||
QScriptValue qScriptValueFromDataEngine(QScriptEngine *engine, const DataEnginePtr &dataEngine)
|
||||
{
|
||||
return engine->newQObject(const_cast<Plasma::DataEngine *>(dataEngine), QScriptEngine::AutoOwnership, QScriptEngine::PreferExistingWrapperObject);
|
||||
}
|
||||
|
||||
void dataEngineFromQScriptValue(const QScriptValue &scriptValue, DataEnginePtr &dataEngine)
|
||||
{
|
||||
QObject *obj = scriptValue.toQObject();
|
||||
dataEngine = static_cast<Plasma::DataEngine *>(obj);
|
||||
}
|
||||
|
||||
typedef Plasma::ServiceJob *ServiceJobPtr;
|
||||
QScriptValue qScriptValueFromServiceJob(QScriptEngine *engine, const ServiceJobPtr &serviceJob)
|
||||
{
|
||||
return engine->newQObject(const_cast<Plasma::ServiceJob *>(serviceJob), QScriptEngine::AutoOwnership, QScriptEngine::PreferExistingWrapperObject);
|
||||
}
|
||||
|
||||
void serviceJobFromQScriptValue(const QScriptValue &scriptValue, ServiceJobPtr &serviceJob)
|
||||
{
|
||||
QObject *obj = scriptValue.toQObject();
|
||||
serviceJob = static_cast<Plasma::ServiceJob *>(obj);
|
||||
}
|
||||
|
||||
void registerDataEngineMetaTypes(QScriptEngine *engine)
|
||||
{
|
||||
qRegisterMetaType<Plasma::DataEngine::Data>("Plasma::DataEngine::Data");
|
||||
qRegisterMetaType<Plasma::DataEngine::Data>("DataEngine::Data");
|
||||
qScriptRegisterMapMetaType<Plasma::DataEngine::Data>(engine);
|
||||
qScriptRegisterMetaType<Plasma::Service *>(engine, qScriptValueFromService, serviceFromQScriptValue);
|
||||
qScriptRegisterMetaType<Plasma::DataEngine *>(engine, qScriptValueFromDataEngine, dataEngineFromQScriptValue);
|
||||
qScriptRegisterMetaType<Plasma::ServiceJob *>(engine, qScriptValueFromServiceJob, serviceJobFromQScriptValue);
|
||||
}
|
||||
|
83
plasma/private/declarative/dataenginebindings_p.h
Normal file
83
plasma/private/declarative/dataenginebindings_p.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2007 Richard J. Moore <rich@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 version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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 DATAENGINE_H
|
||||
#define DATAENGINE_H
|
||||
|
||||
#include <QScriptEngine>
|
||||
#include <QScriptValue>
|
||||
#include <QScriptValueIterator>
|
||||
#include <kdebug.h>
|
||||
|
||||
#include <dataengine.h>
|
||||
#include <service.h>
|
||||
#include <servicejob.h>
|
||||
|
||||
using namespace Plasma;
|
||||
|
||||
Q_DECLARE_METATYPE(DataEngine::Dict)
|
||||
Q_DECLARE_METATYPE(DataEngine::Data)
|
||||
|
||||
template <class M>
|
||||
QScriptValue qScriptValueFromMap(QScriptEngine *eng, const M &map)
|
||||
{
|
||||
//kDebug() << "qScriptValueFromMap called";
|
||||
QScriptValue obj = eng->newObject();
|
||||
typename M::const_iterator begin = map.constBegin();
|
||||
typename M::const_iterator end = map.constEnd();
|
||||
typename M::const_iterator it;
|
||||
for (it = begin; it != end; ++it) {
|
||||
if (it.value().type() == QVariant::Hash) {
|
||||
obj.setProperty(it.key(), qScriptValueFromMap(eng, it.value().toHash()));
|
||||
} else if (it.value().type() == QVariant::Map) {
|
||||
obj.setProperty(it.key(), qScriptValueFromMap(eng, it.value().toMap()));
|
||||
} else {
|
||||
obj.setProperty(it.key(), qScriptValueFromValue(eng, it.value()));
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <class M>
|
||||
void qScriptValueToMap(const QScriptValue &value, M &map)
|
||||
{
|
||||
//kDebug() << "qScriptValueToMap called";
|
||||
QScriptValueIterator it(value);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
map[it.name()] = qscriptvalue_cast<typename M::mapped_type>(it.value());
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int qScriptRegisterMapMetaType(
|
||||
QScriptEngine *engine,
|
||||
const QScriptValue &prototype = QScriptValue()
|
||||
#ifndef qdoc
|
||||
, T * /* dummy */ = 0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return qScriptRegisterMetaType<T>(engine, qScriptValueFromMap, qScriptValueToMap, prototype);
|
||||
}
|
||||
|
||||
void registerDataEngineMetaTypes(QScriptEngine *engine);
|
||||
|
||||
#endif // DATAENGINE_H
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* 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 "declarativenetworkaccessmanagerfactory_p.h"
|
||||
|
||||
#include "config-plasma.h"
|
||||
|
||||
#if !PLASMA_NO_KIO
|
||||
#include <kio/accessmanager.h>
|
||||
#else
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#endif
|
||||
|
||||
QNetworkAccessManager *DeclarativeNetworkAccessManagerFactory::create(QObject *parent)
|
||||
{
|
||||
#if !PLASMA_NO_KIO
|
||||
return new KIO::AccessManager(parent);
|
||||
#else
|
||||
return new QNetworkAccessManager(parent);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* 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 DECLARATIVENETWORKACCESSMANAGERFACTORY_H
|
||||
#define DECLARATIVENETWORKACCESSMANAGERFACTORY_H
|
||||
|
||||
#include <QDeclarativeNetworkAccessManagerFactory>
|
||||
|
||||
class DeclarativeNetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory
|
||||
{
|
||||
public:
|
||||
QNetworkAccessManager *create(QObject *parent);
|
||||
};
|
||||
|
||||
#endif
|
154
plasma/private/effects/blur.cpp
Normal file
154
plasma/private/effects/blur.cpp
Normal file
@ -0,0 +1,154 @@
|
||||
#ifndef BLUR_CPP
|
||||
#define BLUR_CPP
|
||||
|
||||
/*
|
||||
* Copyright 2007 Jani Huhtanen <jani.huhtanen@tut.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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 <cmath>
|
||||
|
||||
// Exponential blur, Jani Huhtanen, 2006
|
||||
//
|
||||
template<int aprec, int zprec>
|
||||
static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha);
|
||||
|
||||
template<int aprec,int zprec>
|
||||
static inline void blurrow(QImage &im, int line, int alpha);
|
||||
|
||||
template<int aprec, int zprec>
|
||||
static inline void blurcol(QImage &im, int col, int alpha);
|
||||
|
||||
/*
|
||||
* expblur(QImage &img, int radius)
|
||||
*
|
||||
* In-place blur of image 'img' with kernel
|
||||
* of approximate radius 'radius'.
|
||||
*
|
||||
* Blurs with two sided exponential impulse
|
||||
* response.
|
||||
*
|
||||
* aprec = precision of alpha parameter
|
||||
* in fixed-point format 0.aprec
|
||||
*
|
||||
* zprec = precision of state parameters
|
||||
* zR,zG,zB and zA in fp format 8.zprec
|
||||
*/
|
||||
template<int aprec,int zprec>
|
||||
void expblur(QImage &img, int radius)
|
||||
{
|
||||
if (radius < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
/* Calculate the alpha such that 90% of
|
||||
the kernel is within the radius.
|
||||
(Kernel extends to infinity)
|
||||
*/
|
||||
int alpha = (int)((1 << aprec) * (1.0f - std::exp(-2.3f / (radius + 1.f))));
|
||||
|
||||
int height = img.height();
|
||||
int width = img.width();
|
||||
for (int row=0; row<height; row++) {
|
||||
blurrow<aprec,zprec>(img, row, alpha);
|
||||
}
|
||||
|
||||
for (int col=0; col<width; col++) {
|
||||
blurcol<aprec,zprec>(img, col, alpha);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
template<int aprec, int zprec>
|
||||
static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha)
|
||||
{
|
||||
int R, G, B, A;
|
||||
R = *bptr;
|
||||
G = *(bptr + 1);
|
||||
B = *(bptr + 2);
|
||||
A = *(bptr + 3);
|
||||
|
||||
zR += (alpha * ((R << zprec) - zR)) >> aprec;
|
||||
zG += (alpha * ((G << zprec) - zG)) >> aprec;
|
||||
zB += (alpha * ((B << zprec) - zB)) >> aprec;
|
||||
zA += (alpha * ((A << zprec) - zA)) >> aprec;
|
||||
|
||||
*bptr = zR >> zprec;
|
||||
*(bptr+1) = zG >> zprec;
|
||||
*(bptr+2) = zB >> zprec;
|
||||
*(bptr+3) = zA >> zprec;
|
||||
}
|
||||
|
||||
template<int aprec,int zprec>
|
||||
static inline void blurrow(QImage &im, int line, int alpha)
|
||||
{
|
||||
int zR, zG, zB, zA;
|
||||
|
||||
QRgb *ptr = (QRgb *)im.scanLine(line);
|
||||
int width = im.width();
|
||||
|
||||
zR = *((unsigned char *)ptr ) << zprec;
|
||||
zG = *((unsigned char *)ptr + 1) << zprec;
|
||||
zB = *((unsigned char *)ptr + 2) << zprec;
|
||||
zA = *((unsigned char *)ptr + 3) << zprec;
|
||||
|
||||
for (int index=1; index<width; index++) {
|
||||
blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha);
|
||||
}
|
||||
for (int index=width-2; index>=0; index--) {
|
||||
blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha);
|
||||
}
|
||||
}
|
||||
|
||||
template<int aprec, int zprec>
|
||||
static inline void blurcol(QImage &im, int col, int alpha)
|
||||
{
|
||||
int zR, zG, zB, zA;
|
||||
|
||||
QRgb *ptr = (QRgb *)im.bits();
|
||||
ptr += col;
|
||||
int height = im.height();
|
||||
int width = im.width();
|
||||
|
||||
zR = *((unsigned char *)ptr ) << zprec;
|
||||
zG = *((unsigned char *)ptr + 1) << zprec;
|
||||
zB = *((unsigned char *)ptr + 2) << zprec;
|
||||
zA = *((unsigned char *)ptr + 3) << zprec;
|
||||
|
||||
for (int index=width; index<(height-1)*width; index+=width) {
|
||||
blurinner<aprec,zprec>((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha);
|
||||
}
|
||||
|
||||
for (int index=(height-2)*width; index>=0; index-=width) {
|
||||
blurinner<aprec,zprec>((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline const T &qClamp(const T &x, const T &low, const T &high)
|
||||
{
|
||||
if (x < low) {
|
||||
return low;
|
||||
} else if (x > high) {
|
||||
return high;
|
||||
} else {
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
250
plasma/private/effects/halopainter.cpp
Normal file
250
plasma/private/effects/halopainter.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
|
||||
*
|
||||
* This library 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 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 library; see the file COPYING.LIB. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "halopainter_p.h"
|
||||
#include <QPainter>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
static inline qreal gaussian(qreal x, qreal sigma)
|
||||
{
|
||||
return (1.0 / std::sqrt(2.0 * M_PI) * sigma)
|
||||
* std::exp(-((x * x) / (2.0 * sigma * sigma)));
|
||||
}
|
||||
|
||||
static void gaussianBlur(QImage &image, int radius)
|
||||
{
|
||||
// The gaussian curve is effectively zero after 3 standard deviations.
|
||||
qreal sigma = radius / 3.;
|
||||
int size = radius * 2 + 1;
|
||||
int center = size / 2;
|
||||
qreal *kernel = new qreal[size];
|
||||
qreal total = 0;
|
||||
|
||||
// Generate the gaussian kernel
|
||||
for (int i = 0; i < size; i++) {
|
||||
kernel[i] = gaussian(i - center, sigma);
|
||||
total += kernel[i];
|
||||
}
|
||||
|
||||
// Normalize the kernel
|
||||
for (int i = 0; i < size; i++)
|
||||
kernel[i] = kernel[i] / total;
|
||||
|
||||
quint32 *buf = new quint32[image.width() * image.height()];
|
||||
memset(buf, 0, image.width() * image.height() * sizeof(quint32));
|
||||
|
||||
// Blur the image horizontally
|
||||
for (int y = 0; y < image.height(); y++)
|
||||
{
|
||||
quint32 *src = (quint32*)image.scanLine(y);
|
||||
quint32 *dst = buf + image.width() * y;
|
||||
|
||||
for (int x = 0, start = center; x < center; x++, start--) {
|
||||
double a = 0;
|
||||
for (int i = start; i < size; i++)
|
||||
a += qAlpha(src[x - center + i]) * kernel[i];
|
||||
dst[x] = qRound(a) << 24;
|
||||
}
|
||||
|
||||
for (int x = center; x < image.width() - center; x++) {
|
||||
double a = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
a += qAlpha(src[x - center + i]) * kernel[i];
|
||||
dst[x] = qRound(a) << 24;
|
||||
}
|
||||
|
||||
for (int x = image.width() - center, stop = size - 1; x < image.width(); x++, stop--) {
|
||||
double a = 0;
|
||||
for (int i = 0; i < stop; i++)
|
||||
a += qAlpha(src[x - center + i]) * kernel[i];
|
||||
dst[x] = qRound(a) << 24;
|
||||
}
|
||||
}
|
||||
|
||||
// Blur the image vertically
|
||||
quint32 *src = buf;
|
||||
quint32 *dst = (quint32*)image.bits();
|
||||
|
||||
for (int x = 0; x < image.width(); x++)
|
||||
{
|
||||
int di = x;
|
||||
|
||||
for (int y = 0, start = center; y < center; y++, start--) {
|
||||
double a = 0;
|
||||
int si = (y - center + start) * image.width() + x;
|
||||
for (int i = start; i < size; i++) {
|
||||
a += qAlpha(src[si]) * kernel[i];
|
||||
si += image.width();
|
||||
}
|
||||
dst[di] = qRound(a) << 24;
|
||||
di += image.width();
|
||||
}
|
||||
|
||||
for (int y = center; y < image.height() - center; y++) {
|
||||
double a = 0;
|
||||
int si = (y - center) * image.width() + x;
|
||||
for (int i = 0; i < size; i++) {
|
||||
a += qAlpha(src[si]) * kernel[i];
|
||||
si += image.width();
|
||||
}
|
||||
dst[di] = qRound(a) << 24;
|
||||
di += image.width();
|
||||
}
|
||||
|
||||
for (int y = image.height() - center, stop = size - 1; y < image.height(); y++, stop--) {
|
||||
double a = 0;
|
||||
int si = (y - center) * image.width() + x;
|
||||
for (int i = 0; i < stop; i++) {
|
||||
a += qAlpha(src[si]) * kernel[i];
|
||||
si += image.width();
|
||||
}
|
||||
dst[di] = qRound(a) << 24;
|
||||
di += image.width();
|
||||
}
|
||||
}
|
||||
|
||||
delete [] buf;
|
||||
delete [] kernel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
TileSet::TileSet(const QPixmap &pixmap)
|
||||
{
|
||||
int tw = pixmap.width() / 3;
|
||||
int th = pixmap.height();
|
||||
|
||||
for (int x = 0; x < 3; x++)
|
||||
tiles[x] = pixmap.copy(x * tw, 0, tw, th);
|
||||
}
|
||||
|
||||
void TileSet::paint(QPainter *p, const QRect &r)
|
||||
{
|
||||
int tw = tiles[Left].width();
|
||||
int th = tiles[Left].height();
|
||||
int tw2 = tw * 2;
|
||||
|
||||
if (r.width() < tw2) {
|
||||
int sw = r.width() / 2;
|
||||
p->drawPixmap(r.x(), r.y(), tiles[Left], 0, 0, sw, tiles[Left].height());
|
||||
p->drawPixmap(r.x() + sw, r.y(), tiles[Right], tw - sw, 0, sw, tiles[Right].height());
|
||||
} else {
|
||||
p->drawPixmap(r.topLeft(), tiles[Left]);
|
||||
if (r.width() - tw2 > 0)
|
||||
p->drawTiledPixmap(r.x() + tw, r.y(), r.width() - tw2, th, tiles[Center]);
|
||||
p->drawPixmap(r.right() - tw + 1, r.y(), tiles[Right]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
HaloPainter *HaloPainter::s_instance = 0;
|
||||
|
||||
|
||||
HaloPainter::HaloPainter()
|
||||
: m_tileCache(16), m_haloCache(30)
|
||||
{
|
||||
}
|
||||
|
||||
HaloPainter::~HaloPainter()
|
||||
{
|
||||
}
|
||||
|
||||
TileSet *HaloPainter::tiles(int height) const
|
||||
{
|
||||
TileSet *tiles = m_tileCache.object(height);
|
||||
|
||||
if (!tiles) {
|
||||
QImage image(64 * 3, height + 16, QImage::Format_ARGB32_Premultiplied);
|
||||
image.fill(0);
|
||||
|
||||
QPainter p(&image);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(Qt::white);
|
||||
p.drawRoundedRect(image.rect().adjusted(8, 8, -8, -8), height, height / 2);
|
||||
p.end();
|
||||
|
||||
gaussianBlur(image, 8);
|
||||
|
||||
p.begin(&image);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
p.fillRect(image.rect(), QColor(255, 255, 255, 255));
|
||||
p.end();
|
||||
|
||||
tiles = new TileSet(QPixmap::fromImage(image));
|
||||
m_tileCache.insert(height, tiles);
|
||||
}
|
||||
|
||||
return tiles;
|
||||
}
|
||||
|
||||
void HaloPainter::paint(QPainter *painter, const QRect &textRect) const
|
||||
{
|
||||
int radius = textRect.height() / 2;
|
||||
const QRect hr = textRect.adjusted(-8 - radius, -9, 8 + radius, 9);
|
||||
|
||||
int key = hr.width() << 16 | hr.height();
|
||||
QPixmap *pixmap = m_haloCache.object(key);
|
||||
|
||||
if (!pixmap) {
|
||||
TileSet *halo = tiles(hr.height() - 16);
|
||||
|
||||
pixmap = new QPixmap(hr.size());
|
||||
pixmap->fill(Qt::transparent);
|
||||
QPainter p(pixmap);
|
||||
p.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
halo->paint(&p, pixmap->rect());
|
||||
QLinearGradient g(0, 0, pixmap->width(), 0);
|
||||
if (hr.width() < 80) {
|
||||
for (int i = 0; i <= 16; i++) {
|
||||
g.setColorAt(i / 16., QColor(0, 0, 0, 164 * (1 - std::pow((i - 8) / 8., 2))));
|
||||
}
|
||||
} else {
|
||||
const qreal pixel = 1. / hr.width();
|
||||
for (int i = 0; i <= 8; i++) {
|
||||
const QColor color(0, 0, 0, 164 * (1 - std::pow((i - 8) / 8., 2)));
|
||||
g.setColorAt(i * (pixel * 40) / 8, color);
|
||||
g.setColorAt(1 - i * (pixel * 40) / 8, color);
|
||||
}
|
||||
}
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
p.fillRect(pixmap->rect(), g);
|
||||
p.end();
|
||||
|
||||
m_haloCache.insert(key, pixmap);
|
||||
}
|
||||
|
||||
painter->drawPixmap(hr.topLeft(), *pixmap);
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
80
plasma/private/effects/halopainter_p.h
Normal file
80
plasma/private/effects/halopainter_p.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
|
||||
*
|
||||
* This library 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 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 library; see the file COPYING.LIB. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef HALOPAINTER_H
|
||||
#define HALOPAINTER_H
|
||||
|
||||
#include <QCache>
|
||||
#include <QPixmap>
|
||||
|
||||
class QRect;
|
||||
class QPainter;
|
||||
|
||||
namespace Plasma {
|
||||
|
||||
class TileSet
|
||||
{
|
||||
public:
|
||||
enum Tile {
|
||||
Left, Center, Right, NTiles
|
||||
};
|
||||
|
||||
TileSet(const QPixmap &pixmap);
|
||||
~TileSet() {}
|
||||
|
||||
void paint(QPainter *painter, const QRect &rect);
|
||||
|
||||
protected:
|
||||
QPixmap tiles[NTiles];
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
class HaloPainter : public QObject
|
||||
{
|
||||
public:
|
||||
~HaloPainter();
|
||||
static HaloPainter *instance() {
|
||||
if (!s_instance) {
|
||||
s_instance = new HaloPainter;
|
||||
}
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
static void drawHalo(QPainter *painter, const QRect &textRect) {
|
||||
instance()->paint(painter, textRect);
|
||||
}
|
||||
|
||||
private:
|
||||
HaloPainter();
|
||||
TileSet *tiles(int height) const;
|
||||
void paint(QPainter *painter, const QRect &textRect) const;
|
||||
|
||||
private:
|
||||
static HaloPainter *s_instance;
|
||||
mutable QCache<int, TileSet> m_tileCache;
|
||||
mutable QCache<int, QPixmap> m_haloCache;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
||||
|
86
plasma/private/effectwatcher.cpp
Normal file
86
plasma/private/effectwatcher.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2011 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 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 "effectwatcher_p.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <qx11info_x11.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
EffectWatcher::EffectWatcher(const QString& property, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_property(property)
|
||||
{
|
||||
m_effectActive = isEffectActive();
|
||||
|
||||
QCoreApplication::instance()->installNativeEventFilter(this);
|
||||
|
||||
Display *dpy = QX11Info::display();
|
||||
Window root = DefaultRootWindow(dpy);
|
||||
XWindowAttributes attrs;
|
||||
//Don't reset eventual other masks already there
|
||||
XGetWindowAttributes(dpy, root, &attrs);
|
||||
attrs.your_event_mask |= PropertyChangeMask;
|
||||
XSelectInput(dpy, root, attrs.your_event_mask);
|
||||
}
|
||||
|
||||
bool EffectWatcher::nativeEventFilter(const QByteArray& eventType, void *message, long *result)
|
||||
{
|
||||
Q_UNUSED(result);
|
||||
if (eventType != "xcb_generic_event_t")
|
||||
return false;
|
||||
xcb_generic_event_t* event = reinterpret_cast<xcb_generic_event_t *>(message);
|
||||
uint response_type = event->response_type & ~0x80;
|
||||
if (response_type != XCB_PROPERTY_NOTIFY)
|
||||
return false;
|
||||
|
||||
xcb_property_notify_event_t* prop_event = reinterpret_cast<xcb_property_notify_event_t *>(event);
|
||||
Display *dpy = QX11Info::display();
|
||||
Atom testAtom = XInternAtom(dpy, m_property.toLatin1(), False);
|
||||
if (prop_event->atom == testAtom) {
|
||||
bool nowEffectActive = isEffectActive();
|
||||
if (m_effectActive != nowEffectActive) {
|
||||
m_effectActive = nowEffectActive;
|
||||
emit effectChanged(m_effectActive);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EffectWatcher::isEffectActive() const
|
||||
{
|
||||
Display *dpy = QX11Info::display();
|
||||
Atom testAtom = XInternAtom(dpy, m_property.toLatin1(), False);
|
||||
|
||||
bool nowEffectActive = false;
|
||||
int cnt;
|
||||
Atom *list = XListProperties(dpy, DefaultRootWindow(dpy), &cnt);
|
||||
if (list != NULL) {
|
||||
nowEffectActive = (qFind(list, list + cnt, testAtom) != list + cnt);
|
||||
XFree(list);
|
||||
}
|
||||
return nowEffectActive;
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
52
plasma/private/effectwatcher_p.h
Normal file
52
plasma/private/effectwatcher_p.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2011 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 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 BLURWATCHER_H
|
||||
#define BLURWATCHER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QAbstractNativeEventFilter>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class EffectWatcher: public QObject, public QAbstractNativeEventFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EffectWatcher(const QString& property, QObject *parent = 0);
|
||||
|
||||
protected:
|
||||
bool isEffectActive() const;
|
||||
|
||||
bool nativeEventFilter(const QByteArray& eventType, void *message, long *result) Q_DECL_OVERRIDE;
|
||||
|
||||
Q_SIGNALS:
|
||||
void effectChanged(bool on);
|
||||
|
||||
private:
|
||||
QString m_property;
|
||||
bool m_effectActive;
|
||||
};
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#endif
|
149
plasma/private/framesvg_p.h
Normal file
149
plasma/private/framesvg_p.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2008 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2009 Marco Martin <notmart@gmail.com>
|
||||
*
|
||||
* 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 PLASMA_FRAMESVG_P_H
|
||||
#define PLASMA_FRAMESVG_P_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QStringBuilder>
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
class FrameData
|
||||
{
|
||||
public:
|
||||
FrameData(FrameSvg *svg)
|
||||
: enabledBorders(FrameSvg::AllBorders),
|
||||
frameSize(-1,-1),
|
||||
topHeight(0),
|
||||
leftWidth(0),
|
||||
rightWidth(0),
|
||||
bottomHeight(0),
|
||||
topMargin(0),
|
||||
leftMargin(0),
|
||||
rightMargin(0),
|
||||
bottomMargin(0),
|
||||
noBorderPadding(false),
|
||||
stretchBorders(false),
|
||||
tileCenter(false),
|
||||
composeOverBorder(false)
|
||||
{
|
||||
ref(svg);
|
||||
}
|
||||
|
||||
FrameData(const FrameData &other, FrameSvg *svg)
|
||||
: enabledBorders(other.enabledBorders),
|
||||
frameSize(other.frameSize),
|
||||
topHeight(0),
|
||||
leftWidth(0),
|
||||
rightWidth(0),
|
||||
bottomHeight(0),
|
||||
topMargin(0),
|
||||
leftMargin(0),
|
||||
rightMargin(0),
|
||||
bottomMargin(0),
|
||||
noBorderPadding(false),
|
||||
stretchBorders(false),
|
||||
tileCenter(false),
|
||||
composeOverBorder(false)
|
||||
{
|
||||
ref(svg);
|
||||
}
|
||||
|
||||
~FrameData()
|
||||
{
|
||||
}
|
||||
|
||||
void ref(FrameSvg *svg);
|
||||
bool deref(FrameSvg *svg);
|
||||
bool removeRefs(FrameSvg *svg);
|
||||
bool isUsed() const;
|
||||
int refcount() const;
|
||||
|
||||
FrameSvg::EnabledBorders enabledBorders;
|
||||
QPixmap cachedBackground;
|
||||
QHash<QString, QRegion> cachedMasks;
|
||||
static const int MAX_CACHED_MASKS = 10;
|
||||
|
||||
QSize frameSize;
|
||||
|
||||
//measures
|
||||
int topHeight;
|
||||
int leftWidth;
|
||||
int rightWidth;
|
||||
int bottomHeight;
|
||||
|
||||
//margins, are equal to the measures by default
|
||||
int topMargin;
|
||||
int leftMargin;
|
||||
int rightMargin;
|
||||
int bottomMargin;
|
||||
|
||||
//size of the svg where the size of the "center"
|
||||
//element is contentWidth x contentHeight
|
||||
bool noBorderPadding : 1;
|
||||
bool stretchBorders : 1;
|
||||
bool tileCenter : 1;
|
||||
bool composeOverBorder : 1;
|
||||
|
||||
QHash<FrameSvg *, int> references;
|
||||
};
|
||||
|
||||
class FrameSvgPrivate
|
||||
{
|
||||
public:
|
||||
FrameSvgPrivate(FrameSvg *psvg)
|
||||
: q(psvg),
|
||||
cacheAll(false),
|
||||
overlayPos(0,0)
|
||||
{
|
||||
}
|
||||
|
||||
~FrameSvgPrivate();
|
||||
|
||||
QPixmap alphaMask();
|
||||
|
||||
void generateBackground(FrameData *frame);
|
||||
void generateFrameBackground(FrameData *frame);
|
||||
QString cacheId(FrameData *frame, const QString &prefixToUse) const;
|
||||
void cacheFrame(const QString &prefixToSave, const QPixmap &background, const QPixmap &overlay);
|
||||
void updateSizes() const;
|
||||
void updateNeeded();
|
||||
void updateAndSignalSizes();
|
||||
QSizeF frameSize(FrameData *frame) const;
|
||||
|
||||
Location location;
|
||||
QString prefix;
|
||||
|
||||
FrameSvg *q;
|
||||
|
||||
bool cacheAll : 1;
|
||||
QPoint overlayPos;
|
||||
|
||||
QHash<QString, FrameData*> frames;
|
||||
|
||||
static QHash<QString, FrameData *> s_sharedFrames;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
83
plasma/private/getsource.cpp
Normal file
83
plasma/private/getsource.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright © 2008 Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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 "getsource_p.h"
|
||||
|
||||
#include "authorizationmanager_p.h"
|
||||
#include "dataengineservice_p.h"
|
||||
#include "service_p.h"
|
||||
|
||||
#include "../remote/authorizationmanager.h"
|
||||
#include "../remote/authorizationrule.h"
|
||||
#include "../dataengine.h"
|
||||
#include "../service.h"
|
||||
|
||||
#include <kdebug.h>
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
GetSource::GetSource(DataEngine *engine, const QString& operation,
|
||||
QHash<QString,QVariant>& parameters,
|
||||
DataEngineService *service)
|
||||
: ServiceJob(QString("publickey"), operation, parameters, service),
|
||||
m_engine(engine),
|
||||
m_service(service)
|
||||
{
|
||||
}
|
||||
|
||||
void GetSource::start()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "Trying to perform the action" << operationName();
|
||||
#endif
|
||||
|
||||
//TODO: check with capabilities before performing actions.
|
||||
if (operationName() == "GetSource") {
|
||||
QString source = parameters().value("SourceName").toString();
|
||||
QString UUID = parameters().value("UUID").toString();
|
||||
if (!m_service->m_peersAlreadyUpdated[source].contains(UUID)) {
|
||||
m_service->m_peersAlreadyUpdated[source].append(UUID);
|
||||
setResult(m_service->m_data[source]);
|
||||
} else {
|
||||
setResult(false); //no update needed
|
||||
}
|
||||
} else if (operationName() == "GetSourceNames") {
|
||||
setResult(m_engine->sources());
|
||||
} else if (operationName() == "ServiceForSource") {
|
||||
QString source = parameters().value("SourceName").toString();
|
||||
Service *service = m_engine->serviceForSource(source);
|
||||
QString serviceName = "plasma-service-" + service->name();
|
||||
|
||||
#ifndef NDEBUG
|
||||
kDebug() << "serviceForSource: getting source " << serviceName;
|
||||
#endif
|
||||
service->d->publish(Plasma::NoAnnouncement, serviceName);
|
||||
if (!AuthorizationManager::self()->d->matchingRule(serviceName, identity())) {
|
||||
AuthorizationRule *rule = new AuthorizationRule(serviceName, identity().id());
|
||||
rule->setPolicy(AuthorizationRule::Allow);
|
||||
AuthorizationManager::self()->d->rules.append(rule);
|
||||
}
|
||||
setResult(serviceName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include "moc_getsource_p.cpp"
|
||||
|
48
plasma/private/getsource_p.h
Normal file
48
plasma/private/getsource_p.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright © 2009 Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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 GETSOURCE_H
|
||||
#define GETSOURCE_H
|
||||
|
||||
#include "../servicejob.h"
|
||||
|
||||
namespace Plasma
|
||||
{
|
||||
|
||||
class DataEngine;
|
||||
class DataEngineService;
|
||||
|
||||
class GetSource : public Plasma::ServiceJob
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GetSource(DataEngine *engine, const QString& operation,
|
||||
QHash<QString,QVariant>& parameters,
|
||||
DataEngineService *service = 0);
|
||||
|
||||
void start();
|
||||
|
||||
private:
|
||||
DataEngine *m_engine;
|
||||
DataEngineService *m_service;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //JOBVIEW_H
|
122
plasma/private/joliemessagehelper_p.h
Normal file
122
plasma/private/joliemessagehelper_p.h
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright © 2009 Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License version 2 as
|
||||
* published by the Free Software Foundation
|
||||
*
|
||||
* 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 JOLIEMESSAGEHELPER_H
|
||||
#define JOLIEMESSAGEHELPER_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QtJolie/Message>
|
||||
#include <QtJolie/Value>
|
||||
#include <kdebug.h>
|
||||
#include <klocalizedstring.h>
|
||||
|
||||
namespace JolieMessage {
|
||||
namespace Field {
|
||||
static const QByteArray DESTINATION = "Destination";
|
||||
static const QByteArray ENABLEDOPERATIONS
|
||||
= "EnabledOperations";
|
||||
static const QByteArray IDENTITY = "Credentials";
|
||||
static const QByteArray IDENTITYID = "CredentialsID";
|
||||
static const QByteArray PARAMETERS = "Parameters";
|
||||
static const QByteArray PIN = "PIN";
|
||||
static const QByteArray RESULT = "Result";
|
||||
static const QByteArray SIGNATURE = "Signature";
|
||||
static const QByteArray TOKEN = "Token";
|
||||
static const QByteArray UUID = "UUID";
|
||||
static const QByteArray OPERATION = "Operation";
|
||||
static const QByteArray OPERATIONSDESCRIPTION
|
||||
= "OperationsDescription";
|
||||
}
|
||||
|
||||
namespace Error {
|
||||
static const QByteArray INVALIDTOKEN = "InvalidToken";
|
||||
static const QByteArray REQUIREPIN = "RequirePIN";
|
||||
static const QByteArray ACCESSDENIED = "AccessDenied";
|
||||
}
|
||||
|
||||
inline QString errorMessage(const QByteArray &error)
|
||||
{
|
||||
if (error == Error::INVALIDTOKEN) {
|
||||
return i18nc("Error message, access to a remote service failed.",
|
||||
"Invalid token.");
|
||||
} else if (error == Error::REQUIREPIN) {
|
||||
return i18nc("Error message, access to a remote service failed.",
|
||||
"Matching password required.");
|
||||
} else if (error == Error::ACCESSDENIED) {
|
||||
return i18nc("Error message, access to a remote service failed.",
|
||||
"Access denied.");
|
||||
}
|
||||
return i18n("Unknown error.");
|
||||
}
|
||||
|
||||
inline QByteArray field(const QByteArray &fieldName, const Jolie::Message &message)
|
||||
{
|
||||
if (!message.data().children(fieldName).isEmpty()) {
|
||||
return message.data().children(fieldName).first().toByteArray();
|
||||
} else {
|
||||
return QByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
inline QByteArray payload(const Jolie::Message &message)
|
||||
{
|
||||
QByteArray result;
|
||||
//result = "payload!";
|
||||
result.append(message.operationName());
|
||||
result.append(field(Field::PARAMETERS, message));
|
||||
result.append(field(Field::IDENTITY, message));
|
||||
result.append(field(Field::IDENTITYID, message));
|
||||
result.append(field(Field::OPERATION, message));
|
||||
result.append(field(Field::OPERATIONSDESCRIPTION, message));
|
||||
result.append(field(Field::PIN, message));
|
||||
result.append(field(Field::TOKEN, message));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline QString print(const Jolie::Message &message)
|
||||
{
|
||||
QString result;
|
||||
result =
|
||||
QString("\n=== JOLIE MESSAGE ===\nId = %1\nOperation = %2\nResource = %3\nData= %4\n")
|
||||
.arg(QString::number(message.id()))
|
||||
.arg(QString(message.operationName()))
|
||||
.arg(QString(message.resourcePath()))
|
||||
.arg(QString(message.data().toByteArray()));
|
||||
|
||||
result += "=====================\n";
|
||||
|
||||
foreach (const QByteArray &child, message.data().childrenNames()) {
|
||||
result += "\n******" + child + "******\n";
|
||||
foreach (const Jolie::Value &value, message.data().children(child)) {
|
||||
if (child == Field::TOKEN || child == Field::PARAMETERS
|
||||
|| child == Field::SIGNATURE) {
|
||||
result += value.toByteArray().toBase64();
|
||||
} else {
|
||||
result += value.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result += "\n== END OF MESSAGE ==\n";
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user