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