• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

ktoolinvocation.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
00003     Copyright (C) 2006 Thiago Macieira <thiago@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "ktoolinvocation.h"
00022 #include "klauncher_iface.h"
00023 #include "kdebug.h"
00024 #include "kglobal.h"
00025 #include "kstandarddirs.h"
00026 #include "kcomponentdata.h"
00027 #include "kurl.h"
00028 #include "kmessage.h"
00029 #include "kservice.h"
00030 #include <klockfile.h>
00031 #include <klocale.h>
00032 
00033 #include <QMutex>
00034 #include <QMutexLocker>
00035 #include <QCoreApplication>
00036 #include <QThread>
00037 
00038 #include <errno.h>
00039 
00040 
00041 KToolInvocation *KToolInvocation::self()
00042 {
00043     K_GLOBAL_STATIC(KToolInvocation, s_self)
00044     return s_self;
00045 }
00046 
00047 KToolInvocation::KToolInvocation() : QObject(0), d(0)
00048 {
00049 }
00050 
00051 KToolInvocation::~KToolInvocation()
00052 {
00053 }
00054 
00055 Q_GLOBAL_STATIC_WITH_ARGS(org::kde::KLauncher, klauncherIface,
00056                           (QString::fromLatin1("org.kde.klauncher"), QString::fromLatin1("/KLauncher"), QDBusConnection::sessionBus()))
00057 
00058 org::kde::KLauncher *KToolInvocation::klauncher()
00059 {
00060     if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QString::fromLatin1("org.kde.klauncher"))) {
00061         kDebug(180) << "klauncher not running... launching kdeinit";
00062         KToolInvocation::startKdeinit();
00063     }
00064     return ::klauncherIface();
00065 }
00066 
00067 static void printError(const QString& text, QString* error)
00068 {
00069     if (error)
00070         *error = text;
00071     else
00072         kError() << text << endl;
00073 }
00074 
00075 bool KToolInvocation::isMainThreadActive(QString* error)
00076 {
00077     if (QCoreApplication::instance() && QCoreApplication::instance()->thread() != QThread::currentThread())
00078     {
00079         printError(i18n("Function must be called from the main thread."), error);
00080         return false;
00081     }
00082 
00083     return true;
00084 }
00085 
00086 int KToolInvocation::startServiceInternal(const char *_function,
00087                                           const QString& _name, const QStringList &URLs,
00088                                           QString *error, QString *serviceName, int *pid,
00089                                           const QByteArray& startup_id, bool noWait,
00090                                           const QString& workdir)
00091 {
00092     QString function = QLatin1String(_function);
00093     org::kde::KLauncher *launcher = KToolInvocation::klauncher();
00094     QDBusMessage msg = QDBusMessage::createMethodCall(launcher->service(),
00095                                                 launcher->path(),
00096                                                 launcher->interface(),
00097                                                 function);
00098     msg << _name << URLs;
00099     if (function == QLatin1String("kdeinit_exec_with_workdir"))
00100         msg << workdir;
00101 #ifdef Q_WS_X11
00102     // make sure there is id, so that user timestamp exists
00103     QStringList envs;
00104     QByteArray s = startup_id;
00105     emit kapplication_hook(envs, s);
00106     msg << envs;
00107     msg << QString::fromLatin1(s);
00108 #else
00109     msg << QStringList();
00110     msg << QString();
00111 #endif
00112     if( !function.startsWith( QLatin1String("kdeinit_exec") ) )
00113         msg << noWait;
00114 
00115     QDBusMessage reply = QDBusConnection::sessionBus().call(msg);
00116     if ( reply.type() != QDBusMessage::ReplyMessage )
00117     {
00118         QDBusReply<QString> replyObj(reply);
00119         if (replyObj.error().type() == QDBusError::NoReply) {
00120             printError(i18n("Error launching %1. Either KLauncher is not running anymore, or it failed to start the application.", _name), error);
00121         } else {
00122             const QString rpl = reply.arguments().count() > 0 ? reply.arguments().at(0).toString() : reply.errorMessage();
00123             printError(i18n("KLauncher could not be reached via D-Bus. Error when calling %1:\n%2\n",function, rpl), error);
00124         }
00125         //qDebug() << reply;
00126         return EINVAL;
00127     }
00128 
00129     if (noWait)
00130         return 0;
00131 
00132     Q_ASSERT(reply.arguments().count() == 4);
00133     if (serviceName)
00134         *serviceName = reply.arguments().at(1).toString();
00135     if (error)
00136         *error = reply.arguments().at(2).toString();
00137     if (pid)
00138         *pid = reply.arguments().at(3).toInt();
00139     return reply.arguments().at(0).toInt();
00140 }
00141 
00142 #ifndef KDE_NO_DEPRECATED
00143 int
00144 KToolInvocation::startServiceByName( const QString& _name, const QString &URL,
00145                                      QString *error, QString *serviceName, int *pid,
00146                                      const QByteArray& startup_id, bool noWait )
00147 {
00148     if (!isMainThreadActive(error))
00149         return EINVAL;
00150 
00151     QStringList URLs;
00152     if (!URL.isEmpty())
00153         URLs.append(URL);
00154     return self()->startServiceInternal("start_service_by_name",
00155                                         _name, URLs, error, serviceName, pid, startup_id, noWait);
00156 }
00157 #endif
00158 
00159 #ifndef KDE_NO_DEPRECATED
00160 int
00161 KToolInvocation::startServiceByName( const QString& _name, const QStringList &URLs,
00162                                      QString *error, QString *serviceName, int *pid,
00163                                      const QByteArray& startup_id, bool noWait )
00164 {
00165     if (!isMainThreadActive(error))
00166         return EINVAL;
00167 
00168     return self()->startServiceInternal("start_service_by_name",
00169                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00170 }
00171 #endif
00172 
00173 int
00174 KToolInvocation::startServiceByDesktopPath( const QString& _name, const QString &URL,
00175                                             QString *error, QString *serviceName,
00176                                             int *pid, const QByteArray& startup_id, bool noWait )
00177 {
00178     if (!isMainThreadActive(error))
00179         return EINVAL;
00180 
00181     QStringList URLs;
00182     if (!URL.isEmpty())
00183         URLs.append(URL);
00184     return self()->startServiceInternal("start_service_by_desktop_path",
00185                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00186 }
00187 
00188 int
00189 KToolInvocation::startServiceByDesktopPath( const QString& _name, const QStringList &URLs,
00190                                             QString *error, QString *serviceName, int *pid,
00191                                             const QByteArray& startup_id, bool noWait )
00192 {
00193     if (!isMainThreadActive(error))
00194         return EINVAL;
00195 
00196     return self()->startServiceInternal("start_service_by_desktop_path",
00197                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00198 }
00199 
00200 int
00201 KToolInvocation::startServiceByDesktopName( const QString& _name, const QString &URL,
00202                                             QString *error, QString *serviceName, int *pid,
00203                                             const QByteArray& startup_id, bool noWait )
00204 {
00205     if (!isMainThreadActive(error))
00206         return EINVAL;
00207 
00208     QStringList URLs;
00209     if (!URL.isEmpty())
00210         URLs.append(URL);
00211     return self()->startServiceInternal("start_service_by_desktop_name",
00212                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00213 }
00214 
00215 int
00216 KToolInvocation::startServiceByDesktopName( const QString& _name, const QStringList &URLs,
00217                                             QString *error, QString *serviceName, int *pid,
00218                                             const QByteArray& startup_id, bool noWait )
00219 {
00220     if (!isMainThreadActive(error))
00221         return EINVAL;
00222 
00223     return self()->startServiceInternal("start_service_by_desktop_name",
00224                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00225 }
00226 
00227 int
00228 KToolInvocation::kdeinitExec( const QString& name, const QStringList &args,
00229                               QString *error, int *pid, const QByteArray& startup_id )
00230 {
00231     if (!isMainThreadActive(error))
00232         return EINVAL;
00233 
00234     return self()->startServiceInternal("kdeinit_exec",
00235                                 name, args, error, 0, pid, startup_id, false);
00236 }
00237 
00238 
00239 int
00240 KToolInvocation::kdeinitExecWait( const QString& name, const QStringList &args,
00241                                   QString *error, int *pid, const QByteArray& startup_id )
00242 {
00243     if (!isMainThreadActive(error))
00244         return EINVAL;
00245 
00246     return self()->startServiceInternal("kdeinit_exec_wait",
00247                                 name, args, error, 0, pid, startup_id, false);
00248 }
00249 
00250 void KToolInvocation::invokeHelp( const QString& anchor,
00251                                   const QString& _appname,
00252                                   const QByteArray& startup_id )
00253 {
00254     if (!isMainThreadActive())
00255         return;
00256 
00257     KUrl url;
00258     QString appname;
00259     QString docPath;
00260     if (_appname.isEmpty()) {
00261         appname = QCoreApplication::instance()->applicationName();
00262     } else
00263         appname = _appname;
00264 
00265     KService::Ptr service(KService::serviceByDesktopName(appname));
00266     if (service) {
00267         docPath = service->docPath();
00268     }
00269 
00270     if (!docPath.isEmpty()) {
00271         url = KUrl(KUrl("help:/"), docPath);
00272     } else {
00273         url = QString::fromLatin1("help:/%1/index.html").arg(appname);
00274     }
00275 
00276     if (!anchor.isEmpty()) {
00277         url.addQueryItem(QString::fromLatin1("anchor"), anchor);
00278     }
00279 
00280     // launch a browser for URIs not handled by khelpcenter
00281     // (following KCMultiDialog::slotHelpClicked())
00282     if (!(url.protocol() == QLatin1String("help") || url.protocol() == QLatin1String("man") || url.protocol() == QLatin1String("info"))) {
00283         invokeBrowser(url.url());
00284         return;
00285     }
00286 
00287     QDBusInterface *iface = new QDBusInterface(QLatin1String("org.kde.khelpcenter"),
00288                                                QLatin1String("/KHelpCenter"),
00289                                                QLatin1String("org.kde.khelpcenter.khelpcenter"),
00290                                                QDBusConnection::sessionBus());
00291     if ( !iface->isValid() )
00292     {
00293         QString error;
00294 #ifdef Q_WS_WIN
00295         // startServiceByDesktopName() does not work yet; KRun:processDesktopExec returned 'KRun: syntax error in command "khelpcenter %u" , service "KHelpCenter" '
00296         if (kdeinitExec(QLatin1String("khelpcenter"), QStringList() << url.url(), &error, 0, startup_id))
00297 #else
00298         if (startServiceByDesktopName(QLatin1String("khelpcenter"), url.url(), &error, 0, 0, startup_id, false))
00299 #endif
00300         {
00301             KMessage::message(KMessage::Error,
00302                               i18n("Could not launch the KDE Help Center:\n\n%1", error),
00303                               i18n("Could not Launch Help Center"));
00304             delete iface;
00305         return;
00306         }
00307 
00308         delete iface;
00309         iface = new QDBusInterface(QLatin1String("org.kde.khelpcenter"),
00310                                    QLatin1String("/KHelpCenter"),
00311                                    QLatin1String("org.kde.khelpcenter.khelpcenter"),
00312                                    QDBusConnection::sessionBus());
00313     }
00314 
00315     iface->call(QString::fromLatin1("openUrl"), url.url(), startup_id );
00316     delete iface;
00317 }
00318 
00319 void KToolInvocation::invokeMailer(const QString &address, const QString &subject, const QByteArray& startup_id)
00320 {
00321     if (!isMainThreadActive())
00322         return;
00323 
00324     invokeMailer(address, QString(), QString(), subject, QString(), QString(),
00325                  QStringList(), startup_id );
00326 }
00327 
00328 void KToolInvocation::invokeMailer(const KUrl &mailtoURL, const QByteArray& startup_id, bool allowAttachments )
00329 {
00330     if (!isMainThreadActive())
00331         return;
00332 
00333     QString address = mailtoURL.path();
00334     QString subject;
00335     QString cc;
00336     QString bcc;
00337     QString body;
00338 
00339     const QStringList queries = mailtoURL.query().mid(1).split(QLatin1Char('&'));
00340     const QChar comma = QChar::fromLatin1(',');
00341     QStringList attachURLs;
00342     for (QStringList::ConstIterator it = queries.begin(); it != queries.end(); ++it)
00343     {
00344         QString q = (*it).toLower();
00345         if (q.startsWith(QLatin1String("subject=")))
00346             subject = KUrl::fromPercentEncoding((*it).mid(8).toLatin1());
00347         else
00348             if (q.startsWith(QLatin1String("cc=")))
00349                 cc = cc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): cc + comma + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
00350             else
00351                 if (q.startsWith(QLatin1String("bcc=")))
00352                     bcc = bcc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(4).toLatin1()): bcc + comma + KUrl::fromPercentEncoding((*it).mid(4).toLatin1());
00353                 else
00354                     if (q.startsWith(QLatin1String("body=")))
00355                         body = KUrl::fromPercentEncoding((*it).mid(5).toLatin1());
00356                     else
00357                         if (allowAttachments && q.startsWith(QLatin1String("attach=")))
00358                             attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(7).toLatin1()));
00359                         else
00360                             if (allowAttachments && q.startsWith(QLatin1String("attachment=")))
00361                                 attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(11).toLatin1()));
00362                             else
00363                                 if (q.startsWith(QLatin1String("to=")))
00364                                     address = address.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): address + comma + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
00365     }
00366 
00367     invokeMailer( address, cc, bcc, subject, body, QString(), attachURLs, startup_id );
00368 }
00369 
00370 void KToolInvocation::startKdeinit()
00371 {
00372   KComponentData inst( "startkdeinitlock" );
00373   KLockFile lock( KStandardDirs::locateLocal("tmp", QString::fromLatin1("startkdeinitlock"), inst ));
00374   if( lock.lock( KLockFile::NoBlockFlag ) != KLockFile::LockOK ) {
00375      lock.lock();
00376      if( QDBusConnection::sessionBus().interface()->isServiceRegistered(QString::fromLatin1("org.kde.klauncher")))
00377          return; // whoever held the lock has already started it
00378   }
00379   // Try to launch kdeinit.
00380   QString srv = KStandardDirs::findExe(QLatin1String("kdeinit4"));
00381   if (srv.isEmpty())
00382      return;
00383 //   this is disabled because we are in kdecore
00384 //  const bool gui = qApp && qApp->type() != QApplication::Tty;
00385 //  if ( gui )
00386 //    qApp->setOverrideCursor( Qt::WaitCursor );
00387   QStringList args;
00388 #ifndef Q_WS_WIN
00389   args += QString::fromLatin1("--suicide");
00390 #endif
00391   QProcess::execute(srv, args);
00392 //  if ( gui )
00393 //    qApp->restoreOverrideCursor();
00394 }
00395 
00396 #include "ktoolinvocation.moc"

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal