mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
421 lines
10 KiB
C++
421 lines
10 KiB
C++
/*
|
|
This file is part of the KDE Kontact Plugin Interface Library.
|
|
|
|
Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org>
|
|
Copyright (c) 2002-2003 Daniel Molkentin <molkentin@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 "plugin.h"
|
|
#include <QFile>
|
|
#include "core.h"
|
|
|
|
#include <kpimutils/processes.h>
|
|
|
|
#include <kparts/componentfactory.h>
|
|
#include <kxmlguifactory.h>
|
|
#include <kaboutdata.h>
|
|
#include <kglobal.h>
|
|
#include <klocalizedstring.h>
|
|
#include <kdebug.h>
|
|
#include <kcomponentdata.h>
|
|
#include <kstandarddirs.h>
|
|
#include <krun.h>
|
|
|
|
#include <QObject>
|
|
#include <QDBusConnection>
|
|
#include <QDomDocument>
|
|
|
|
#include <unistd.h>
|
|
|
|
using namespace KontactInterface;
|
|
|
|
/**
|
|
Private class that helps to provide binary compatibility between releases.
|
|
@internal
|
|
*/
|
|
//@cond PRIVATE
|
|
class Plugin::Private
|
|
{
|
|
public:
|
|
|
|
void partDestroyed();
|
|
void setXmlFiles();
|
|
void removeInvisibleToolbarActions( Plugin *plugin );
|
|
|
|
Core *core;
|
|
QList<KAction*> newActions;
|
|
QList<KAction*> syncActions;
|
|
QString identifier;
|
|
QString title;
|
|
QString icon;
|
|
QString executableName;
|
|
QString serviceName;
|
|
QByteArray partLibraryName;
|
|
QByteArray pluginName;
|
|
bool hasPart;
|
|
KParts::ReadOnlyPart *part;
|
|
bool disabled;
|
|
};
|
|
//@endcond
|
|
|
|
Plugin::Plugin( Core *core, QObject *parent, const char *appName, const char *pluginName )
|
|
: KXMLGUIClient( core ), QObject( parent ), d( new Private )
|
|
{
|
|
setObjectName( QLatin1String(appName) );
|
|
core->factory()->addClient( this );
|
|
KGlobal::locale()->insertCatalog( QLatin1String(appName) );
|
|
|
|
d->pluginName = pluginName ? pluginName : appName;
|
|
d->core = core;
|
|
d->hasPart = true;
|
|
d->part = 0;
|
|
d->disabled = false;
|
|
}
|
|
|
|
Plugin::~Plugin()
|
|
{
|
|
delete d->part;
|
|
delete d;
|
|
}
|
|
|
|
void Plugin::setIdentifier( const QString &identifier )
|
|
{
|
|
d->identifier = identifier;
|
|
}
|
|
|
|
QString Plugin::identifier() const
|
|
{
|
|
return d->identifier;
|
|
}
|
|
|
|
void Plugin::setTitle( const QString &title )
|
|
{
|
|
d->title = title;
|
|
}
|
|
|
|
QString Plugin::title() const
|
|
{
|
|
return d->title;
|
|
}
|
|
|
|
void Plugin::setIcon( const QString &icon )
|
|
{
|
|
d->icon = icon;
|
|
}
|
|
|
|
QString Plugin::icon() const
|
|
{
|
|
return d->icon;
|
|
}
|
|
|
|
void Plugin::setExecutableName( const QString &bin )
|
|
{
|
|
d->executableName = bin;
|
|
}
|
|
|
|
QString Plugin::executableName() const
|
|
{
|
|
return d->executableName;
|
|
}
|
|
|
|
void Plugin::setPartLibraryName( const QByteArray &libName )
|
|
{
|
|
d->partLibraryName = libName;
|
|
}
|
|
|
|
bool Plugin::createDBUSInterface( const QString &serviceType )
|
|
{
|
|
Q_UNUSED( serviceType );
|
|
return false;
|
|
}
|
|
|
|
bool Plugin::isRunningStandalone() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
KParts::ReadOnlyPart *Plugin::loadPart()
|
|
{
|
|
return core()->createPart( d->partLibraryName );
|
|
}
|
|
|
|
const KAboutData *Plugin::aboutData() const
|
|
{
|
|
KPluginLoader loader( QString::fromLatin1(d->partLibraryName) );
|
|
KPluginFactory *factory = loader.factory();
|
|
kDebug() << "filename:" << loader.fileName();
|
|
kDebug() << "libname:" << d->partLibraryName;
|
|
|
|
if ( factory ) {
|
|
if ( factory->componentData().isValid() ) {
|
|
kDebug() << "returning factory component aboutdata";
|
|
return factory->componentData().aboutData();
|
|
} else {
|
|
// If the componentData of the factory is invalid, the likely cause is that
|
|
// the part has not been ported to use K_PLUGIN_FACTORY/K_EXPORT_PLUGIN yet.
|
|
// In that case, fallback to the old method of loading component data, which
|
|
// does only work for old-style parts.
|
|
|
|
kDebug() << "Unable to load component data for" << loader.fileName()
|
|
<< "trying to use the old style plugin system now.";
|
|
const KComponentData instance =
|
|
KParts::Factory::partComponentDataFromLibrary( QString::fromLatin1(d->partLibraryName) );
|
|
if ( instance.isValid() ) {
|
|
return instance.aboutData();
|
|
} else {
|
|
kDebug() << "Invalid instance, unable to get about information!";
|
|
}
|
|
}
|
|
}
|
|
|
|
kError() << "Cannot load instance for" << title();
|
|
return 0;
|
|
}
|
|
|
|
KParts::ReadOnlyPart *Plugin::part()
|
|
{
|
|
if ( !d->part ) {
|
|
d->part = createPart();
|
|
if ( d->part ) {
|
|
connect( d->part, SIGNAL(destroyed()), SLOT(partDestroyed()) );
|
|
d->removeInvisibleToolbarActions( this );
|
|
core()->partLoaded( this, d->part );
|
|
}
|
|
}
|
|
return d->part;
|
|
}
|
|
|
|
QString Plugin::tipFile() const
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QString Plugin::registerClient()
|
|
{
|
|
if ( d->serviceName.isEmpty() ) {
|
|
d->serviceName = QLatin1String("org.kde.") + QLatin1String(objectName().toLatin1());
|
|
#ifdef Q_WS_WIN
|
|
const QString pid = QString::number( getpid() );
|
|
d->serviceName.append( QLatin1String(".unique-") + pid );
|
|
#endif
|
|
QDBusConnection::sessionBus().registerService( d->serviceName );
|
|
}
|
|
return d->serviceName;
|
|
}
|
|
|
|
int Plugin::weight() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void Plugin::insertNewAction( KAction *action )
|
|
{
|
|
d->newActions.append( action );
|
|
}
|
|
|
|
void Plugin::insertSyncAction( KAction *action )
|
|
{
|
|
d->syncActions.append( action );
|
|
}
|
|
|
|
QList<KAction*> Plugin::newActions() const
|
|
{
|
|
return d->newActions;
|
|
}
|
|
|
|
QList<KAction*> Plugin::syncActions() const
|
|
{
|
|
return d->syncActions;
|
|
}
|
|
|
|
QStringList Plugin::invisibleToolbarActions() const
|
|
{
|
|
return QStringList();
|
|
}
|
|
|
|
bool Plugin::canDecodeMimeData( const QMimeData *data ) const
|
|
{
|
|
Q_UNUSED( data );
|
|
return false;
|
|
}
|
|
|
|
void Plugin::processDropEvent( QDropEvent * )
|
|
{
|
|
}
|
|
|
|
void Plugin::readProperties( const KConfigGroup & )
|
|
{
|
|
}
|
|
|
|
void Plugin::saveProperties( KConfigGroup & )
|
|
{
|
|
}
|
|
|
|
Core *Plugin::core() const
|
|
{
|
|
return d->core;
|
|
}
|
|
|
|
void Plugin::aboutToSelect()
|
|
{
|
|
// Because the 3 korganizer plugins share the same part, we need to switch
|
|
// that part's XML files every time we are about to show its GUI...
|
|
d->setXmlFiles();
|
|
|
|
select();
|
|
}
|
|
|
|
void Plugin::select()
|
|
{
|
|
}
|
|
|
|
void Plugin::configUpdated()
|
|
{
|
|
}
|
|
|
|
//@cond PRIVATE
|
|
void Plugin::Private::partDestroyed()
|
|
{
|
|
part = 0;
|
|
}
|
|
|
|
void Plugin::Private::removeInvisibleToolbarActions( Plugin *plugin )
|
|
{
|
|
if ( pluginName.isEmpty() ) {
|
|
return;
|
|
}
|
|
|
|
// Hide unwanted toolbar action by modifying the XML before createGUI, rather
|
|
// than doing it by calling removeAction on the toolbar after createGUI. Both
|
|
// solutions work visually, but only modifying the XML ensures that the
|
|
// actions don't appear in "edit toolbars". #207296
|
|
const QStringList hideActions = plugin->invisibleToolbarActions();
|
|
//kDebug() << "Hiding actions" << hideActions << "from" << pluginName << part;
|
|
QDomDocument doc = part->domDocument();
|
|
QDomElement docElem = doc.documentElement();
|
|
// 1. Iterate over containers
|
|
for ( QDomElement containerElem = docElem.firstChildElement();
|
|
!containerElem.isNull(); containerElem = containerElem.nextSiblingElement() ) {
|
|
if ( QString::compare( containerElem.tagName(), QLatin1String("ToolBar"), Qt::CaseInsensitive ) == 0 ) {
|
|
// 2. Iterate over actions in toolbars
|
|
QDomElement actionElem = containerElem.firstChildElement();
|
|
while ( !actionElem.isNull() ) {
|
|
QDomElement nextActionElem = actionElem.nextSiblingElement();
|
|
if ( QString::compare( actionElem.tagName(), QLatin1String("Action"), Qt::CaseInsensitive ) == 0 ) {
|
|
//kDebug() << "Looking at action" << actionElem.attribute("name");
|
|
if ( hideActions.contains( actionElem.attribute( QLatin1String("name") ) ) ) {
|
|
//kDebug() << "REMOVING";
|
|
containerElem.removeChild( actionElem );
|
|
}
|
|
}
|
|
actionElem = nextActionElem;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Possible optimization: we could do all the above and the writing below
|
|
// only when (newAppFile does not exist) or (version of domDocument > version of newAppFile) (*)
|
|
// This requires parsing newAppFile when it exists, though, and better use
|
|
// the fast kdeui code for that rather than a full QDomDocument.
|
|
// (*) or when invisibleToolbarActions() changes :)
|
|
|
|
const QString newAppFile =
|
|
KStandardDirs::locateLocal( "data", QLatin1String("kontact/default-") + QLatin1String(pluginName) + QLatin1String(".rc") );
|
|
QFile file( newAppFile );
|
|
if ( !file.open( QFile::WriteOnly ) ) {
|
|
kWarning() << "error writing to" << newAppFile;
|
|
return;
|
|
}
|
|
file.write( doc.toString().toUtf8() );
|
|
file.flush();
|
|
|
|
setXmlFiles();
|
|
}
|
|
|
|
void Plugin::Private::setXmlFiles()
|
|
{
|
|
const QString newAppFile =
|
|
KStandardDirs::locateLocal( "data", QLatin1String("kontact/default-") + QLatin1String(pluginName) + QLatin1String(".rc") );
|
|
const QString localFile =
|
|
KStandardDirs::locateLocal( "data", QLatin1String("kontact/local-") + QLatin1String(pluginName) + QLatin1String(".rc") );
|
|
if ( part->xmlFile() != newAppFile || part->localXMLFile() != localFile ) {
|
|
part->replaceXMLFile( newAppFile, localFile );
|
|
}
|
|
}
|
|
//@endcond
|
|
|
|
void Plugin::slotConfigUpdated()
|
|
{
|
|
configUpdated();
|
|
}
|
|
|
|
void Plugin::bringToForeground()
|
|
{
|
|
if ( d->executableName.isEmpty() ) {
|
|
return;
|
|
}
|
|
#ifdef Q_WS_WIN
|
|
KPIMUtils::activateWindowForProcess( d->executableName );
|
|
#else
|
|
KRun::runCommand( d->executableName, 0 );
|
|
#endif
|
|
}
|
|
|
|
Summary *Plugin::createSummaryWidget( QWidget *parent )
|
|
{
|
|
Q_UNUSED( parent );
|
|
return 0;
|
|
}
|
|
|
|
bool Plugin::showInSideBar() const
|
|
{
|
|
return d->hasPart;
|
|
}
|
|
|
|
void Plugin::setShowInSideBar( bool hasPart )
|
|
{
|
|
d->hasPart = hasPart;
|
|
}
|
|
|
|
bool Plugin::queryClose() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void Plugin::setDisabled( bool disabled )
|
|
{
|
|
d->disabled = disabled;
|
|
}
|
|
|
|
bool Plugin::disabled() const
|
|
{
|
|
return d->disabled;
|
|
}
|
|
|
|
void Plugin::shortcutChanged()
|
|
{
|
|
}
|
|
|
|
void Plugin::virtual_hook( int, void * )
|
|
{
|
|
//BASE::virtual_hook( id, data );
|
|
}
|
|
|
|
#include "moc_plugin.cpp"
|
|
|
|
// vim: sw=2 et sts=2 tw=80
|