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