• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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                           ("org.kde.klauncher", "/KLauncher", QDBusConnection::sessionBus()))
00057 
00058 org::kde::KLauncher *KToolInvocation::klauncher()
00059 {
00060     if ( !QDBusConnection::sessionBus().interface()->isServiceRegistered( "org.kde.klauncher" ) )
00061     {
00062         kDebug() << "klauncher not running... launching kdeinit";
00063         KToolInvocation::startKdeinit();
00064     }
00065     return ::klauncherIface();
00066 }
00067 
00068 static void printError(const QString& text, QString* error)
00069 {
00070     if (error)
00071         *error = text;
00072     else
00073         kError() << text << endl;
00074 }
00075 
00076 bool KToolInvocation::isMainThreadActive(QString* error)
00077 {
00078     if (QCoreApplication::instance() && QCoreApplication::instance()->thread() != QThread::currentThread())
00079     {
00080         printError(i18n("Function must be called from the main thread."), error);
00081         return false;
00082     }
00083 
00084     return true;
00085 }
00086 
00087 int KToolInvocation::startServiceInternal(const char *_function,
00088                                           const QString& _name, const QStringList &URLs,
00089                                           QString *error, QString *serviceName, int *pid,
00090                                           const QByteArray& startup_id, bool noWait,
00091                                           const QString& workdir)
00092 {
00093     QString function = QLatin1String(_function);
00094     org::kde::KLauncher *launcher = KToolInvocation::klauncher();
00095     QDBusMessage msg = QDBusMessage::createMethodCall(launcher->service(),
00096                                                 launcher->path(),
00097                                                 launcher->interface(),
00098                                                 function);
00099     msg << _name << URLs;
00100     if (function == QLatin1String("kdeinit_exec_with_workdir"))
00101         msg << workdir;
00102 #ifdef Q_WS_X11
00103     // make sure there is id, so that user timestamp exists
00104     QStringList envs;
00105     QByteArray s = startup_id;
00106     emit kapplication_hook(envs, s);
00107     msg << envs;
00108     msg << QString(s);
00109 #else
00110     msg << QStringList();
00111     msg << QString();
00112 #endif
00113     if( !function.startsWith( QLatin1String("kdeinit_exec") ) )
00114         msg << noWait;
00115 
00116     QDBusMessage reply = QDBusConnection::sessionBus().call(msg);
00117     if ( reply.type() != QDBusMessage::ReplyMessage )
00118     {
00119         QDBusReply<QString> replyObj(reply);
00120         if (replyObj.error().type() == QDBusError::NoReply) {
00121             printError(i18n("Error launching %1. Either KLauncher is not running anymore, or it failed to start the application.", _name), error);
00122         } else {
00123             const QString rpl = reply.arguments().count() > 0 ? reply.arguments().at(0).toString() : reply.errorMessage();
00124             printError(i18n("KLauncher could not be reached via D-Bus. Error when calling %1:\n%2\n",function, rpl), error);
00125         }
00126         //qDebug() << reply;
00127         return EINVAL;
00128     }
00129 
00130     if (noWait)
00131         return 0;
00132 
00133     Q_ASSERT(reply.arguments().count() == 4);
00134     if (serviceName)
00135         *serviceName = reply.arguments().at(1).toString();
00136     if (error)
00137         *error = reply.arguments().at(2).toString();
00138     if (pid)
00139         *pid = reply.arguments().at(3).toInt();
00140     return reply.arguments().at(0).toInt();
00141 }
00142 
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 
00158 int
00159 KToolInvocation::startServiceByName( const QString& _name, const QStringList &URLs,
00160                                      QString *error, QString *serviceName, int *pid,
00161                                      const QByteArray& startup_id, bool noWait )
00162 {
00163     if (!isMainThreadActive(error))
00164         return EINVAL;
00165 
00166     return self()->startServiceInternal("start_service_by_name",
00167                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00168 }
00169 
00170 int
00171 KToolInvocation::startServiceByDesktopPath( const QString& _name, const QString &URL,
00172                                             QString *error, QString *serviceName,
00173                                             int *pid, const QByteArray& startup_id, bool noWait )
00174 {
00175     if (!isMainThreadActive(error))
00176         return EINVAL;
00177 
00178     QStringList URLs;
00179     if (!URL.isEmpty())
00180         URLs.append(URL);
00181     return self()->startServiceInternal("start_service_by_desktop_path",
00182                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00183 }
00184 
00185 int
00186 KToolInvocation::startServiceByDesktopPath( const QString& _name, const QStringList &URLs,
00187                                             QString *error, QString *serviceName, int *pid,
00188                                             const QByteArray& startup_id, bool noWait )
00189 {
00190     if (!isMainThreadActive(error))
00191         return EINVAL;
00192 
00193     return self()->startServiceInternal("start_service_by_desktop_path",
00194                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00195 }
00196 
00197 int
00198 KToolInvocation::startServiceByDesktopName( const QString& _name, const QString &URL,
00199                                             QString *error, QString *serviceName, int *pid,
00200                                             const QByteArray& startup_id, bool noWait )
00201 {
00202     if (!isMainThreadActive(error))
00203         return EINVAL;
00204 
00205     QStringList URLs;
00206     if (!URL.isEmpty())
00207         URLs.append(URL);
00208     return self()->startServiceInternal("start_service_by_desktop_name",
00209                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00210 }
00211 
00212 int
00213 KToolInvocation::startServiceByDesktopName( const QString& _name, const QStringList &URLs,
00214                                             QString *error, QString *serviceName, int *pid,
00215                                             const QByteArray& startup_id, bool noWait )
00216 {
00217     if (!isMainThreadActive(error))
00218         return EINVAL;
00219 
00220     return self()->startServiceInternal("start_service_by_desktop_name",
00221                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00222 }
00223 
00224 int
00225 KToolInvocation::kdeinitExec( const QString& name, const QStringList &args,
00226                               QString *error, int *pid, const QByteArray& startup_id )
00227 {
00228     if (!isMainThreadActive(error))
00229         return EINVAL;
00230 
00231     return self()->startServiceInternal("kdeinit_exec",
00232                                 name, args, error, 0, pid, startup_id, false);
00233 }
00234 
00235 
00236 int
00237 KToolInvocation::kdeinitExecWait( const QString& name, const QStringList &args,
00238                                   QString *error, int *pid, const QByteArray& startup_id )
00239 {
00240     if (!isMainThreadActive(error))
00241         return EINVAL;
00242 
00243     return self()->startServiceInternal("kdeinit_exec_wait",
00244                                 name, args, error, 0, pid, startup_id, false);
00245 }
00246 
00247 void KToolInvocation::invokeHelp( const QString& anchor,
00248                                   const QString& _appname,
00249                                   const QByteArray& startup_id )
00250 {
00251     if (!isMainThreadActive())
00252         return;
00253 
00254     KUrl url;
00255     QString appname;
00256     QString docPath;
00257     if (_appname.isEmpty()) {
00258         appname = QCoreApplication::instance()->applicationName();
00259     } else
00260         appname = _appname;
00261     
00262     KService::Ptr service(KService::serviceByDesktopName(appname));
00263     if (service) {
00264         docPath = service->docPath();
00265     }
00266     
00267     if (!docPath.isEmpty()) {
00268         url = KUrl(KUrl("help:/"), docPath);
00269     } else {
00270         url = QString("help:/%1/index.html").arg(appname);
00271     }
00272     
00273     if (!anchor.isEmpty()) {
00274         url.addQueryItem("anchor", anchor);
00275     }
00276     
00277     // launch a browser for URIs not handled by khelpcenter
00278     // (following KCMultiDialog::slotHelpClicked())
00279     if (!(url.protocol() == "help" || url.protocol() == "man" || url.protocol() == "info")) {
00280         invokeBrowser(url.url());
00281         return;
00282     }
00283 
00284     QDBusInterface *iface = new QDBusInterface(QLatin1String("org.kde.khelpcenter"),
00285                                                QLatin1String("/KHelpCenter"),
00286                                                QLatin1String("org.kde.khelpcenter.khelpcenter"),
00287                                                QDBusConnection::sessionBus());
00288     if ( !iface->isValid() )
00289     {
00290         QString error;
00291 #ifdef Q_WS_WIN
00292         // startServiceByDesktopName() does not work yet; KRun:processDesktopExec returned 'KRun: syntax error in command "khelpcenter %u" , service "KHelpCenter" '
00293         if (kdeinitExec( "khelpcenter", QStringList() << url.url(), &error, 0, startup_id ))
00294 #else
00295         if (startServiceByDesktopName("khelpcenter", url.url(), &error, 0, 0, startup_id, false))
00296 #endif
00297         {
00298             KMessage::message(KMessage::Error,
00299                               i18n("Could not launch the KDE Help Center:\n\n%1", error),
00300                               i18n("Could not Launch Help Center"));
00301             return;
00302         }
00303 
00304         delete iface;
00305         iface = new QDBusInterface(QLatin1String("org.kde.khelpcenter"),
00306                                    QLatin1String("/KHelpCenter"),
00307                                    QLatin1String("org.kde.khelpcenter.khelpcenter"),
00308                                    QDBusConnection::sessionBus());
00309     }
00310 
00311     iface->call("openUrl", url.url(), startup_id );
00312     delete iface;
00313 }
00314 
00315 void KToolInvocation::invokeMailer(const QString &address, const QString &subject, const QByteArray& startup_id)
00316 {
00317     if (!isMainThreadActive())
00318         return;
00319 
00320     invokeMailer(address, QString(), QString(), subject, QString(), QString(),
00321                  QStringList(), startup_id );
00322 }
00323 
00324 void KToolInvocation::invokeMailer(const KUrl &mailtoURL, const QByteArray& startup_id, bool allowAttachments )
00325 {
00326     if (!isMainThreadActive())
00327         return;
00328 
00329     QString address = KUrl::fromPercentEncoding(mailtoURL.path().toLatin1()), subject, cc, bcc, body;
00330     const QStringList queries = mailtoURL.query().mid(1).split( '&');
00331     QStringList attachURLs;
00332     for (QStringList::ConstIterator it = queries.begin(); it != queries.end(); ++it)
00333     {
00334         QString q = (*it).toLower();
00335         if (q.startsWith("subject="))
00336             subject = KUrl::fromPercentEncoding((*it).mid(8).toLatin1());
00337         else
00338             if (q.startsWith("cc="))
00339                 cc = cc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): cc + ',' + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
00340             else
00341                 if (q.startsWith("bcc="))
00342                     bcc = bcc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(4).toLatin1()): bcc + ',' + KUrl::fromPercentEncoding((*it).mid(4).toLatin1());
00343                 else
00344                     if (q.startsWith("body="))
00345                         body = KUrl::fromPercentEncoding((*it).mid(5).toLatin1());
00346                     else
00347                         if (allowAttachments && q.startsWith("attach="))
00348                             attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(7).toLatin1()));
00349                         else
00350                             if (allowAttachments && q.startsWith("attachment="))
00351                                 attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(11).toLatin1()));
00352                             else
00353                                 if (q.startsWith("to="))
00354                                     address = address.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): address + ',' + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
00355     }
00356 
00357     invokeMailer( address, cc, bcc, subject, body, QString(), attachURLs, startup_id );
00358 }
00359 
00360 void KToolInvocation::startKdeinit()
00361 {
00362   KComponentData inst( "startkdeinitlock" );
00363   KLockFile lock( KStandardDirs::locateLocal( "tmp", "startkdeinitlock", inst ));
00364   if( lock.lock( KLockFile::NoBlockFlag ) != KLockFile::LockOK ) {
00365      lock.lock();
00366      if( QDBusConnection::sessionBus().interface()->isServiceRegistered( "org.kde.klauncher" ))
00367          return; // whoever held the lock has already started it
00368   }
00369   // Try to launch kdeinit.
00370   QString srv = KStandardDirs::findExe(QLatin1String("kdeinit4"));
00371   if (srv.isEmpty())
00372      return;
00373 //   this is disabled because we are in kdecore
00374 //  const bool gui = qApp && qApp->type() != QApplication::Tty;
00375 //  if ( gui )
00376 //    qApp->setOverrideCursor( Qt::WaitCursor );
00377   QStringList args;
00378 #ifndef Q_WS_WIN
00379   args += "--suicide";
00380 #endif
00381   QProcess::execute(srv, args);
00382 //  if ( gui )
00383 //    qApp->restoreOverrideCursor();
00384 }
00385 
00386 #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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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