Kontact Plugin Interface Library
plugin.cpp
00001 /* 00002 This file is part of the KDE Kontact Plugin Interface Library. 00003 00004 Copyright (c) 2001 Matthias Hoelzer-Kluepfel <mhk@kde.org> 00005 Copyright (c) 2002-2003 Daniel Molkentin <molkentin@kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include "plugin.h" 00024 #include <QFile> 00025 #include "core.h" 00026 00027 #include <kpimutils/processes.h> 00028 00029 #include <kparts/componentfactory.h> 00030 #include <kxmlguifactory.h> 00031 #include <kaboutdata.h> 00032 #include <kglobal.h> 00033 #include <kdebug.h> 00034 #include <kcomponentdata.h> 00035 #include <kstandarddirs.h> 00036 #include <krun.h> 00037 00038 #include <QObject> 00039 #include <QDBusConnection> 00040 00041 #include <unistd.h> 00042 00043 using namespace KontactInterface; 00044 00049 //@cond PRIVATE 00050 class Plugin::Private 00051 { 00052 public: 00053 00054 void partDestroyed(); 00055 void setXmlFiles(); 00056 void removeInvisibleToolbarActions( Plugin *plugin ); 00057 00058 Core *core; 00059 QList<KAction*> newActions; 00060 QList<KAction*> syncActions; 00061 QString identifier; 00062 QString title; 00063 QString icon; 00064 QString executableName; 00065 QString serviceName; 00066 QByteArray partLibraryName; 00067 QByteArray pluginName; 00068 bool hasPart; 00069 KParts::ReadOnlyPart *part; 00070 bool disabled; 00071 }; 00072 //@endcond 00073 00074 Plugin::Plugin( Core *core, QObject *parent, const char *appName, const char *pluginName ) 00075 : KXMLGUIClient( core ), QObject( parent ), d( new Private ) 00076 { 00077 setObjectName( appName ); 00078 core->factory()->addClient( this ); 00079 KGlobal::locale()->insertCatalog( appName ); 00080 00081 d->pluginName = pluginName ? pluginName : appName; 00082 d->core = core; 00083 d->hasPart = true; 00084 d->part = 0; 00085 d->disabled = false; 00086 } 00087 00088 Plugin::~Plugin() 00089 { 00090 delete d->part; 00091 delete d; 00092 } 00093 00094 void Plugin::setIdentifier( const QString &identifier ) 00095 { 00096 d->identifier = identifier; 00097 } 00098 00099 QString Plugin::identifier() const 00100 { 00101 return d->identifier; 00102 } 00103 00104 void Plugin::setTitle( const QString &title ) 00105 { 00106 d->title = title; 00107 } 00108 00109 QString Plugin::title() const 00110 { 00111 return d->title; 00112 } 00113 00114 void Plugin::setIcon( const QString &icon ) 00115 { 00116 d->icon = icon; 00117 } 00118 00119 QString Plugin::icon() const 00120 { 00121 return d->icon; 00122 } 00123 00124 void Plugin::setExecutableName( const QString &bin ) 00125 { 00126 d->executableName = bin; 00127 } 00128 00129 QString Plugin::executableName() const 00130 { 00131 return d->executableName; 00132 } 00133 00134 void Plugin::setPartLibraryName( const QByteArray &libName ) 00135 { 00136 d->partLibraryName = libName; 00137 } 00138 00139 bool Plugin::createDBUSInterface( const QString &serviceType ) 00140 { 00141 Q_UNUSED( serviceType ); 00142 return false; 00143 } 00144 00145 bool Plugin::isRunningStandalone() const 00146 { 00147 return false; 00148 } 00149 00150 KParts::ReadOnlyPart *Plugin::loadPart() 00151 { 00152 return core()->createPart( d->partLibraryName ); 00153 } 00154 00155 const KAboutData *Plugin::aboutData() const 00156 { 00157 KPluginLoader loader( d->partLibraryName ); 00158 KPluginFactory *factory = loader.factory(); 00159 kDebug() << "filename:" << loader.fileName(); 00160 kDebug() << "libname:" << d->partLibraryName; 00161 00162 if ( factory ) { 00163 if ( factory->componentData().isValid() ) { 00164 kDebug() << "returning factory component aboutdata"; 00165 return factory->componentData().aboutData(); 00166 } else { 00167 // If the componentData of the factory is invalid, the likely cause is that 00168 // the part has not been ported to use K_PLUGIN_FACTORY/K_EXPORT_PLUGIN yet. 00169 // In that case, fallback to the old method of loading component data, which 00170 // does only work for old-style parts. 00171 00172 kDebug() << "Unable to load component data for" << loader.fileName() 00173 << "trying to use the old style plugin system now."; 00174 const KComponentData instance = 00175 KParts::Factory::partComponentDataFromLibrary( d->partLibraryName ); 00176 if ( instance.isValid() ) { 00177 return instance.aboutData(); 00178 } else { 00179 kDebug() << "Invalid instance, unable to get about information!"; 00180 } 00181 } 00182 } 00183 00184 kError() << "Cannot load instance for" << title(); 00185 return 0; 00186 } 00187 00188 KParts::ReadOnlyPart *Plugin::part() 00189 { 00190 if ( !d->part ) { 00191 d->part = createPart(); 00192 if ( d->part ) { 00193 connect( d->part, SIGNAL(destroyed()), SLOT(partDestroyed()) ); 00194 d->removeInvisibleToolbarActions(this); 00195 core()->partLoaded( this, d->part ); 00196 } 00197 } 00198 return d->part; 00199 } 00200 00201 QString Plugin::tipFile() const 00202 { 00203 return QString(); 00204 } 00205 00206 QString Plugin::registerClient() 00207 { 00208 if ( d->serviceName.isEmpty() ) { 00209 d->serviceName = "org.kde." + objectName().toLatin1(); 00210 #ifdef Q_WS_WIN 00211 const QString pid = QString::number( getpid() ); 00212 d->serviceName.append( ".unique-" + pid ); 00213 #endif 00214 QDBusConnection::sessionBus().registerService( d->serviceName ); 00215 } 00216 return d->serviceName; 00217 } 00218 00219 int Plugin::weight() const 00220 { 00221 return 0; 00222 } 00223 00224 void Plugin::insertNewAction( KAction *action ) 00225 { 00226 d->newActions.append( action ); 00227 } 00228 00229 void Plugin::insertSyncAction( KAction *action ) 00230 { 00231 d->syncActions.append( action ); 00232 } 00233 00234 QList<KAction*> Plugin::newActions() const 00235 { 00236 return d->newActions; 00237 } 00238 00239 QList<KAction*> Plugin::syncActions() const 00240 { 00241 return d->syncActions; 00242 } 00243 00244 QStringList Plugin::invisibleToolbarActions() const 00245 { 00246 return QStringList(); 00247 } 00248 00249 bool Plugin::canDecodeMimeData( const QMimeData *data ) const 00250 { 00251 Q_UNUSED( data ); 00252 return false; 00253 } 00254 00255 void Plugin::processDropEvent( QDropEvent * ) 00256 { 00257 } 00258 00259 void Plugin::readProperties( const KConfigGroup & ) 00260 { 00261 } 00262 00263 void Plugin::saveProperties( KConfigGroup & ) 00264 { 00265 } 00266 00267 Core *Plugin::core() const 00268 { 00269 return d->core; 00270 } 00271 00272 void Plugin::aboutToSelect() 00273 { 00274 // Because the 3 korganizer plugins share the same part, we need to switch 00275 // that part's XML files every time we are about to show its GUI... 00276 d->setXmlFiles(); 00277 00278 select(); 00279 } 00280 00281 void Plugin::select() 00282 { 00283 } 00284 00285 void Plugin::configUpdated() 00286 { 00287 } 00288 00289 //@cond PRIVATE 00290 void Plugin::Private::partDestroyed() 00291 { 00292 part = 0; 00293 } 00294 00295 void Plugin::Private::removeInvisibleToolbarActions( Plugin *plugin ) 00296 { 00297 if ( pluginName.isEmpty() ) { 00298 return; 00299 } 00300 00301 // Hide unwanted toolbar action by modifying the XML before createGUI, rather 00302 // than doing it by calling removeAction on the toolbar after createGUI. Both 00303 // solutions work visually, but only modifying the XML ensures that the 00304 // actions don't appear in "edit toolbars". #207296 00305 const QStringList hideActions = plugin->invisibleToolbarActions(); 00306 //kDebug() << "Hiding actions" << hideActions << "from" << pluginName << part; 00307 QDomDocument doc = part->domDocument(); 00308 QDomElement docElem = doc.documentElement(); 00309 // 1. Iterate over containers 00310 for ( QDomElement containerElem = docElem.firstChildElement(); 00311 !containerElem.isNull(); containerElem = containerElem.nextSiblingElement() ) { 00312 if ( QString::compare( containerElem.tagName(), "ToolBar", Qt::CaseInsensitive ) == 0 ) { 00313 // 2. Iterate over actions in toolbars 00314 QDomElement actionElem = containerElem.firstChildElement(); 00315 while ( !actionElem.isNull() ) { 00316 QDomElement nextActionElem = actionElem.nextSiblingElement(); 00317 if ( QString::compare( actionElem.tagName(), "Action", Qt::CaseInsensitive ) == 0 ) { 00318 //kDebug() << "Looking at action" << actionElem.attribute("name"); 00319 if ( hideActions.contains( actionElem.attribute( "name" ) ) ) { 00320 //kDebug() << "REMOVING"; 00321 containerElem.removeChild( actionElem ); 00322 } 00323 } 00324 actionElem = nextActionElem; 00325 } 00326 } 00327 } 00328 00329 // Possible optimization: we could do all the above and the writing below 00330 // only when (newAppFile does not exist) or (version of domDocument > version of newAppFile) (*) 00331 // This requires parsing newAppFile when it exists, though, and better use 00332 // the fast kdeui code for that rather than a full QDomDocument. 00333 // (*) or when invisibleToolbarActions() changes :) 00334 00335 const QString newAppFile = 00336 KStandardDirs::locateLocal( "data", "kontact/default-" + pluginName + ".rc" ); 00337 QFile file( newAppFile ); 00338 if ( !file.open( QFile::WriteOnly ) ) { 00339 kWarning() << "error writing to" << newAppFile; 00340 return; 00341 } 00342 file.write( doc.toString().toUtf8() ); 00343 file.flush(); 00344 00345 setXmlFiles(); 00346 } 00347 00348 void Plugin::Private::setXmlFiles() 00349 { 00350 const QString newAppFile = 00351 KStandardDirs::locateLocal( "data", "kontact/default-" + pluginName + ".rc" ); 00352 const QString localFile = 00353 KStandardDirs::locateLocal( "data", "kontact/local-" + pluginName + ".rc" ); 00354 if ( part->xmlFile() != newAppFile || part->localXMLFile() != localFile ) { 00355 part->replaceXMLFile( newAppFile, localFile ); 00356 } 00357 } 00358 //@endcond 00359 00360 void Plugin::slotConfigUpdated() 00361 { 00362 configUpdated(); 00363 } 00364 00365 void Plugin::bringToForeground() 00366 { 00367 if ( d->executableName.isEmpty() ) { 00368 return; 00369 } 00370 #ifdef Q_WS_WIN 00371 KPIMUtils::activateWindowForProcess( d->executableName ); 00372 #else 00373 KRun::runCommand( d->executableName, 0 ); 00374 #endif 00375 } 00376 00377 Summary *Plugin::createSummaryWidget( QWidget *parent ) 00378 { 00379 Q_UNUSED( parent ); 00380 return 0; 00381 } 00382 00383 bool Plugin::showInSideBar() const 00384 { 00385 return d->hasPart; 00386 } 00387 00388 void Plugin::setShowInSideBar( bool hasPart ) 00389 { 00390 d->hasPart = hasPart; 00391 } 00392 00393 bool Plugin::queryClose() const 00394 { 00395 return true; 00396 } 00397 00398 void Plugin::setDisabled( bool disabled ) 00399 { 00400 d->disabled = disabled; 00401 } 00402 00403 bool Plugin::disabled() const 00404 { 00405 return d->disabled; 00406 } 00407 00408 void Plugin::virtual_hook( int, void * ) 00409 { 00410 //BASE::virtual_hook( id, data ); 00411 } 00412 00413 #include "plugin.moc" 00414 00415 // vim: sw=2 et sts=2 tw=80
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 7 2012 23:59:57 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon May 7 2012 23:59:57 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.