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

KDECore

ktoolinvocation_x11.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (c) 1997,1998 Matthias Kalle Dalheimer <kalle@kde.org>
00003     Copyright (c) 1999 Espen Sand <espen@kde.org>
00004     Copyright (c) 2000-2004 Frerich Raabe <raabe@kde.org>
00005     Copyright (c) 2003,2004 Oswald Buddenhagen <ossi@kde.org>
00006     Copyright (c) 2006 Thiago Macieira <thiago@kde.org>
00007     Copyright (C) 2008 Aaron Seigo <aseigo@kde.org>
00008 
00009     This library is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU Library General Public
00011     License as published by the Free Software Foundation; either
00012     version 2 of the License, or (at your option) any later version.
00013 
00014     This library is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017     Library General Public License for more details.
00018 
00019     You should have received a copy of the GNU Library General Public License
00020     along with this library; see the file COPYING.LIB.  If not, write to
00021     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00022     Boston, MA 02110-1301, USA.
00023 */
00024 
00025 #include <config.h>
00026 
00027 #include "ktoolinvocation.h"
00028 
00029 #include <kconfiggroup.h>
00030 
00031 #include "kcmdlineargs.h"
00032 #include "kconfig.h"
00033 #include "kcodecs.h"
00034 #include "kdebug.h"
00035 #include "kglobal.h"
00036 #include "kshell.h"
00037 #include "kmacroexpander.h"
00038 #include "klocale.h"
00039 #include "kstandarddirs.h"
00040 #include "kmessage.h"
00041 #include "kservice.h"
00042 
00043 #include <QtCore/QCoreApplication>
00044 #include <QtCore/QProcess>
00045 #include <QtCore/QHash>
00046 #include <QtCore/QDebug>
00047 #include <QtCore/QBool>
00048 #include <QtCore/QFile>
00049 #include <QtDBus/QtDBus>
00050 
00051 static QStringList splitEmailAddressList( const QString & aStr )
00052 {
00053     // This is a copy of KPIM::splitEmailAddrList().
00054     // Features:
00055     // - always ignores quoted characters
00056     // - ignores everything (including parentheses and commas)
00057     //   inside quoted strings
00058     // - supports nested comments
00059     // - ignores everything (including double quotes and commas)
00060     //   inside comments
00061 
00062     QStringList list;
00063 
00064     if (aStr.isEmpty())
00065         return list;
00066 
00067     QString addr;
00068     uint addrstart = 0;
00069     int commentlevel = 0;
00070     bool insidequote = false;
00071 
00072     for (int index=0; index<aStr.length(); index++) {
00073         // the following conversion to latin1 is o.k. because
00074         // we can safely ignore all non-latin1 characters
00075         switch (aStr[index].toLatin1()) {
00076         case '"' : // start or end of quoted string
00077             if (commentlevel == 0)
00078                 insidequote = !insidequote;
00079             break;
00080         case '(' : // start of comment
00081             if (!insidequote)
00082                 commentlevel++;
00083             break;
00084         case ')' : // end of comment
00085             if (!insidequote) {
00086                 if (commentlevel > 0)
00087                     commentlevel--;
00088                 else {
00089                     //kDebug() << "Error in address splitting: Unmatched ')'"
00090                     //          << endl;
00091                     return list;
00092                 }
00093             }
00094             break;
00095         case '\\' : // quoted character
00096             index++; // ignore the quoted character
00097             break;
00098         case ',' :
00099             if (!insidequote && (commentlevel == 0)) {
00100                 addr = aStr.mid(addrstart, index-addrstart);
00101                 if (!addr.isEmpty())
00102                     list += addr.simplified();
00103                 addrstart = index+1;
00104             }
00105             break;
00106         }
00107     }
00108     // append the last address to the list
00109     if (!insidequote && (commentlevel == 0)) {
00110         addr = aStr.mid(addrstart, aStr.length()-addrstart);
00111         if (!addr.isEmpty())
00112             list += addr.simplified();
00113     }
00114     //else
00115     //  kDebug() << "Error in address splitting: "
00116     //            << "Unexpected end of address list"
00117     //            << endl;
00118 
00119     return list;
00120 }
00121 
00122 #ifdef Q_WS_MAEMO_5
00123 // taken from QDesktopServices, which we cannot use here due to it being in QtGui
00124 inline static bool maemo5Launch(const QUrl &url)
00125 {
00126     typedef bool (*Ptr_hildon_uri_open)(const char *, void *, void **);
00127     static Ptr_hildon_uri_open hildon_uri_open = 0;
00128 
00129     if (!hildon_uri_open) {
00130         QLibrary lib(QLatin1String("libhildonmime"), 0, 0);
00131         hildon_uri_open = (Ptr_hildon_uri_open)lib.resolve("hildon_uri_open");
00132     }
00133     if (hildon_uri_open)
00134         return hildon_uri_open(url.toEncoded().constData(), 0, 0);
00135     return false;
00136 }
00137 #endif
00138 
00139 void KToolInvocation::invokeMailer(const QString &_to, const QString &_cc, const QString &_bcc,
00140                                    const QString &subject, const QString &body,
00141                                    const QString & /*messageFile TODO*/, const QStringList &attachURLs,
00142                                    const QByteArray& startup_id )
00143 {
00144     if (!isMainThreadActive())
00145         return;
00146 
00147     KConfig config(QString::fromLatin1("emaildefaults"));
00148     KConfigGroup defaultsGrp(&config, "Defaults");
00149 
00150     QString group = defaultsGrp.readEntry("Profile","Default");
00151 
00152     KConfigGroup profileGrp(&config, QString::fromLatin1("PROFILE_%1").arg(group) );
00153     QString command = profileGrp.readPathEntry("EmailClient", QString());
00154 
00155     QString to, cc, bcc;
00156     if (command.isEmpty() || command == QLatin1String("kmail")
00157         || command.endsWith(QLatin1String("/kmail")))
00158     {
00159         command = QLatin1String("kmail --composer -s %s -c %c -b %b --body %B --attach %A -- %t");
00160         if ( !_to.isEmpty() )
00161         {
00162             KUrl url;
00163             url.setProtocol(QLatin1String("mailto"));
00164             url.setPath(_to);
00165             to = QString::fromLatin1(url.toEncoded());
00166         }
00167         if ( !_cc.isEmpty() )
00168         {
00169             KUrl url;
00170             url.setProtocol(QLatin1String("mailto"));
00171             url.setPath(_cc);
00172             cc = QString::fromLatin1(url.toEncoded());
00173         }
00174         if ( !_bcc.isEmpty() )
00175         {
00176             KUrl url;
00177             url.setProtocol(QLatin1String("mailto"));
00178             url.setPath(_bcc);
00179             bcc = QString::fromLatin1(url.toEncoded());
00180         }
00181     } else {
00182         to = _to;
00183         cc = _cc;
00184         bcc = _bcc;
00185         if( !command.contains( QLatin1Char('%') ))
00186             command += QLatin1String(" %u");
00187     }
00188 
00189     if (profileGrp.readEntry("TerminalClient", false))
00190     {
00191         KConfigGroup confGroup( KGlobal::config(), "General" );
00192         QString preferredTerminal = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
00193         command = preferredTerminal + QString::fromLatin1(" -e ") + command;
00194     }
00195 
00196     QStringList cmdTokens = KShell::splitArgs(command);
00197     QString cmd = cmdTokens.takeFirst();
00198 
00199     KUrl url;
00200     //QStringList qry;
00201     if (!to.isEmpty())
00202     {
00203         QStringList tos = splitEmailAddressList( to );
00204         url.setPath( tos.first() );
00205         tos.erase( tos.begin() );
00206         for (QStringList::ConstIterator it = tos.constBegin(); it != tos.constEnd(); ++it)
00207             url.addQueryItem(QString::fromLatin1("to"), *it);
00208         //qry.append( "to=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
00209     }
00210     const QStringList ccs = splitEmailAddressList( cc );
00211     for (QStringList::ConstIterator it = ccs.constBegin(); it != ccs.constEnd(); ++it)
00212         url.addQueryItem(QString::fromLatin1("cc"), *it);
00213     //qry.append( "cc=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
00214     const QStringList bccs = splitEmailAddressList( bcc );
00215     for (QStringList::ConstIterator it = bccs.constBegin(); it != bccs.constEnd(); ++it)
00216         url.addQueryItem(QString::fromLatin1("bcc"), *it);
00217     //qry.append( "bcc=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
00218     for (QStringList::ConstIterator it = attachURLs.constBegin(); it != attachURLs.constEnd(); ++it)
00219         url.addQueryItem(QString::fromLatin1("attach"), *it);
00220     //qry.append( "attach=" + QLatin1String(KUrl::toPercentEncoding( *it ) ));
00221     if (!subject.isEmpty())
00222         url.addQueryItem(QString::fromLatin1("subject"), subject);
00223     //qry.append( "subject=" + QLatin1String(KUrl::toPercentEncoding( subject ) ));
00224     if (!body.isEmpty())
00225         url.addQueryItem(QString::fromLatin1("body"), body);
00226     //qry.append( "body=" + QLatin1String(KUrl::toPercentEncoding( body ) ));
00227     //url.setQuery( qry.join( "&" ) );
00228 
00229     if ( ! (to.isEmpty() && (!url.hasQuery())) )
00230         url.setProtocol(QString::fromLatin1("mailto"));
00231 
00232     QHash<QChar, QString> keyMap;
00233     keyMap.insert(QLatin1Char('t'), to);
00234     keyMap.insert(QLatin1Char('s'), subject);
00235     keyMap.insert(QLatin1Char('c'), cc);
00236     keyMap.insert(QLatin1Char('b'), bcc);
00237     keyMap.insert(QLatin1Char('B'), body);
00238     keyMap.insert(QLatin1Char('u'), url.url());
00239 
00240     QString attachlist = attachURLs.join(QString::fromLatin1(","));
00241     attachlist.prepend(QLatin1Char('\''));
00242     attachlist.append(QLatin1Char('\''));
00243     keyMap.insert(QLatin1Char('A'), attachlist);
00244 
00245     for (QStringList::Iterator it = cmdTokens.begin(); it != cmdTokens.end(); )
00246     {
00247         if (*it == QLatin1String("%A"))
00248         {
00249             if (it == cmdTokens.begin()) // better safe than sorry ...
00250                 continue;
00251             QStringList::ConstIterator urlit = attachURLs.begin();
00252             QStringList::ConstIterator urlend = attachURLs.end();
00253             if ( urlit != urlend )
00254             {
00255                 QStringList::Iterator previt = it;
00256                 --previt;
00257                 *it = *urlit;
00258                 ++it;
00259                 while ( ++urlit != urlend )
00260                 {
00261                     cmdTokens.insert( it, *previt );
00262                     cmdTokens.insert( it, *urlit );
00263                 }
00264             } else {
00265                 --it;
00266                 it = cmdTokens.erase( cmdTokens.erase( it ) );
00267             }
00268         } else {
00269             *it = KMacroExpander::expandMacros(*it, keyMap);
00270             ++it;
00271         }
00272     }
00273 
00274     QString error;
00275     // TODO this should check if cmd has a .desktop file, and use data from it, together
00276     // with sending more ASN data
00277     if (kdeinitExec(cmd, cmdTokens, &error, NULL, startup_id ))
00278     {
00279       KMessage::message(KMessage::Error,
00280                       i18n("Could not launch the mail client:\n\n%1", error),
00281                       i18n("Could not launch Mail Client"));
00282     }
00283 }
00284 
00285 void KToolInvocation::invokeBrowser( const QString &url, const QByteArray& startup_id )
00286 {
00287     if (!isMainThreadActive())
00288         return;
00289 
00290 #ifdef Q_WS_MAEMO_5
00291     if (maemo5Launch(url))
00292       return;
00293 #endif
00294     QStringList args;
00295     args << url;
00296     QString error;
00297 
00298     // This method should launch a webbrowser, preferably without doing a mimetype
00299     // check first, like KRun (i.e. kde-open) would do.
00300 
00301     // In a KDE session, honour BrowserApplication if set, otherwise call kfmclient if present,
00302     // otherwise xdg-open, otherwise kde-open (which does a mimetype check first though).
00303 
00304     // Outside KDE, call xdg-open if present, otherwise fallback to the above logic.
00305 
00306     QString exe; // the binary we are going to launch.
00307 
00308     const QString xdg_open = KStandardDirs::findExe(QString::fromLatin1("xdg-open"));
00309     if (qgetenv("KDE_FULL_SESSION").isEmpty()) {
00310         exe = xdg_open;
00311     }
00312 
00313     if (exe.isEmpty()) {
00314         // We're in a KDE session (or there's no xdg-open installed)
00315         KConfigGroup config(KGlobal::config(), "General");
00316         const QString browserApp = config.readPathEntry("BrowserApplication", QString());
00317         if (!browserApp.isEmpty()) {
00318             exe = browserApp;
00319             if (exe.startsWith(QLatin1Char('!'))) {
00320                 exe = exe.mid(1); // Literal command
00321                 QStringList cmdTokens = KShell::splitArgs(exe);
00322                 exe = cmdTokens.takeFirst();
00323                 args = cmdTokens + args;
00324             } else {
00325                 // desktop file ID
00326                 KService::Ptr service = KService::serviceByStorageId(exe);
00327                 if (service) {
00328                     kDebug() << "Starting service" << service->entryPath();
00329                     if (startServiceByDesktopPath(service->entryPath(), args,
00330                             &error, 0, 0, startup_id)) {
00331                         KMessage::message(KMessage::Error,
00332                                           // TODO: i18n("Could not launch %1:\n\n%2", exe, error),
00333                                           i18n("Could not launch the browser:\n\n%1", error),
00334                                           i18n("Could not launch Browser"));
00335                     }
00336                     return;
00337                 }
00338             }
00339         } else {
00340             const QString kfmclient = KStandardDirs::findExe(QString::fromLatin1("kfmclient"));
00341             if (!kfmclient.isEmpty()) {
00342                 exe = kfmclient;
00343                 args.prepend(QLatin1String("openURL"));
00344             } else {
00345                 exe = xdg_open;
00346             }
00347         }
00348     }
00349 
00350     if (exe.isEmpty()) {
00351         exe = QString::fromLatin1("kde-open"); // it's from kdebase-runtime, it has to be there.
00352     }
00353 
00354     kDebug(180) << "Using" << exe << "to open" << url;
00355     if (kdeinitExec(exe, args, &error, NULL, startup_id ))
00356     {
00357         KMessage::message(KMessage::Error,
00358                           // TODO: i18n("Could not launch %1:\n\n%2", exe, error),
00359                           i18n("Could not launch the browser:\n\n%1", error),
00360                           i18n("Could not launch Browser"));
00361     }
00362 }
00363 
00364 void KToolInvocation::invokeTerminal(const QString &command,
00365                                      const QString &workdir,
00366                                      const QByteArray &startup_id)
00367 {
00368     if (!isMainThreadActive()) {
00369         return;
00370     }
00371 
00372     KConfigGroup confGroup( KGlobal::config(), "General" );
00373     QString exec = confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
00374 
00375     if (!command.isEmpty()) {
00376         if (exec == QLatin1String("konsole")) {
00377             exec += QString::fromLatin1(" --noclose");
00378         } else if (exec == QLatin1String("xterm")) {
00379             exec += QString::fromLatin1(" -hold");
00380         }
00381 
00382         exec += QString::fromLatin1(" -e ") + command;
00383     }
00384 
00385     QStringList cmdTokens = KShell::splitArgs(exec);
00386     QString cmd = cmdTokens.takeFirst();
00387 
00388     if (exec == QLatin1String("konsole") && !workdir.isEmpty()) {
00389         cmdTokens << QString::fromLatin1("--workdir");
00390         cmdTokens << workdir;
00391         // For other terminals like xterm, we'll simply change the working
00392         // directory before launching them, see below.
00393     }
00394 
00395     QString error;
00396     if (self()->startServiceInternal("kdeinit_exec_with_workdir",
00397                                     cmd, cmdTokens, &error, 0, NULL, startup_id, false, workdir)) {
00398       KMessage::message(KMessage::Error,
00399                       i18n("Could not launch the terminal client:\n\n%1", error),
00400                       i18n("Could not launch Terminal Client"));
00401     }
00402 }

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