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

KDECore

  • kdecore
  • kernel
ktoolinvocation.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
3  Copyright (C) 2006 Thiago Macieira <thiago@kde.org>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "ktoolinvocation.h"
22 #include "klauncher_iface.h"
23 #include "kdebug.h"
24 #include "kglobal.h"
25 #include "kstandarddirs.h"
26 #include "kcomponentdata.h"
27 #include "kurl.h"
28 #include "kmessage.h"
29 #include "kservice.h"
30 #include <klockfile.h>
31 #include <klocale.h>
32 
33 #include <QMutex>
34 #include <QMutexLocker>
35 #include <QCoreApplication>
36 #include <QThread>
37 
38 #include <errno.h>
39 
40 
41 KToolInvocation *KToolInvocation::self()
42 {
43  K_GLOBAL_STATIC(KToolInvocation, s_self)
44  return s_self;
45 }
46 
47 KToolInvocation::KToolInvocation() : QObject(0), d(0)
48 {
49 }
50 
51 KToolInvocation::~KToolInvocation()
52 {
53 }
54 
55 Q_GLOBAL_STATIC_WITH_ARGS(org::kde::KLauncher, klauncherIface,
56  (QString::fromLatin1("org.kde.klauncher"), QString::fromLatin1("/KLauncher"), QDBusConnection::sessionBus()))
57 
58 org::kde::KLauncher *KToolInvocation::klauncher()
59 {
60  if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(QString::fromLatin1("org.kde.klauncher"))) {
61  kDebug(180) << "klauncher not running... launching kdeinit";
62  KToolInvocation::startKdeinit();
63  }
64  return ::klauncherIface();
65 }
66 
67 static void printError(const QString& text, QString* error)
68 {
69  if (error)
70  *error = text;
71  else
72  kError() << text << endl;
73 }
74 
75 bool KToolInvocation::isMainThreadActive(QString* error)
76 {
77  if (QCoreApplication::instance() && QCoreApplication::instance()->thread() != QThread::currentThread())
78  {
79  printError(i18n("Function must be called from the main thread."), error);
80  return false;
81  }
82 
83  return true;
84 }
85 
86 int KToolInvocation::startServiceInternal(const char *_function,
87  const QString& _name, const QStringList &URLs,
88  QString *error, QString *serviceName, int *pid,
89  const QByteArray& startup_id, bool noWait,
90  const QString& workdir)
91 {
92  QString function = QLatin1String(_function);
93  org::kde::KLauncher *launcher = KToolInvocation::klauncher();
94  QDBusMessage msg = QDBusMessage::createMethodCall(launcher->service(),
95  launcher->path(),
96  launcher->interface(),
97  function);
98  msg << _name << URLs;
99  if (function == QLatin1String("kdeinit_exec_with_workdir"))
100  msg << workdir;
101 #ifdef Q_WS_X11
102  // make sure there is id, so that user timestamp exists
103  QStringList envs;
104  QByteArray s = startup_id;
105  emit kapplication_hook(envs, s);
106  msg << envs;
107  msg << QString::fromLatin1(s);
108 #else
109  msg << QStringList();
110  msg << QString();
111 #endif
112  if( !function.startsWith( QLatin1String("kdeinit_exec") ) )
113  msg << noWait;
114 
115  QDBusMessage reply = QDBusConnection::sessionBus().call(msg, QDBus::Block, INT_MAX);
116  if ( reply.type() != QDBusMessage::ReplyMessage )
117  {
118  QDBusReply<QString> replyObj(reply);
119  if (replyObj.error().type() == QDBusError::NoReply) {
120  printError(i18n("Error launching %1. Either KLauncher is not running anymore, or it failed to start the application.", _name), error);
121  } else {
122  const QString rpl = reply.arguments().count() > 0 ? reply.arguments().at(0).toString() : reply.errorMessage();
123  printError(i18n("KLauncher could not be reached via D-Bus. Error when calling %1:\n%2\n",function, rpl), error);
124  }
125  //qDebug() << reply;
126  return EINVAL;
127  }
128 
129  if (noWait)
130  return 0;
131 
132  Q_ASSERT(reply.arguments().count() == 4);
133  if (serviceName)
134  *serviceName = reply.arguments().at(1).toString();
135  if (error)
136  *error = reply.arguments().at(2).toString();
137  if (pid)
138  *pid = reply.arguments().at(3).toInt();
139  return reply.arguments().at(0).toInt();
140 }
141 
142 #ifndef KDE_NO_DEPRECATED
143 int
144 KToolInvocation::startServiceByName( const QString& _name, const QString &URL,
145  QString *error, QString *serviceName, int *pid,
146  const QByteArray& startup_id, bool noWait )
147 {
148  if (!isMainThreadActive(error))
149  return EINVAL;
150 
151  QStringList URLs;
152  if (!URL.isEmpty())
153  URLs.append(URL);
154  return self()->startServiceInternal("start_service_by_name",
155  _name, URLs, error, serviceName, pid, startup_id, noWait);
156 }
157 #endif
158 
159 #ifndef KDE_NO_DEPRECATED
160 int
161 KToolInvocation::startServiceByName( const QString& _name, const QStringList &URLs,
162  QString *error, QString *serviceName, int *pid,
163  const QByteArray& startup_id, bool noWait )
164 {
165  if (!isMainThreadActive(error))
166  return EINVAL;
167 
168  return self()->startServiceInternal("start_service_by_name",
169  _name, URLs, error, serviceName, pid, startup_id, noWait);
170 }
171 #endif
172 
173 int
174 KToolInvocation::startServiceByDesktopPath( const QString& _name, const QString &URL,
175  QString *error, QString *serviceName,
176  int *pid, const QByteArray& startup_id, bool noWait )
177 {
178  if (!isMainThreadActive(error))
179  return EINVAL;
180 
181  QStringList URLs;
182  if (!URL.isEmpty())
183  URLs.append(URL);
184  return self()->startServiceInternal("start_service_by_desktop_path",
185  _name, URLs, error, serviceName, pid, startup_id, noWait);
186 }
187 
188 int
189 KToolInvocation::startServiceByDesktopPath( const QString& _name, const QStringList &URLs,
190  QString *error, QString *serviceName, int *pid,
191  const QByteArray& startup_id, bool noWait )
192 {
193  if (!isMainThreadActive(error))
194  return EINVAL;
195 
196  return self()->startServiceInternal("start_service_by_desktop_path",
197  _name, URLs, error, serviceName, pid, startup_id, noWait);
198 }
199 
200 int
201 KToolInvocation::startServiceByDesktopName( const QString& _name, const QString &URL,
202  QString *error, QString *serviceName, int *pid,
203  const QByteArray& startup_id, bool noWait )
204 {
205  if (!isMainThreadActive(error))
206  return EINVAL;
207 
208  QStringList URLs;
209  if (!URL.isEmpty())
210  URLs.append(URL);
211  return self()->startServiceInternal("start_service_by_desktop_name",
212  _name, URLs, error, serviceName, pid, startup_id, noWait);
213 }
214 
215 int
216 KToolInvocation::startServiceByDesktopName( const QString& _name, const QStringList &URLs,
217  QString *error, QString *serviceName, int *pid,
218  const QByteArray& startup_id, bool noWait )
219 {
220  if (!isMainThreadActive(error))
221  return EINVAL;
222 
223  return self()->startServiceInternal("start_service_by_desktop_name",
224  _name, URLs, error, serviceName, pid, startup_id, noWait);
225 }
226 
227 int
228 KToolInvocation::kdeinitExec( const QString& name, const QStringList &args,
229  QString *error, int *pid, const QByteArray& startup_id )
230 {
231  if (!isMainThreadActive(error))
232  return EINVAL;
233 
234  return self()->startServiceInternal("kdeinit_exec",
235  name, args, error, 0, pid, startup_id, false);
236 }
237 
238 
239 int
240 KToolInvocation::kdeinitExecWait( const QString& name, const QStringList &args,
241  QString *error, int *pid, const QByteArray& startup_id )
242 {
243  if (!isMainThreadActive(error))
244  return EINVAL;
245 
246  return self()->startServiceInternal("kdeinit_exec_wait",
247  name, args, error, 0, pid, startup_id, false);
248 }
249 
250 void KToolInvocation::invokeHelp( const QString& anchor,
251  const QString& _appname,
252  const QByteArray& startup_id )
253 {
254  if (!isMainThreadActive())
255  return;
256 
257  KUrl url;
258  QString appname;
259  QString docPath;
260  if (_appname.isEmpty()) {
261  appname = QCoreApplication::instance()->applicationName();
262  } else
263  appname = _appname;
264 
265  KService::Ptr service(KService::serviceByDesktopName(appname));
266  if (service) {
267  docPath = service->docPath();
268  }
269 
270  if (!docPath.isEmpty()) {
271  url = KUrl(KUrl("help:/"), docPath);
272  } else {
273  url = QString::fromLatin1("help:/%1/index.html").arg(appname);
274  }
275 
276  if (!anchor.isEmpty()) {
277  url.addQueryItem(QString::fromLatin1("anchor"), anchor);
278  }
279 
280  // launch a browser for URIs not handled by khelpcenter
281  // (following KCMultiDialog::slotHelpClicked())
282  if (!(url.protocol() == QLatin1String("help") || url.protocol() == QLatin1String("man") || url.protocol() == QLatin1String("info"))) {
283  invokeBrowser(url.url());
284  return;
285  }
286 
287  QDBusInterface *iface = new QDBusInterface(QLatin1String("org.kde.khelpcenter"),
288  QLatin1String("/KHelpCenter"),
289  QLatin1String("org.kde.khelpcenter.khelpcenter"),
290  QDBusConnection::sessionBus());
291  if ( !iface->isValid() )
292  {
293  QString error;
294 #ifdef Q_WS_WIN
295  // startServiceByDesktopName() does not work yet; KRun:processDesktopExec returned 'KRun: syntax error in command "khelpcenter %u" , service "KHelpCenter" '
296  if (kdeinitExec(QLatin1String("khelpcenter"), QStringList() << url.url(), &error, 0, startup_id))
297 #else
298  if (startServiceByDesktopName(QLatin1String("khelpcenter"), url.url(), &error, 0, 0, startup_id, false))
299 #endif
300  {
301  KMessage::message(KMessage::Error,
302  i18n("Could not launch the KDE Help Center:\n\n%1", error),
303  i18n("Could not Launch Help Center"));
304  delete iface;
305  return;
306  }
307 
308  delete iface;
309  iface = new QDBusInterface(QLatin1String("org.kde.khelpcenter"),
310  QLatin1String("/KHelpCenter"),
311  QLatin1String("org.kde.khelpcenter.khelpcenter"),
312  QDBusConnection::sessionBus());
313  }
314 
315  iface->call(QString::fromLatin1("openUrl"), url.url(), startup_id );
316  delete iface;
317 }
318 
319 void KToolInvocation::invokeMailer(const QString &address, const QString &subject, const QByteArray& startup_id)
320 {
321  if (!isMainThreadActive())
322  return;
323 
324  invokeMailer(address, QString(), QString(), subject, QString(), QString(),
325  QStringList(), startup_id );
326 }
327 
328 void KToolInvocation::invokeMailer(const KUrl &mailtoURL, const QByteArray& startup_id, bool allowAttachments )
329 {
330  if (!isMainThreadActive())
331  return;
332 
333  QString address = mailtoURL.path();
334  QString subject;
335  QString cc;
336  QString bcc;
337  QString body;
338 
339  const QStringList queries = mailtoURL.query().mid(1).split(QLatin1Char('&'));
340  const QChar comma = QChar::fromLatin1(',');
341  QStringList attachURLs;
342  for (QStringList::ConstIterator it = queries.begin(); it != queries.end(); ++it)
343  {
344  QString q = (*it).toLower();
345  if (q.startsWith(QLatin1String("subject=")))
346  subject = KUrl::fromPercentEncoding((*it).mid(8).toLatin1());
347  else
348  if (q.startsWith(QLatin1String("cc=")))
349  cc = cc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): cc + comma + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
350  else
351  if (q.startsWith(QLatin1String("bcc=")))
352  bcc = bcc.isEmpty()? KUrl::fromPercentEncoding((*it).mid(4).toLatin1()): bcc + comma + KUrl::fromPercentEncoding((*it).mid(4).toLatin1());
353  else
354  if (q.startsWith(QLatin1String("body=")))
355  body = KUrl::fromPercentEncoding((*it).mid(5).toLatin1());
356  else
357  if (allowAttachments && q.startsWith(QLatin1String("attach=")))
358  attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(7).toLatin1()));
359  else
360  if (allowAttachments && q.startsWith(QLatin1String("attachment=")))
361  attachURLs.push_back(KUrl::fromPercentEncoding((*it).mid(11).toLatin1()));
362  else
363  if (q.startsWith(QLatin1String("to=")))
364  address = address.isEmpty()? KUrl::fromPercentEncoding((*it).mid(3).toLatin1()): address + comma + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
365  }
366 
367  invokeMailer( address, cc, bcc, subject, body, QString(), attachURLs, startup_id );
368 }
369 
370 void KToolInvocation::startKdeinit()
371 {
372  KComponentData inst( "startkdeinitlock" );
373  KLockFile lock( KStandardDirs::locateLocal("tmp", QString::fromLatin1("startkdeinitlock"), inst ));
374  if( lock.lock( KLockFile::NoBlockFlag ) != KLockFile::LockOK ) {
375  lock.lock();
376  if( QDBusConnection::sessionBus().interface()->isServiceRegistered(QString::fromLatin1("org.kde.klauncher")))
377  return; // whoever held the lock has already started it
378  }
379  // Try to launch kdeinit.
380  QString srv = KStandardDirs::findExe(QLatin1String("kdeinit4"));
381  if (srv.isEmpty())
382  return;
383 // this is disabled because we are in kdecore
384 // const bool gui = qApp && qApp->type() != QApplication::Tty;
385 // if ( gui )
386 // qApp->setOverrideCursor( Qt::WaitCursor );
387  QStringList args;
388 #ifndef Q_WS_WIN
389  args += QString::fromLatin1("--suicide");
390 #endif
391  QProcess::execute(srv, args);
392 // if ( gui )
393 // qApp->restoreOverrideCursor();
394 }
395 
396 #include "ktoolinvocation.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Apr 20 2013 05:59:12 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs-4.10.2 API Reference

Skip menu "kdelibs-4.10.2 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal