• Skip to content
  • Skip to link menu
KDE 4.1 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 <klockfile.h>
00030 #include <klocale.h>
00031 
00032 #include <QMutex>
00033 #include <QMutexLocker>
00034 #include <QCoreApplication>
00035 #include <QThread>
00036 
00037 #include <errno.h>
00038 
00039 
00040 KToolInvocation *KToolInvocation::self()
00041 {
00042     K_GLOBAL_STATIC(KToolInvocation, s_self)
00043     return s_self;
00044 }
00045 
00046 KToolInvocation::KToolInvocation() : QObject(0), d(0)
00047 {
00048 }
00049 
00050 KToolInvocation::~KToolInvocation()
00051 {
00052 }
00053 
00054 Q_GLOBAL_STATIC_WITH_ARGS(org::kde::KLauncher, klauncherIface,
00055                           ("org.kde.klauncher", "/KLauncher", QDBusConnection::sessionBus()))
00056 
00057 org::kde::KLauncher *KToolInvocation::klauncher()
00058 {
00059     if ( !QDBusConnection::sessionBus().interface()->isServiceRegistered( "org.kde.klauncher" ) )
00060     {
00061         kDebug() << "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(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         QString rpl = reply.arguments().count() > 0 ? reply.arguments().at(0).toString() : QLatin1String("empty");
00119         printError(i18n("KLauncher could not be reached via D-Bus. Error when calling %1:\n%2\n",function, rpl), error);
00120         //qDebug() << reply;
00121         return EINVAL;
00122     }
00123 
00124     if (noWait)
00125         return 0;
00126 
00127     Q_ASSERT(reply.arguments().count() == 4);
00128     if (serviceName)
00129         *serviceName = reply.arguments().at(1).toString();
00130     if (error)
00131         *error = reply.arguments().at(2).toString();
00132     if (pid)
00133         *pid = reply.arguments().at(3).toInt();
00134     return reply.arguments().at(0).toInt();
00135 }
00136 
00137 int
00138 KToolInvocation::startServiceByName( const QString& _name, const QString &URL,
00139                                      QString *error, QString *serviceName, int *pid,
00140                                      const QByteArray& startup_id, bool noWait )
00141 {
00142     if (!isMainThreadActive(error))
00143         return EINVAL;
00144 
00145     QStringList URLs;
00146     if (!URL.isEmpty())
00147         URLs.append(URL);
00148     return self()->startServiceInternal("start_service_by_name",
00149                                         _name, URLs, error, serviceName, pid, startup_id, noWait);
00150 }
00151 
00152 int
00153 KToolInvocation::startServiceByName( const QString& _name, const QStringList &URLs,
00154                                      QString *error, QString *serviceName, int *pid,
00155                                      const QByteArray& startup_id, bool noWait )
00156 {
00157     if (!isMainThreadActive(error))
00158         return EINVAL;
00159 
00160     return self()->startServiceInternal("start_service_by_name",
00161                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00162 }
00163 
00164 int
00165 KToolInvocation::startServiceByDesktopPath( const QString& _name, const QString &URL,
00166                                             QString *error, QString *serviceName,
00167                                             int *pid, const QByteArray& startup_id, bool noWait )
00168 {
00169     if (!isMainThreadActive(error))
00170         return EINVAL;
00171 
00172     QStringList URLs;
00173     if (!URL.isEmpty())
00174         URLs.append(URL);
00175     return self()->startServiceInternal("start_service_by_desktop_path",
00176                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00177 }
00178 
00179 int
00180 KToolInvocation::startServiceByDesktopPath( const QString& _name, const QStringList &URLs,
00181                                             QString *error, QString *serviceName, int *pid,
00182                                             const QByteArray& startup_id, bool noWait )
00183 {
00184     if (!isMainThreadActive(error))
00185         return EINVAL;
00186 
00187     return self()->startServiceInternal("start_service_by_desktop_path",
00188                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00189 }
00190 
00191 int
00192 KToolInvocation::startServiceByDesktopName( const QString& _name, const QString &URL,
00193                                             QString *error, QString *serviceName, int *pid,
00194                                             const QByteArray& startup_id, bool noWait )
00195 {
00196     if (!isMainThreadActive(error))
00197         return EINVAL;
00198 
00199     QStringList URLs;
00200     if (!URL.isEmpty())
00201         URLs.append(URL);
00202     return self()->startServiceInternal("start_service_by_desktop_name",
00203                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00204 }
00205 
00206 int
00207 KToolInvocation::startServiceByDesktopName( const QString& _name, const QStringList &URLs,
00208                                             QString *error, QString *serviceName, int *pid,
00209                                             const QByteArray& startup_id, bool noWait )
00210 {
00211     if (!isMainThreadActive(error))
00212         return EINVAL;
00213 
00214     return self()->startServiceInternal("start_service_by_desktop_name",
00215                                 _name, URLs, error, serviceName, pid, startup_id, noWait);
00216 }
00217 
00218 int
00219 KToolInvocation::kdeinitExec( const QString& name, const QStringList &args,
00220                               QString *error, int *pid, const QByteArray& startup_id )
00221 {
00222     if (!isMainThreadActive(error))
00223         return EINVAL;
00224 
00225     return self()->startServiceInternal("kdeinit_exec",
00226                                 name, args, error, 0, pid, startup_id, false);
00227 }
00228 
00229 
00230 int
00231 KToolInvocation::kdeinitExecWait( const QString& name, const QStringList &args,
00232                                   QString *error, int *pid, const QByteArray& startup_id )
00233 {
00234     if (!isMainThreadActive(error))
00235         return EINVAL;
00236 
00237     return self()->startServiceInternal("kdeinit_exec_wait",
00238                                 name, args, error, 0, pid, startup_id, false);
00239 }
00240 
00241 void KToolInvocation::invokeHelp( const QString& anchor,
00242                                   const QString& _appname,
00243                                   const QByteArray& startup_id )
00244 {
00245     if (!isMainThreadActive())
00246         return;
00247 
00248     QString url;
00249     QString appname;
00250     if (_appname.isEmpty()) {
00251         appname = QCoreApplication::instance()->applicationName();
00252     } else
00253         appname = _appname;
00254 
00255     if (!anchor.isEmpty())
00256         url = QString("help:/%1?anchor=%2").arg(appname).arg(anchor);
00257     else
00258         url = QString("help:/%1/index.html").arg(appname);
00259 
00260     QDBusInterface *iface = new QDBusInterface(QLatin1String("org.kde.khelpcenter"),
00261                                                QLatin1String("/KHelpCenter"),
00262                                                QLatin1String("org.kde.khelpcenter.khelpcenter"),
00263                                                QDBusConnection::sessionBus());
00264     if ( !iface->isValid() )
00265     {
00266         QString error;
00267 #ifdef Q_WS_WIN
00268         // startServiceByDesktopName() does not work yet; KRun:processDesktopExec returned 'KRun: syntax error in command "khelpcenter %u" , service "KHelpCenter" '
00269         if (kdeinitExec( "khelpcenter", QStringList() << url, &error, 0, startup_id ))
00270 #else
00271         if (startServiceByDesktopName("khelpcenter", url, &error, 0, 0, startup_id, false))
00272 #endif
00273         {
00274             KMessage::message(KMessage::Error,
00275                               i18n("Could not launch the KDE Help Center:\n\n%1", error),
00276                               i18n("Could not Launch Help Center"));
00277             return;
00278         }
00279 
00280         delete iface;
00281         iface = new QDBusInterface(QLatin1String("org.kde.khelpcenter"),
00282                                    QLatin1String("/KHelpCenter"),
00283                                    QLatin1String("org.kde.khelpcenter.khelpcenter"),
00284                                    QDBusConnection::sessionBus());
00285     }
00286 
00287     iface->call("openUrl", url, startup_id );
00288     delete iface;
00289 }
00290 
00291 void KToolInvocation::invokeMailer(const QString &address, const QString &subject, const QByteArray& startup_id)
00292 {
00293     if (!isMainThreadActive())
00294         return;
00295 
00296     invokeMailer(address, QString(), QString(), subject, QString(), QString(),
00297                  QStringList(), startup_id );
00298 }
00299 
00300 void KToolInvocation::invokeMailer(const KUrl &mailtoURL, const QByteArray& startup_id, bool allowAttachments )
00301 {
00302     if (!isMainThreadActive())
00303         return;
00304 
00305     QString address = KUrl::fromPercentEncoding(mailtoURL.path().toLatin1()), subject, cc, bcc, body;
00306     const QStringList queries = mailtoURL.query().mid(1).split( '&');
00307     QStringList attachURLs;
00308     for (QStringList::ConstIterator it = queries.begin(); it != queries.end(); ++it)
00309     {
00310         QString q = (*it).toLower();
00311         if (q.startsWith("subject="))
00312             subject = KUrl::fromPercentEncoding((*it).mid(8).toLatin1());
00313         else
00314             if (q.startsWith("cc="))
00315                 cc = cc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): cc + ',' + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
00316             else
00317                 if (q.startsWith("bcc="))
00318                     bcc = bcc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(4).toLatin1()): bcc + ',' + KUrl::fromPercentEncoding((*it).mid(4).toLatin1());
00319                 else
00320                     if (q.startsWith("body="))
00321                         body = KUrl::fromPercentEncoding((*it).mid(5).toLatin1());
00322                     else
00323                         if (allowAttachments && q.startsWith("attach="))
00324                             attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(7).toLatin1()));
00325                         else
00326                             if (allowAttachments && q.startsWith("attachment="))
00327                                 attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(11).toLatin1()));
00328                             else
00329                                 if (q.startsWith("to="))
00330                                     address = address.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): address + ',' + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
00331     }
00332 
00333     invokeMailer( address, cc, bcc, subject, body, QString(), attachURLs, startup_id );
00334 }
00335 
00336 void KToolInvocation::startKdeinit()
00337 {
00338   KComponentData inst( "startkdeinitlock" );
00339   KLockFile lock( KStandardDirs::locateLocal( "tmp", "startkdeinitlock", inst ));
00340   if( lock.lock( KLockFile::NoBlockFlag ) != KLockFile::LockOK ) {
00341      lock.lock();
00342      if( QDBusConnection::sessionBus().interface()->isServiceRegistered( "org.kde.klauncher" ))
00343          return; // whoever held the lock has already started it
00344   }
00345   // Try to launch kdeinit.
00346   QString srv = KStandardDirs::findExe(QLatin1String("kdeinit4"));
00347   if (srv.isEmpty())
00348      return;
00349 //   this is disabled because we are in kdecore
00350 //  const bool gui = qApp && qApp->type() != QApplication::Tty;
00351 //  if ( gui )
00352 //    qApp->setOverrideCursor( Qt::WaitCursor );
00353   QStringList args;
00354 #ifndef Q_WS_WIN
00355   args += "--suicide";
00356 #endif
00357   QProcess::execute(srv, args);
00358 //  if ( gui )
00359 //    qApp->restoreOverrideCursor();
00360 }
00361 
00362 #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
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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