KDECore
kcmdlineargs.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 1999 Waldo Bastian <bastian@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include "kcmdlineargs.h" 00020 #include <kdebug.h> 00021 00022 #include <config.h> 00023 00024 #include <sys/param.h> 00025 00026 #include <assert.h> 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 #include <string.h> 00030 #include <unistd.h> 00031 #include <locale.h> 00032 00033 #ifdef HAVE_LIMITS_H 00034 #include <limits.h> 00035 #endif 00036 00037 #include <QtCore/QDir> 00038 #include <QtCore/QFile> 00039 #include <QtCore/QHash> 00040 #include <QtCore/QTextCodec> 00041 00042 #include "kaboutdata.h" 00043 #include "klocale.h" 00044 #include "kdeversion.h" 00045 #include "kcomponentdata.h" 00046 #include "kglobal.h" 00047 #include "kurl.h" 00048 00049 #include "kuitsemantics_p.h" // for escaping arguments in i18n 00050 00051 // ----------------------------------------------------------------------------- 00052 // Design notes: 00053 // 00054 // These classes deal with a lot of text, some of which needs to be 00055 // marked for translation. Since at the time when these object and calls are 00056 // made the translation catalogs are usually still not initialized, the 00057 // translation has to be delayed. This is achieved by using KLocalizedString 00058 // for translatable strings. KLocalizedStrings are produced by ki18n* calls, 00059 // instead of the more usuall i18n* calls which produce QString by trying to 00060 // translate immediately. 00061 // 00062 // All the non-translatable string arguments to methods are taken QByteArray, 00063 // all the translatable are KLocalizedString. The getter methods always return 00064 // proper QString: the non-translatable strings supplied by the code are 00065 // treated with QString::fromUtf8(), those coming from the outside with 00066 // QTextCodec::toUnicode(), and translatable strings are finalized to QStrings 00067 // at the point of getter calls (i.e. delayed translation). 00068 // 00069 // The code below uses locally defined s->decodeInput(QByteArray) and 00070 // s->encodeOutput(QString) calls to centralize the conversion of raw external 00071 // bytes (instead of QString::to/fromLocal8Bit(), QFile::decodeName, etc.) 00072 // ----------------------------------------------------------------------------- 00073 00074 #ifdef Q_WS_X11 00075 #define DISPLAY "DISPLAY" 00076 #elif defined(Q_WS_QWS) 00077 #define DISPLAY "QWS_DISPLAY" 00078 #else 00079 #define DISPLAY "NODISPLAY" 00080 #endif 00081 00082 // 00083 // Helper classes 00084 // 00085 00086 class KCmdLineParsedOptions : public QHash<QByteArray,QByteArray> 00087 { 00088 public: 00089 KCmdLineParsedOptions() { } 00090 }; 00091 00092 class KCmdLineParsedArgs : public QList<QByteArray> 00093 { 00094 public: 00095 KCmdLineParsedArgs() { } 00096 }; 00097 00098 00099 class KCmdLineArgsList: public QList<KCmdLineArgs*> 00100 { 00101 public: 00102 KCmdLineArgsList() { } 00103 ~KCmdLineArgsList() { 00104 while (count()) 00105 delete takeFirst(); 00106 } 00107 }; 00108 00109 // 00110 // KCmdLineOptions 00111 // 00112 00113 class KCmdLineOptionsPrivate { 00114 public: 00115 QList<QByteArray> names; 00116 QList<KLocalizedString> descriptions; 00117 QStringList defaults; 00118 }; 00119 00120 KCmdLineOptions::KCmdLineOptions () 00121 : d(new KCmdLineOptionsPrivate) 00122 {} 00123 00124 KCmdLineOptions::~KCmdLineOptions () 00125 { 00126 delete d; 00127 } 00128 00129 KCmdLineOptions::KCmdLineOptions (const KCmdLineOptions &options) 00130 : d(new KCmdLineOptionsPrivate(*(options.d))) 00131 { 00132 } 00133 00134 KCmdLineOptions& KCmdLineOptions::operator= (const KCmdLineOptions &options) 00135 { 00136 if (this != &options) { 00137 *d = *(options.d); 00138 } 00139 return *this; 00140 } 00141 00142 KCmdLineOptions &KCmdLineOptions::add (const QByteArray &name, 00143 const KLocalizedString &description, 00144 const QByteArray &defaultValue) 00145 { 00146 d->names.append(name); 00147 d->descriptions.append(description); 00148 d->defaults.append(QString::fromUtf8(defaultValue)); 00149 return *this; 00150 } 00151 00152 KCmdLineOptions &KCmdLineOptions::add (const KCmdLineOptions &other) 00153 { 00154 d->names += other.d->names; 00155 d->descriptions += other.d->descriptions; 00156 d->defaults += other.d->defaults; 00157 return *this; 00158 } 00159 00160 // 00161 // KCmdLineArgs static data and methods 00162 // 00163 00164 class KCmdLineArgsStatic { 00165 public: 00166 00167 KCmdLineArgsList *argsList; // All options. 00168 const KAboutData *about; 00169 00170 int all_argc; // The original argc 00171 char **all_argv; // The original argv 00172 char *appName; 00173 bool parsed : 1; // Whether we have parsed the arguments since calling init 00174 bool ignoreUnknown : 1; // Ignore unknown options and arguments 00175 QByteArray mCwd; // Current working directory. Important for KUnqiueApp! 00176 KCmdLineArgs::StdCmdLineArgs mStdargs; 00177 00178 KCmdLineOptions qt_options; 00179 KCmdLineOptions kde_options; 00180 00181 KCmdLineArgsStatic (); 00182 00183 ~KCmdLineArgsStatic (); 00184 00185 QTextCodec *codec; // codec for converting raw input to QString 00186 00194 static QString decodeInput(const QByteArray &rawstr); 00195 00203 static QByteArray encodeOutput(const QString &str); 00204 00209 void printQ(const QString &msg); 00210 00224 static int findOption(const KCmdLineOptions &options, QByteArray &opt, 00225 QByteArray &opt_name, QString &def, bool &enabled); 00226 00232 static void findOption(const QByteArray &optv, const QByteArray &_opt, 00233 int &i, bool _enabled, bool &moreOptions); 00234 00241 static void parseAllArgs(); 00242 00250 static void removeArgs(const QByteArray &id); 00251 }; 00252 00253 K_GLOBAL_STATIC(KCmdLineArgsStatic, s) 00254 00255 KCmdLineArgsStatic::KCmdLineArgsStatic () { 00256 // Global data 00257 argsList = 0; 00258 all_argc = 0; 00259 all_argv = 0; 00260 appName = 0; 00261 mCwd.clear(); 00262 about = 0; 00263 parsed = false; 00264 ignoreUnknown = false; 00265 mStdargs = 0; 00266 00267 // Text codec. 00268 codec = QTextCodec::codecForLocale(); 00269 00270 // Qt options 00271 //FIXME: Check if other options are specific to Qt/X11 00272 #ifdef Q_WS_X11 00273 qt_options.add("display <displayname>", ki18n("Use the X-server display 'displayname'")); 00274 #elif defined(Q_WS_QWS) 00275 qt_options.add("display <displayname>", ki18n("Use the QWS display 'displayname'")); 00276 #else 00277 #endif 00278 qt_options.add("session <sessionId>", ki18n("Restore the application for the given 'sessionId'")); 00279 qt_options.add("cmap", ki18n("Causes the application to install a private color\nmap on an 8-bit display")); 00280 qt_options.add("ncols <count>", ki18n("Limits the number of colors allocated in the color\ncube on an 8-bit display, if the application is\nusing the QApplication::ManyColor color\nspecification")); 00281 qt_options.add("nograb", ki18n("tells Qt to never grab the mouse or the keyboard")); 00282 qt_options.add("dograb", ki18n("running under a debugger can cause an implicit\n-nograb, use -dograb to override")); 00283 qt_options.add("sync", ki18n("switches to synchronous mode for debugging")); 00284 qt_options.add("fn"); 00285 qt_options.add("font <fontname>", ki18n("defines the application font")); 00286 qt_options.add("bg"); 00287 qt_options.add("background <color>", ki18n("sets the default background color and an\napplication palette (light and dark shades are\ncalculated)")); 00288 qt_options.add("fg"); 00289 qt_options.add("foreground <color>", ki18n("sets the default foreground color")); 00290 qt_options.add("btn"); 00291 qt_options.add("button <color>", ki18n("sets the default button color")); 00292 qt_options.add("name <name>", ki18n("sets the application name")); 00293 qt_options.add("title <title>", ki18n("sets the application title (caption)")); 00294 qt_options.add("testability", ki18n("load the testability framework")); 00295 #ifdef Q_WS_X11 00296 qt_options.add("visual TrueColor", ki18n("forces the application to use a TrueColor visual on\nan 8-bit display")); 00297 qt_options.add("inputstyle <inputstyle>", ki18n("sets XIM (X Input Method) input style. Possible\nvalues are onthespot, overthespot, offthespot and\nroot")); 00298 qt_options.add("im <XIM server>", ki18n("set XIM server")); 00299 qt_options.add("noxim", ki18n("disable XIM")); 00300 #endif 00301 #ifdef Q_WS_QWS 00302 qt_options.add("qws", ki18n("forces the application to run as QWS Server")); 00303 #endif 00304 qt_options.add("reverse", ki18n("mirrors the whole layout of widgets")); 00305 qt_options.add("stylesheet <file.qss>", ki18n("applies the Qt stylesheet to the application widgets")); 00306 qt_options.add("graphicssystem <system>", ki18n("use a different graphics system instead of the default one, options are raster and opengl (experimental)")); 00307 qt_options.add("qmljsdebugger <port>", ki18n("QML JS debugger information. Application must be\nbuilt with -DQT_DECLARATIVE_DEBUG for the debugger to be\nenabled")); 00308 // KDE options 00309 kde_options.add("caption <caption>", ki18n("Use 'caption' as name in the titlebar")); 00310 kde_options.add("icon <icon>", ki18n("Use 'icon' as the application icon")); 00311 kde_options.add("config <filename>", ki18n("Use alternative configuration file")); 00312 kde_options.add("nocrashhandler", ki18n("Disable crash handler, to get core dumps")); 00313 #ifdef Q_WS_X11 00314 kde_options.add("waitforwm", ki18n("Waits for a WM_NET compatible windowmanager")); 00315 #endif 00316 kde_options.add("style <style>", ki18n("sets the application GUI style")); 00317 kde_options.add("geometry <geometry>", ki18n("sets the client geometry of the main widget - see man X for the argument format (usually WidthxHeight+XPos+YPos)")); 00318 #ifndef Q_WS_WIN 00319 kde_options.add("smkey <sessionKey>"); // this option is obsolete and exists only to allow smooth upgrades from sessions 00320 #endif 00321 } 00322 00323 KCmdLineArgsStatic::~KCmdLineArgsStatic () 00324 { 00325 delete argsList; 00326 // KAboutData object is deleted by ~KCleanUpGlobalStatic. 00327 //delete about; 00328 } 00329 00330 // 00331 // KCmdLineArgs private data and methods 00332 // 00333 00334 class KCmdLineArgsPrivate 00335 { 00336 friend class KCmdLineArgsStatic; 00337 public: 00338 KCmdLineArgsPrivate(const KCmdLineOptions &_options, const KLocalizedString &_name, const QByteArray &_id) 00339 : options(_options) 00340 , name(_name) 00341 , id(_id) 00342 , parsedOptionList(0) 00343 , parsedArgList(0) 00344 , isQt(id == "qt") 00345 { 00346 } 00347 ~KCmdLineArgsPrivate() 00348 { 00349 delete parsedOptionList; 00350 delete parsedArgList; 00351 } 00352 const KCmdLineOptions options; 00353 const KLocalizedString name; 00354 const QByteArray id; 00355 KCmdLineParsedOptions *parsedOptionList; 00356 KCmdLineParsedArgs *parsedArgList; 00357 bool isQt; 00358 00364 void setOption(const QByteArray &option, bool enabled); 00365 00371 void setOption(const QByteArray &option, const QByteArray &value); 00372 00378 void addArgument(const QByteArray &argument); 00379 00385 void save( QDataStream &) const; 00386 00392 void load( QDataStream &); 00393 }; 00394 00395 // 00396 // Static functions 00397 // 00398 00399 QString 00400 KCmdLineArgsStatic::decodeInput(const QByteArray &rawstr) 00401 { 00402 return s->codec->toUnicode(rawstr); 00403 } 00404 00405 QByteArray 00406 KCmdLineArgsStatic::encodeOutput(const QString &str) 00407 { 00408 return s->codec->fromUnicode(str); 00409 } 00410 00411 void 00412 KCmdLineArgsStatic::printQ(const QString &msg) 00413 { 00414 fprintf(stdout, "%s", encodeOutput(msg).data()); 00415 } 00416 00417 void 00418 KCmdLineArgs::init(int _argc, char **_argv, 00419 const QByteArray &_appname, 00420 const QByteArray &_catalog, 00421 const KLocalizedString &_programName, 00422 const QByteArray &_version, 00423 const KLocalizedString &_description, 00424 StdCmdLineArgs stdargs) 00425 { 00426 init(_argc, _argv, 00427 new KAboutData(_appname, _catalog, _programName, _version, _description), 00428 stdargs); 00429 } 00430 00431 void 00432 KCmdLineArgs::initIgnore(int _argc, char **_argv, const QByteArray &_appname ) 00433 { 00434 init(_argc, _argv, 00435 new KAboutData(_appname, 0, ki18n(_appname), "unknown", ki18n("KDE Application"))); 00436 s->ignoreUnknown = true; 00437 } 00438 00439 void 00440 KCmdLineArgs::init(const KAboutData* ab) 00441 { 00442 char **_argv = (char **) malloc(sizeof(char *)); 00443 _argv[0] = (char *) s->encodeOutput(ab->appName()).data(); 00444 init(1,_argv,ab, CmdLineArgNone); 00445 } 00446 00447 00448 void 00449 KCmdLineArgs::init(int _argc, char **_argv, const KAboutData *_about, StdCmdLineArgs stdargs) 00450 { 00451 s->all_argc = _argc; 00452 s->all_argv = _argv; 00453 00454 if (!s->all_argv) 00455 { 00456 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 00457 fprintf(stderr, "Passing null-pointer to 'argv' is not allowed.\n\n"); 00458 00459 assert( 0 ); 00460 exit(255); 00461 } 00462 00463 // Strip path from argv[0] 00464 if (s->all_argc) { 00465 char *p = strrchr(s->all_argv[0], QDir::separator().toAscii()); 00466 if (p) 00467 s->appName = p+1; 00468 else 00469 s->appName = s->all_argv[0]; 00470 } 00471 00472 s->about = _about; 00473 s->parsed = false; 00474 s->mCwd = QDir::currentPath().toLocal8Bit(); //currentPath() uses fromLocal8Bit internally apparently 00475 addStdCmdLineOptions(stdargs); 00476 } 00477 00478 QString KCmdLineArgs::cwd() 00479 { 00480 return QString::fromLocal8Bit(s->mCwd); 00481 } 00482 00483 QString KCmdLineArgs::appName() 00484 { 00485 if (!s->appName) return QString(); 00486 return s->decodeInput(s->appName); 00487 } 00488 00492 void KCmdLineArgs::addStdCmdLineOptions(StdCmdLineArgs stdargs) { 00493 if (stdargs & KCmdLineArgs::CmdLineArgQt) { 00494 KCmdLineArgs::addCmdLineOptions(s->qt_options, ki18n("Qt"), "qt"); 00495 } 00496 if (stdargs & KCmdLineArgs::CmdLineArgKDE) { 00497 KCmdLineArgs::addCmdLineOptions(s->kde_options, ki18n("KDE"), "kde"); 00498 } 00499 s->mStdargs = stdargs; 00500 } 00501 00502 void 00503 KCmdLineArgs::addCmdLineOptions( const KCmdLineOptions &options, const KLocalizedString &name, 00504 const QByteArray &id, const QByteArray &afterId) 00505 { 00506 if (!s->argsList) 00507 s->argsList = new KCmdLineArgsList; 00508 00509 int pos = s->argsList->count(); 00510 // To make sure that the named options come before unnamed. 00511 if (pos > 0 && !id.isEmpty() && s->argsList->last()->d->name.isEmpty()) 00512 pos--; 00513 00514 KCmdLineArgsList::Iterator args; 00515 int i = 0; 00516 for(args = s->argsList->begin(); args != s->argsList->end(); ++args, i++) 00517 { 00518 if (id == (*args)->d->id) { 00519 return; // Options already present. 00520 } 00521 00522 // Only check for afterId if it has been given non-empty, as the 00523 // unnamed option group should come after all named groups. 00524 if (!afterId.isEmpty() && afterId == (*args)->d->id) 00525 pos = i+1; 00526 } 00527 00528 Q_ASSERT( s->parsed == false ); // You must add _ALL_ cmd line options 00529 // before accessing the arguments! 00530 s->argsList->insert(pos, new KCmdLineArgs(options, name, id)); 00531 } 00532 00533 void 00534 KCmdLineArgs::saveAppArgs( QDataStream &ds) 00535 { 00536 if (!s->parsed) 00537 s->parseAllArgs(); 00538 00539 // Remove Qt and KDE options. 00540 s->removeArgs("qt"); 00541 s->removeArgs("kde"); 00542 s->removeArgs("kuniqueapp"); 00543 00544 ds << s->mCwd; 00545 00546 uint count = s->argsList ? s->argsList->count() : 0; 00547 ds << count; 00548 00549 if (!count) return; 00550 00551 KCmdLineArgsList::Iterator args; 00552 for(args = s->argsList->begin(); args != s->argsList->end(); ++args) 00553 { 00554 ds << (*args)->d->id; 00555 (*args)->d->save(ds); 00556 } 00557 } 00558 00559 void 00560 KCmdLineArgs::loadAppArgs( QDataStream &ds) 00561 { 00562 s->parsed = true; // don't reparse argc/argv! 00563 00564 // Remove Qt and KDE options. 00565 s->removeArgs("qt"); 00566 s->removeArgs("kde"); 00567 s->removeArgs("kuniqueapp"); 00568 00569 KCmdLineArgsList::Iterator args; 00570 if ( s->argsList ) { 00571 for(args = s->argsList->begin(); args != s->argsList->end(); ++args) 00572 { 00573 (*args)->clear(); 00574 } 00575 } 00576 00577 if (ds.atEnd()) 00578 return; 00579 00580 QByteArray qCwd; 00581 ds >> qCwd; 00582 00583 s->mCwd = qCwd; 00584 00585 uint count; 00586 ds >> count; 00587 00588 while(count--) 00589 { 00590 QByteArray id; 00591 ds >> id; 00592 Q_ASSERT( s->argsList ); 00593 bool found = false; 00594 for(args = s->argsList->begin(); args != s->argsList->end(); ++args) 00595 { 00596 if ((*args)->d->id == id) 00597 { 00598 (*args)->d->load(ds); 00599 found = true; 00600 break; 00601 } 00602 } 00603 if (!found) { 00604 kWarning() << "Argument definitions for" << id << "not found!"; 00605 // The next ds >> id will do nonsensical things... 00606 } 00607 } 00608 s->parsed = true; 00609 } 00610 00611 KCmdLineArgs *KCmdLineArgs::parsedArgs(const QByteArray &id) 00612 { 00613 if (!s->argsList) 00614 return 0; 00615 KCmdLineArgsList::Iterator args = s->argsList->begin(); 00616 while(args != s->argsList->end()) 00617 { 00618 if ((*args)->d->id == id) 00619 { 00620 if (!s->parsed) 00621 s->parseAllArgs(); 00622 return *args; 00623 } 00624 ++args; 00625 } 00626 00627 return 0; 00628 } 00629 00630 void KCmdLineArgsStatic::removeArgs(const QByteArray &id) 00631 { 00632 if (!s->argsList) 00633 return; 00634 KCmdLineArgsList::Iterator args = s->argsList->begin(); 00635 while(args != s->argsList->end()) 00636 { 00637 if ((*args)->d->id == id) 00638 { 00639 if (!s->parsed) 00640 s->parseAllArgs(); 00641 break; 00642 } 00643 ++args; 00644 } 00645 00646 if (args != s->argsList->end()) { 00647 KCmdLineArgs *a = *args; 00648 s->argsList->erase(args); 00649 delete a; 00650 } 00651 } 00652 00653 int 00654 KCmdLineArgsStatic::findOption(const KCmdLineOptions &options, QByteArray &opt, 00655 QByteArray &opt_name, QString &def, bool &enabled) 00656 { 00657 int result; 00658 bool inverse; 00659 00660 for (int i = 0; i < options.d->names.size(); i++) 00661 { 00662 result = 0; 00663 inverse = false; 00664 opt_name = options.d->names[i]; 00665 if (opt_name.startsWith(':') || opt_name.isEmpty()) 00666 { 00667 continue; 00668 } 00669 if (opt_name.startsWith('!')) 00670 { 00671 opt_name = opt_name.mid(1); 00672 result = 4; 00673 } 00674 if (opt_name.startsWith("no") && !opt_name.contains('<')) // krazy:exclude=strings 00675 { 00676 opt_name = opt_name.mid(2); 00677 inverse = true; 00678 } 00679 00680 int len = opt.length(); 00681 if (opt == opt_name.left(len)) 00682 { 00683 opt_name = opt_name.mid(len); 00684 if (opt_name.isEmpty()) 00685 { 00686 if (inverse) 00687 return result+2; 00688 00689 if (options.d->descriptions[i].isEmpty()) 00690 { 00691 i++; 00692 if (i >= options.d->names.size()) 00693 return result+0; 00694 QByteArray nextOption = options.d->names[i]; 00695 int p = nextOption.indexOf(' '); 00696 if (p > 0) 00697 nextOption = nextOption.left(p); 00698 if (nextOption.startsWith('!')) 00699 nextOption = nextOption.mid(1); 00700 if (nextOption.startsWith("no") && !nextOption.contains('<')) // krazy:exclude=strings 00701 { 00702 nextOption = nextOption.mid(2); 00703 enabled = !enabled; 00704 } 00705 result = findOption(options, nextOption, opt_name, def, enabled); 00706 Q_ASSERT(result); 00707 opt = nextOption; 00708 return result; 00709 } 00710 00711 return 1; 00712 } 00713 if (opt_name.startsWith(' ')) 00714 { 00715 opt_name = opt_name.mid(1); 00716 def = options.d->defaults[i]; 00717 return result+3; 00718 } 00719 } 00720 } 00721 return 0; 00722 } 00723 00724 void 00725 KCmdLineArgsStatic::findOption(const QByteArray &optv, const QByteArray &_opt, 00726 int &i, bool _enabled, bool &moreOptions) 00727 { 00728 KCmdLineArgsList::Iterator args = s->argsList->begin(); 00729 QByteArray opt = _opt; 00730 QByteArray opt_name; 00731 QString def; 00732 QByteArray argument; 00733 int j = opt.indexOf('='); 00734 if (j != -1) 00735 { 00736 argument = opt.mid(j+1); 00737 opt = opt.left(j); 00738 } 00739 00740 bool enabled = true; 00741 int result = 0; 00742 while (args != s->argsList->end()) 00743 { 00744 enabled = _enabled; 00745 result = findOption((*args)->d->options, opt, opt_name, def, enabled); 00746 if (result) break; 00747 ++args; 00748 } 00749 if ((args == s->argsList->end()) && 00750 (optv.startsWith('-') && !optv.startsWith("--"))) // krazy:exclude=strings 00751 { 00752 // Option not found check if it is a valid option 00753 // in the style of -Pprinter1 or ps -aux 00754 int p = 1; 00755 while (true) 00756 { 00757 QByteArray singleCharOption = " "; // krazy:exclude=doublequote_chars 00758 singleCharOption[0] = optv[p]; 00759 args = s->argsList->begin(); 00760 while (args != s->argsList->end()) 00761 { 00762 enabled = _enabled; 00763 result = findOption((*args)->d->options, singleCharOption, 00764 opt_name, def, enabled); 00765 if (result) break; 00766 ++args; 00767 } 00768 if (args == s->argsList->end()) 00769 break; // Unknown argument 00770 00771 p++; 00772 if (result == 1) // Single option 00773 { 00774 (*args)->d->setOption(singleCharOption, enabled); 00775 if (p < optv.length()) 00776 continue; // Next option 00777 else 00778 return; // Finished 00779 } 00780 else if (result == 3) // This option takes an argument 00781 { 00782 if (argument.isEmpty()) 00783 { 00784 argument = optv.mid(p); 00785 } 00786 (*args)->d->setOption(singleCharOption, argument); 00787 return; 00788 } 00789 break; // Unknown argument 00790 } 00791 args = s->argsList->end(); 00792 result = 0; 00793 } 00794 00795 if (args == s->argsList->end() || !result) 00796 { 00797 if (s->ignoreUnknown) 00798 return; 00799 KCmdLineArgs::enable_i18n(); 00800 KCmdLineArgs::usageError( i18n("Unknown option '%1'.", QString::fromLocal8Bit(_opt))); 00801 } 00802 00803 if ((result & 4) != 0) 00804 { 00805 result &= ~4; 00806 moreOptions = false; 00807 } 00808 00809 if (result == 3) // This option takes an argument 00810 { 00811 if (!enabled) 00812 { 00813 if (s->ignoreUnknown) 00814 return; 00815 KCmdLineArgs::enable_i18n(); 00816 KCmdLineArgs::usageError( i18n("Unknown option '%1'.", QString::fromLocal8Bit(_opt))); 00817 } 00818 if (argument.isEmpty()) 00819 { 00820 i++; 00821 if (i >= s->all_argc) 00822 { 00823 KCmdLineArgs::enable_i18n(); 00824 KCmdLineArgs::usageError( i18nc("@info:shell %1 is cmdoption name","'%1' missing.", QString::fromLocal8Bit(opt_name))); 00825 } 00826 argument = s->all_argv[i]; 00827 } 00828 (*args)->d->setOption(opt, argument); 00829 } 00830 else 00831 { 00832 (*args)->d->setOption(opt, enabled); 00833 } 00834 } 00835 00836 void 00837 KCmdLineArgsStatic::parseAllArgs() 00838 { 00839 bool allowArgs = false; 00840 bool inOptions = true; 00841 bool everythingAfterArgIsArgs = false; 00842 KCmdLineArgs *appOptions = s->argsList->last(); 00843 if (appOptions->d->id.isEmpty()) 00844 { 00845 foreach(const QByteArray& name, appOptions->d->options.d->names) 00846 { 00847 everythingAfterArgIsArgs = everythingAfterArgIsArgs || name.startsWith("!+"); 00848 allowArgs = allowArgs || name.startsWith('+') || everythingAfterArgIsArgs; 00849 } 00850 } 00851 for(int i = 1; i < s->all_argc; i++) 00852 { 00853 if (!s->all_argv[i]) 00854 continue; 00855 00856 if ((s->all_argv[i][0] == '-') && s->all_argv[i][1] && inOptions) 00857 { 00858 bool enabled = true; 00859 QByteArray orig = s->all_argv[i]; 00860 QByteArray option = orig.mid(1); 00861 if (option.startsWith('-')) 00862 { 00863 option = option.mid(1); 00864 if (option.isEmpty()) 00865 { 00866 inOptions = false; 00867 continue; 00868 } 00869 } 00870 if (option == "help") 00871 { 00872 KCmdLineArgs::usage(); 00873 } 00874 else if (option.startsWith("help-")) // krazy:exclude=strings 00875 { 00876 KCmdLineArgs::usage(option.mid(5)); 00877 } 00878 #ifdef Q_WS_MAC 00879 // skip the finder -psn_* hint 00880 else if (option.startsWith("psn_")) // krazy:exclude=strings 00881 { 00882 continue; 00883 } 00884 #endif 00885 else if ((option == "version") || (option == "v")) 00886 { 00887 KCmdLineArgs::enable_i18n(); 00888 s->printQ(i18nc("@info:shell message on appcmd --version; do not translate 'Development Platform'" 00889 "%3 application name, other %n version strings", 00890 "Qt: %1\n" 00891 "KDE Development Platform: %2\n" 00892 "%3: %4\n", 00893 QString::fromLatin1(qVersion()), 00894 QString::fromLatin1(KDE_VERSION_STRING), 00895 s->about->programName(), s->about->version())); 00896 exit(0); 00897 } else if (option == "license") 00898 { 00899 KCmdLineArgs::enable_i18n(); 00900 s->printQ(s->about->license()); 00901 s->printQ(QString::fromLatin1("\n")); 00902 exit(0); 00903 } else if (option == "author") { 00904 KCmdLineArgs::enable_i18n(); 00905 if ( s->about ) { 00906 const QList<KAboutPerson> authors = s->about->authors(); 00907 if ( !authors.isEmpty() ) { 00908 QString authorlist; 00909 for (QList<KAboutPerson>::ConstIterator it = authors.begin(); it != authors.end(); ++it ) { 00910 QString email; 00911 if ( !(*it).emailAddress().isEmpty() ) 00912 email = QString::fromLatin1(" <") + (*it).emailAddress() + QLatin1String(">"); 00913 authorlist += QString::fromLatin1(" ") + (*it).name() + email + QLatin1Char('\n'); 00914 } 00915 s->printQ( i18nc("the 2nd argument is a list of name+address, one on each line","%1 was written by\n%2", QString(s->about->programName()) , authorlist ) ); 00916 } 00917 } else { 00918 s->printQ( i18n("This application was written by somebody who wants to remain anonymous.") ); 00919 } 00920 if (s->about) 00921 { 00922 if (!s->about->customAuthorTextEnabled ()) 00923 { 00924 if (s->about->bugAddress().isEmpty() || s->about->bugAddress() == QLatin1String("submit@bugs.kde.org") ) 00925 s->printQ( i18n( "Please use http://bugs.kde.org to report bugs.\n" ) ); 00926 else 00927 s->printQ( i18n( "Please report bugs to %1.\n" , s->about->bugAddress()) ); 00928 } 00929 else 00930 { 00931 s->printQ(s->about->customAuthorPlainText()+QLatin1Char('\n')); 00932 } 00933 } 00934 exit(0); 00935 } else { 00936 if (option.startsWith("no")) // krazy:exclude=strings 00937 { 00938 bool noHasParameter=false; 00939 foreach(const QByteArray& name, appOptions->d->options.d->names) 00940 { 00941 if (name.contains(option + QByteArray(" ")) && name.contains('<')) 00942 { 00943 noHasParameter=true; 00944 break; 00945 } 00946 } 00947 if (!noHasParameter) 00948 { 00949 option = option.mid(2); 00950 enabled = false; 00951 } 00952 } 00953 s->findOption(orig, option, i, enabled, inOptions); 00954 } 00955 } 00956 else 00957 { 00958 // Check whether appOptions allows these arguments 00959 if (!allowArgs) 00960 { 00961 if (s->ignoreUnknown) 00962 continue; 00963 KCmdLineArgs::enable_i18n(); 00964 KCmdLineArgs::usageError(i18n("Unexpected argument '%1'.", KuitSemantics::escape(s->decodeInput(s->all_argv[i])))); 00965 } 00966 else 00967 { 00968 appOptions->d->addArgument(s->all_argv[i]); 00969 if (everythingAfterArgIsArgs) 00970 inOptions = false; 00971 } 00972 } 00973 } 00974 s->parsed = true; 00975 } 00976 00977 int & KCmdLineArgs::qtArgc() 00978 { 00979 if (!s->argsList) 00980 addStdCmdLineOptions(CmdLineArgKDE|CmdLineArgQt); // Lazy bastards! 00981 00982 static int qt_argc = -1; 00983 if( qt_argc != -1 ) 00984 return qt_argc; 00985 00986 if (!(s->mStdargs & KCmdLineArgs::CmdLineArgQt)) 00987 { 00988 qt_argc = 2; 00989 return qt_argc; 00990 } 00991 00992 KCmdLineArgs *args = parsedArgs("qt"); 00993 Q_ASSERT(args); // No qt options have been added! 00994 if (!s->all_argv) 00995 { 00996 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 00997 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n"); 00998 00999 assert( 0 ); 01000 exit(255); 01001 } 01002 01003 Q_ASSERT(s->all_argc >= (args->count()+1)); 01004 qt_argc = args->count() +1; 01005 return qt_argc; 01006 } 01007 01008 static char** s_qt_argv; 01009 01010 char ** 01011 KCmdLineArgs::qtArgv() 01012 { 01013 if (!s->argsList) 01014 addStdCmdLineOptions(CmdLineArgKDE|CmdLineArgQt); // Lazy bastards! 01015 01016 if( s_qt_argv != NULL ) 01017 return s_qt_argv; 01018 01019 if (!(s->mStdargs & KCmdLineArgs::CmdLineArgQt)) 01020 { 01021 s_qt_argv = new char*[2]; 01022 s_qt_argv[0] = qstrdup(s->all_argc?s->all_argv[0]:""); 01023 s_qt_argv[1] = 0; 01024 01025 return s_qt_argv; 01026 } 01027 01028 KCmdLineArgs *args = parsedArgs("qt"); 01029 if (!args) 01030 { 01031 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 01032 fprintf(stderr, "The \"qt\" options have not be added to KCmdLineArgs!\n\n"); 01033 01034 assert( 0 ); 01035 exit(255); 01036 } 01037 if (!s->all_argv) 01038 { 01039 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 01040 fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n"); 01041 01042 assert( 0 ); 01043 exit(255); 01044 } 01045 01046 int count=args->count(); 01047 s_qt_argv = new char*[ count + 2 ]; 01048 s_qt_argv[0] = qstrdup(s->all_argc?s->all_argv[0]:""); 01049 int i = 0; 01050 for(; i < count; i++) 01051 { 01052 s_qt_argv[i+1] = qstrdup(args->d->parsedArgList->at(i)); 01053 } 01054 s_qt_argv[i+1] = 0; 01055 01056 return s_qt_argv; 01057 } 01058 01059 const KAboutData * 01060 KCmdLineArgs::aboutData() 01061 { 01062 return s->about; 01063 } 01064 01065 void 01066 KCmdLineArgs::enable_i18n() 01067 { 01068 // called twice or too late 01069 if (KGlobal::hasLocale()) 01070 return; 01071 01072 if (!KGlobal::hasMainComponent()) { 01073 KComponentData mainComponentData(s->about); 01074 mainComponentData.config(); 01075 // mainComponentData is now the main component and won't disappear until KGlobal deletes it 01076 } 01077 } 01078 01079 void 01080 KCmdLineArgs::usageError(const QString &error) 01081 { 01082 Q_ASSERT(KGlobal::hasLocale()); 01083 QByteArray localError = s->encodeOutput(error); 01084 if (localError.endsWith('\n')) 01085 localError.chop(1); 01086 fprintf(stderr, "%s: %s\n", s->appName, localError.data()); 01087 01088 QString tmp = i18n("Use --help to get a list of available command line options."); 01089 localError = s->encodeOutput(tmp); 01090 fprintf(stderr, "%s: %s\n", s->appName, localError.data()); 01091 exit(254); 01092 } 01093 01094 void 01095 KCmdLineArgs::usage(const QByteArray &id) 01096 { 01097 enable_i18n(); 01098 Q_ASSERT(s->argsList != 0); // It's an error to call usage(...) without 01099 // having done addCmdLineOptions first! 01100 01101 QString optionFormatString = QString::fromLatin1(" %1 %2\n"); 01102 QString optionFormatStringDef = QString::fromLatin1(" %1 %2 [%3]\n"); 01103 QString tmp; 01104 QString usage; 01105 01106 KCmdLineArgsList::Iterator args = --(s->argsList->end()); 01107 01108 if ((*args)->d->id.isEmpty() && ((*args)->d->options.d->names.size() > 0) && 01109 !(*args)->d->options.d->names[0].startsWith('+')) 01110 { 01111 usage = i18n("[options] ")+usage; 01112 } 01113 01114 while(true) 01115 { 01116 if (!(*args)->d->name.isEmpty()) 01117 { 01118 usage = i18n("[%1-options]", (*args)->d->name.toString())+QLatin1Char(' ')+usage; 01119 } 01120 if (args == s->argsList->begin()) 01121 break; 01122 --args; 01123 } 01124 01125 KCmdLineArgs *appOptions = s->argsList->last(); 01126 if (appOptions->d->id.isEmpty()) 01127 { 01128 const KCmdLineOptions &option = appOptions->d->options; 01129 for (int i = 0; i < option.d->names.size(); i++) 01130 { 01131 QByteArray opt_name = option.d->names[i]; 01132 if (opt_name.startsWith('+')) 01133 usage += QString::fromLatin1(opt_name.mid(1)) + QLatin1Char(' '); 01134 else if ( opt_name.startsWith("!+") ) 01135 usage += QString::fromLatin1(opt_name.mid(2)) + QLatin1Char(' '); 01136 } 01137 } 01138 01139 s->printQ(i18n("Usage: %1 %2\n", QString::fromLocal8Bit(s->appName), KuitSemantics::escape(usage))); 01140 s->printQ(QLatin1Char('\n')+s->about->shortDescription()+QLatin1Char('\n')); 01141 01142 s->printQ(i18n("\nGeneric options:\n")); 01143 s->printQ(optionFormatString.arg(QString::fromLatin1("--help"), -25) 01144 .arg(i18n("Show help about options"))); 01145 01146 args = s->argsList->begin(); 01147 while(args != s->argsList->end()) 01148 { 01149 if (!(*args)->d->name.isEmpty() && !(*args)->d->id.isEmpty()) 01150 { 01151 QString option = QString::fromLatin1("--help-%1").arg(QString::fromLatin1((*args)->d->id)); 01152 QString desc = i18n("Show %1 specific options", (*args)->d->name.toString()); 01153 01154 s->printQ(optionFormatString.arg(option, -25).arg(desc)); 01155 } 01156 ++args; 01157 } 01158 01159 s->printQ(optionFormatString.arg(QString::fromLatin1("--help-all"),-25).arg(i18n("Show all options"))); 01160 s->printQ(optionFormatString.arg(QString::fromLatin1("--author"),-25).arg(i18n("Show author information"))); 01161 s->printQ(optionFormatString.arg(QString::fromLatin1("-v, --version"),-25).arg(i18n("Show version information"))); 01162 s->printQ(optionFormatString.arg(QString::fromLatin1("--license"),-25).arg(i18n("Show license information"))); 01163 s->printQ(optionFormatString.arg(QString::fromLatin1("--"), -25).arg(i18n("End of options"))); 01164 01165 args = s->argsList->begin(); // Sets current to 1st. 01166 01167 bool showAll = (id == "all"); 01168 01169 if (!showAll) 01170 { 01171 while(args != s->argsList->end()) 01172 { 01173 if (id == (*args)->d->id) break; 01174 ++args; 01175 } 01176 } 01177 01178 while(args != s->argsList->end()) 01179 { 01180 bool hasArgs = false; 01181 bool hasOptions = false; 01182 QString optionsHeader; 01183 if (!(*args)->d->name.isEmpty()) 01184 optionsHeader = i18n("\n%1 options:\n", (*args)->d->name.toString()); 01185 else 01186 optionsHeader = i18n("\nOptions:\n"); 01187 01188 while (args != s->argsList->end()) 01189 { 01190 const KCmdLineOptions &option = (*args)->d->options; 01191 QByteArray opt; 01192 01193 for (int i = 0; i < option.d->names.size(); i++) 01194 { 01195 QString description; 01196 QStringList dl; 01197 01198 QString descriptionFull; 01199 if (!option.d->descriptions[i].isEmpty()) { 01200 descriptionFull = option.d->descriptions[i].toString(); 01201 } 01202 01203 // Option header 01204 if (option.d->names[i].startsWith(':')) 01205 { 01206 if (!descriptionFull.isEmpty()) 01207 { 01208 optionsHeader = QLatin1Char('\n')+descriptionFull; 01209 if (!optionsHeader.endsWith(QLatin1Char('\n'))) 01210 optionsHeader.append(QLatin1Char('\n')); 01211 hasOptions = false; 01212 } 01213 continue; 01214 } 01215 01216 // Free-form comment 01217 if (option.d->names[i].isEmpty()) 01218 { 01219 if (!descriptionFull.isEmpty()) 01220 { 01221 tmp = QLatin1Char('\n')+descriptionFull; 01222 if (!tmp.endsWith(QLatin1Char('\n'))) 01223 tmp.append(QLatin1Char('\n')); 01224 s->printQ(tmp); 01225 } 01226 continue; 01227 } 01228 01229 // Options 01230 if (!descriptionFull.isEmpty()) 01231 { 01232 dl = descriptionFull.split(QLatin1Char('\n'), QString::KeepEmptyParts); 01233 description = dl.first(); 01234 dl.erase( dl.begin() ); 01235 } 01236 QByteArray name = option.d->names[i]; 01237 if (name.startsWith('!')) 01238 name = name.mid(1); 01239 01240 if (name.startsWith('+')) 01241 { 01242 if (!hasArgs) 01243 { 01244 s->printQ(i18n("\nArguments:\n")); 01245 hasArgs = true; 01246 } 01247 01248 name = name.mid(1); 01249 if (name.startsWith('[') && name.endsWith(']')) 01250 name = name.mid(1, name.length()-2); 01251 s->printQ(optionFormatString.arg(QString::fromLocal8Bit(name), -25).arg(description)); 01252 } 01253 else 01254 { 01255 if (!hasOptions) 01256 { 01257 s->printQ(optionsHeader); 01258 hasOptions = true; 01259 } 01260 01261 if ((name.length() == 1) || (name[1] == ' ')) 01262 name = '-'+name; 01263 else 01264 name = "--"+name; 01265 if (descriptionFull.isEmpty()) 01266 { 01267 opt = name + ", "; 01268 } 01269 else 01270 { 01271 opt = opt + name; 01272 if (option.d->defaults[i].isEmpty()) 01273 { 01274 s->printQ(optionFormatString.arg(QString::fromLatin1(opt), -25).arg(description)); 01275 } 01276 else 01277 { 01278 s->printQ(optionFormatStringDef.arg(QString::fromLatin1(opt), -25) 01279 .arg(description, option.d->defaults[i])); 01280 } 01281 opt.clear(); 01282 } 01283 } 01284 for(QStringList::Iterator it = dl.begin(); 01285 it != dl.end(); 01286 ++it) 01287 { 01288 s->printQ(optionFormatString.arg(QString(), -25).arg(*it)); 01289 } 01290 } 01291 01292 ++args; 01293 if (args == s->argsList->end() || !(*args)->d->name.isEmpty() || (*args)->d->id.isEmpty()) 01294 break; 01295 } 01296 if (!showAll) break; 01297 } 01298 01299 exit(0); 01300 } 01301 01302 // 01303 // Member functions 01304 // 01305 01311 KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions &_options, 01312 const KLocalizedString &_name, 01313 const QByteArray &_id) 01314 : d(new KCmdLineArgsPrivate(_options, _name, _id)) 01315 { 01316 } 01317 01321 KCmdLineArgs::~KCmdLineArgs() 01322 { 01323 if (!s.isDestroyed() && s->argsList) 01324 s->argsList->removeAll(this); 01325 delete d; 01326 } 01327 01328 void 01329 KCmdLineArgs::setCwd( const QByteArray &cwd ) 01330 { 01331 s->mCwd = cwd; 01332 } 01333 01334 void 01335 KCmdLineArgs::clear() 01336 { 01337 delete d->parsedArgList; d->parsedArgList = 0; 01338 delete d->parsedOptionList; d->parsedOptionList = 0; 01339 } 01340 01341 void 01342 KCmdLineArgs::reset() 01343 { 01344 delete s->argsList; s->argsList = 0; 01345 s->parsed = false; 01346 } 01347 01348 void 01349 KCmdLineArgsPrivate::save( QDataStream &ds) const 01350 { 01351 if (parsedOptionList) 01352 ds << (*(parsedOptionList)); 01353 else 01354 ds << quint32(0); 01355 01356 if (parsedArgList) 01357 ds << (*(parsedArgList)); 01358 else 01359 ds << quint32(0); 01360 } 01361 01362 void 01363 KCmdLineArgsPrivate::load( QDataStream &ds) 01364 { 01365 if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions; 01366 if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs; 01367 01368 ds >> (*(parsedOptionList)); 01369 ds >> (*(parsedArgList)); 01370 01371 if (parsedOptionList->count() == 0) 01372 { 01373 delete parsedOptionList; parsedOptionList = 0; 01374 } 01375 if (parsedArgList->count() == 0) 01376 { 01377 delete parsedArgList; parsedArgList = 0; 01378 } 01379 } 01380 01381 void 01382 KCmdLineArgsPrivate::setOption(const QByteArray &opt, bool enabled) 01383 { 01384 if (isQt) 01385 { 01386 // Qt does it own parsing. 01387 QByteArray argString = "-"; // krazy:exclude=doublequote_chars 01388 if( !enabled ) 01389 argString += "no"; 01390 argString += opt; 01391 addArgument(argString); 01392 } 01393 if (!parsedOptionList) { 01394 parsedOptionList = new KCmdLineParsedOptions; 01395 } 01396 01397 if (enabled) 01398 parsedOptionList->insert( opt, "t" ); // krazy:exclude=doublequote_chars 01399 else 01400 parsedOptionList->insert( opt, "f" ); // krazy:exclude=doublequote_chars 01401 } 01402 01403 void 01404 KCmdLineArgsPrivate::setOption(const QByteArray &opt, const QByteArray &value) 01405 { 01406 if (isQt) 01407 { 01408 // Qt does it's own parsing. 01409 QByteArray argString = "-"; // krazy:exclude=doublequote_chars 01410 argString += opt; 01411 if (opt == "qmljsdebugger") { 01412 // hack: Qt expects the value of the "qmljsdebugger" option to be 01413 // passed using a '=' separator rather than a space, so we recreate it 01414 // correctly. 01415 // See code of QCoreApplicationPrivate::processCommandLineArguments() 01416 addArgument(argString + "=" + value); 01417 } else { 01418 addArgument(argString); 01419 addArgument(value); 01420 } 01421 01422 #if defined(Q_WS_X11) || defined(Q_WS_QWS) 01423 // Hack coming up! 01424 if (argString == "-display") 01425 { 01426 setenv(DISPLAY, value.data(), true); 01427 } 01428 #endif 01429 } 01430 if (!parsedOptionList) { 01431 parsedOptionList = new KCmdLineParsedOptions; 01432 } 01433 01434 parsedOptionList->insertMulti( opt, value ); 01435 } 01436 01437 QString 01438 KCmdLineArgs::getOption(const QByteArray &_opt) const 01439 { 01440 QByteArray opt = _opt; 01441 QByteArray value; 01442 if (d->parsedOptionList) 01443 { 01444 value = d->parsedOptionList->value(opt); 01445 } 01446 if (!value.isEmpty()) 01447 return QString::fromLocal8Bit(value); 01448 01449 // Look up the default. 01450 QByteArray opt_name; 01451 QString def; 01452 bool dummy = true; 01453 int result = s->findOption( d->options, opt, opt_name, def, dummy) & ~4; 01454 01455 if (result != 3) 01456 { 01457 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 01458 fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n", 01459 opt.data(), opt.data()); 01460 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n"); 01461 01462 Q_ASSERT( 0 ); 01463 exit(255); 01464 } 01465 return def; 01466 } 01467 01468 QStringList 01469 KCmdLineArgs::getOptionList(const QByteArray &opt) const 01470 { 01471 QStringList result; 01472 if (!d->parsedOptionList) 01473 return result; 01474 01475 while(true) 01476 { 01477 QByteArray value = d->parsedOptionList->take(opt); 01478 if (value.isEmpty()) 01479 break; 01480 result.prepend(QString::fromLocal8Bit(value)); 01481 } 01482 01483 // Reinsert items in dictionary 01484 // WABA: This is rather silly, but I don't want to add restrictions 01485 // to the API like "you can only call this function once". 01486 // I can't access all items without taking them out of the list. 01487 // So taking them out and then putting them back is the only way. 01488 Q_FOREACH(const QString &str, result) 01489 { 01490 d->parsedOptionList->insertMulti(opt, str.toLocal8Bit()); 01491 } 01492 return result; 01493 } 01494 01495 bool 01496 KCmdLineArgs::isSet(const QByteArray &_opt) const 01497 { 01498 // Look up the default. 01499 QByteArray opt = _opt; 01500 QByteArray opt_name; 01501 QString def; 01502 int result = 0; 01503 KCmdLineArgsList::Iterator args = s->argsList->begin(); 01504 while (args != s->argsList->end()) 01505 { 01506 bool dummy = true; 01507 result = s->findOption((*args)->d->options, opt, opt_name, def, dummy) & ~4; 01508 if (result) break; 01509 ++args; 01510 } 01511 01512 if (result == 0) 01513 { 01514 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n"); 01515 fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n", 01516 opt.data(), opt.data()); 01517 fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n"); 01518 01519 Q_ASSERT( 0 ); 01520 exit(255); 01521 } 01522 01523 QByteArray value; 01524 if (d->parsedOptionList) 01525 { 01526 value = d->parsedOptionList->value(opt); 01527 } 01528 01529 if (!value.isEmpty()) 01530 { 01531 if (result == 3) 01532 return true; 01533 else 01534 return (value.at(0) == 't'); 01535 } 01536 01537 if (result == 3) 01538 return false; // String option has 'false' as default. 01539 01540 // We return 'true' as default if the option was listed as '-nofork' 01541 // We return 'false' as default if the option was listed as '-fork' 01542 return (result == 2); 01543 } 01544 01545 int 01546 KCmdLineArgs::count() const 01547 { 01548 return d->parsedArgList?d->parsedArgList->count():0; 01549 } 01550 01551 QString 01552 KCmdLineArgs::arg(int n) const 01553 { 01554 if (!d->parsedArgList || (n >= (int) d->parsedArgList->count())) 01555 { 01556 fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n"); 01557 fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n", 01558 n); 01559 01560 Q_ASSERT( 0 ); 01561 exit(255); 01562 } 01563 01564 return QString::fromLocal8Bit(d->parsedArgList->at(n)); 01565 } 01566 01567 KUrl 01568 KCmdLineArgs::url(int n) const 01569 { 01570 return makeURL( arg(n).toUtf8() ); 01571 } 01572 01573 KUrl KCmdLineArgs::makeURL(const QByteArray &_urlArg) 01574 { 01575 const QString urlArg = QString::fromUtf8(_urlArg); 01576 QFileInfo fileInfo(urlArg); 01577 if (!fileInfo.isRelative()) { // i.e. starts with '/', on unix 01578 KUrl result; 01579 result.setPath(QDir::fromNativeSeparators(urlArg)); 01580 return result; // Absolute path. 01581 } 01582 01583 if ( KUrl::isRelativeUrl(urlArg) || fileInfo.exists() ) { 01584 KUrl result; 01585 result.setPath(cwd()+QLatin1Char('/')+urlArg); 01586 result.cleanPath(); 01587 return result; // Relative path 01588 } 01589 01590 return KUrl(urlArg); // Argument is a URL 01591 } 01592 01593 void 01594 KCmdLineArgsPrivate::addArgument(const QByteArray &argument) 01595 { 01596 if (!parsedArgList) 01597 parsedArgList = new KCmdLineParsedArgs; 01598 01599 parsedArgList->append(argument); 01600 } 01601 01602 void 01603 KCmdLineArgs::addTempFileOption() 01604 { 01605 KCmdLineOptions tmpopt; 01606 tmpopt.add( "tempfile", ki18n("The files/URLs opened by the application will be deleted after use") ); 01607 KCmdLineArgs::addCmdLineOptions( tmpopt, ki18n("KDE-tempfile"), "kde-tempfile" ); 01608 } 01609 01610 bool KCmdLineArgs::isTempFileSet() 01611 { 01612 KCmdLineArgs* args = KCmdLineArgs::parsedArgs( "kde-tempfile" ); 01613 return args && args->isSet( "tempfile" ); 01614 } 01615 01616 QStringList KCmdLineArgs::allArguments() 01617 { 01618 QStringList lst; 01619 01620 for(int i = 0; i < s->all_argc; i++) { 01621 char* arg = s->all_argv[i]; 01622 if (!arg) 01623 continue; 01624 lst.append(QString::fromLocal8Bit(arg)); 01625 } 01626 return lst; 01627 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:28:09 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:28:09 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.