Changeset 561 for trunk/tools/qdoc3/doc.cpp
- Timestamp:
- Feb 11, 2010, 11:19:06 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/vendor/nokia/qt/4.6.1 merged eligible /branches/vendor/nokia/qt/current merged eligible /branches/vendor/trolltech/qt/current 3-149
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/tools/qdoc3/doc.cpp
r2 r561 2 2 ** 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 ** Contact: Qt Software Information (qt-info@nokia.com) 4 ** All rights reserved. 5 ** Contact: Nokia Corporation (qt-info@nokia.com) 5 6 ** 6 7 ** This file is part of the tools applications of the Qt Toolkit. … … 21 22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 22 23 ** 23 ** In addition, as a special exception, Nokia gives you certain 24 ** additional rights. These rights are described in the Nokia Qt LGPL 25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this 26 ** package. 24 ** In addition, as a special exception, Nokia gives you certain additional 25 ** rights. These rights are described in the Nokia Qt LGPL Exception 26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 27 ** 28 28 ** GNU General Public License Usage … … 34 34 ** met: http://www.gnu.org/copyleft/gpl.html. 35 35 ** 36 ** If you are unsure which license is appropriate for your use, please37 ** contact the sales department at qt-sales@nokia.com.36 ** If you have questions regarding the use of this file, please contact 37 ** Nokia at qt-info@nokia.com. 38 38 ** $QT_END_LICENSE$ 39 39 ** … … 74 74 75 75 enum { 76 CMD_A, CMD_ABSTRACT, CMD_ BADCODE, CMD_BASENAME, CMD_BOLD,77 CMD_B RIEF, CMD_C, CMD_CAPTION, CMD_CHAPTER, CMD_CODE,78 CMD_C ODELINE, CMD_DOTS, CMD_ELSE, CMD_ENDABSTRACT,79 CMD_END CHAPTER, CMD_ENDCODE, CMD_ENDFOOTNOTE, CMD_ENDIF,80 CMD_END LEGALESE, CMD_ENDLINK, CMD_ENDLIST, CMD_ENDOMIT,81 CMD_END PART, CMD_ENDQUOTATION, CMD_ENDRAW, CMD_ENDSECTION1,82 CMD_END SECTION2, CMD_ENDSECTION3, CMD_ENDSECTION4,83 CMD_ENDS IDEBAR, CMD_ENDTABLE, CMD_EXPIRE, CMD_FOOTNOTE,84 CMD_ GENERATELIST, CMD_GRANULARITY, CMD_HEADER, CMD_I,85 CMD_ IF, CMD_IMAGE, CMD_INCLUDE, CMD_INLINEIMAGE, CMD_INDEX,86 CMD_ KEYWORD, CMD_L, CMD_LEGALESE, CMD_LINK, CMD_LIST,87 CMD_ META, CMD_NEWCODE, CMD_O, CMD_OLDCODE, CMD_OMIT,88 CMD_ OMITVALUE, CMD_OVERLOAD,89 CMD_ PART, CMD_PRINTLINE, CMD_PRINTTO,76 CMD_A, CMD_ABSTRACT, CMD_ANNOTATEDLIST, CMD_BADCODE, 77 CMD_BASENAME, CMD_BOLD, CMD_BRIEF, CMD_C, CMD_CAPTION, 78 CMD_CHAPTER, CMD_CODE, CMD_CODELINE, CMD_DOTS, CMD_ELSE, 79 CMD_ENDABSTRACT, CMD_ENDCHAPTER, CMD_ENDCODE, 80 CMD_ENDFOOTNOTE, CMD_ENDIF, CMD_ENDLEGALESE, CMD_ENDLINK, 81 CMD_ENDLIST, CMD_ENDOMIT, CMD_ENDPART, CMD_ENDQUOTATION, 82 CMD_ENDRAW, CMD_ENDSECTION1, CMD_ENDSECTION2, 83 CMD_ENDSECTION3, CMD_ENDSECTION4, CMD_ENDSIDEBAR, 84 CMD_ENDTABLE, CMD_EXPIRE, CMD_FOOTNOTE, CMD_GENERATELIST, 85 CMD_GRANULARITY, CMD_HEADER, CMD_I, CMD_IF, CMD_IMAGE, 86 CMD_INCLUDE, CMD_INLINEIMAGE, CMD_INDEX, CMD_KEYWORD, 87 CMD_L, CMD_LEGALESE, CMD_LINK, CMD_LIST, CMD_META, 88 CMD_NEWCODE, CMD_O, CMD_OLDCODE, CMD_OMIT, CMD_OMITVALUE, 89 CMD_OVERLOAD, CMD_PART, CMD_PRINTLINE, CMD_PRINTTO, 90 90 CMD_PRINTUNTIL, CMD_QUOTATION, CMD_QUOTEFILE, 91 91 CMD_QUOTEFROMFILE, CMD_QUOTEFUNCTION, CMD_RAW, CMD_ROW, 92 92 CMD_SA, CMD_SECTION1, CMD_SECTION2, CMD_SECTION3, 93 CMD_SECTION4, CMD_SIDEBAR, CMD_S KIPLINE, CMD_SKIPTO,94 CMD_SKIP UNTIL, CMD_SNIPPET, CMD_SUB, CMD_SUP, CMD_TABLE,95 CMD_TABLE OFCONTENTS, CMD_TARGET, CMD_TT, CMD_UNDERLINE,96 CMD_UN ICODE, CMD_VALUE, CMD_WARNING,93 CMD_SECTION4, CMD_SIDEBAR, CMD_SINCELIST, CMD_SKIPLINE, 94 CMD_SKIPTO, CMD_SKIPUNTIL, CMD_SNIPPET, CMD_SUB, CMD_SUP, 95 CMD_TABLE, CMD_TABLEOFCONTENTS, CMD_TARGET, CMD_TT, 96 CMD_UNDERLINE, CMD_UNICODE, CMD_VALUE, CMD_WARNING, 97 97 #ifdef QDOC_QML 98 98 CMD_QML, CMD_ENDQML, CMD_CPP, CMD_ENDCPP, CMD_QMLTEXT, … … 109 109 { "a", CMD_A, 0 }, 110 110 { "abstract", CMD_ABSTRACT, 0 }, 111 { "annotatedlist", CMD_ANNOTATEDLIST, 0 }, 111 112 { "badcode", CMD_BADCODE, 0 }, 112 113 { "basename", CMD_BASENAME, 0 }, // ### don't document for now … … 177 178 { "section4", CMD_SECTION4, 0 }, 178 179 { "sidebar", CMD_SIDEBAR, 0 }, // ### don't document for now 180 { "sincelist", CMD_SINCELIST, 0 }, 179 181 { "skipline", CMD_SKIPLINE, 0 }, 180 182 { "skipto", CMD_SKIPTO, 0 }, … … 516 518 case CMD_BADCODE: 517 519 leavePara(); 518 #ifdef QDOC2DOX519 if (DoxWriter::isDoxPass())520 append(Atom::CodeBad,getUnmarkedCode(CMD_BADCODE));521 else522 append(Atom::CodeBad,getCode(CMD_BADCODE, marker));523 #else524 520 append(Atom::CodeBad,getCode(CMD_BADCODE, marker)); 525 #endif526 521 break; 527 522 case CMD_BASENAME: … … 539 534 enterPara(); 540 535 x = untabifyEtc(getArgument(true)); 541 #ifdef QDOC2DOX542 if (DoxWriter::isDoxPass())543 append(Atom::C, x);544 else {545 marker = CodeMarker::markerForCode(x);546 append(Atom::C, marker->markedUpCode(x, 0, ""));547 }548 #else549 536 marker = CodeMarker::markerForCode(x); 550 537 append(Atom::C, marker->markedUpCode(x, 0, "")); 551 #endif552 538 break; 553 539 case CMD_CAPTION: … … 560 546 case CMD_CODE: 561 547 leavePara(); 562 #ifdef QDOC2DOX563 if (DoxWriter::isDoxPass())564 append(Atom::Code, getUnmarkedCode(CMD_CODE));565 else566 append(Atom::Code, getCode(CMD_CODE, marker));567 #else568 548 append(Atom::Code, getCode(CMD_CODE, marker)); 569 #endif570 549 break; 571 550 #ifdef QDOC_QML … … 580 559 case CMD_CODELINE: 581 560 { 582 #ifdef QDOC2DOX583 if (!quoting && !DoxWriter::isDoxPass()) {584 if (priv->text.lastAtom()->type() == Atom::Code585 && priv->text.lastAtom()->string().endsWith("\n\n"))586 priv->text.lastAtom()->chopString();587 appendToCode("\n");588 } lse {589 append(Atom::CodeQuoteCommand, cmdStr);590 append(Atom::CodeQuoteArgument, " ");591 }592 #else593 561 if (!quoting) { 594 562 if (priv->text.lastAtom()->type() == Atom::Code … … 601 569 append(Atom::CodeQuoteArgument, " "); 602 570 } 603 #endif604 571 } 605 572 break; 606 573 case CMD_DOTS: 607 574 { 608 #ifdef QDOC2DOX 609 if (DoxWriter::isDoxPass()) { 610 append(Atom::CodeQuoteCommand, cmdStr); 611 append(Atom::CodeQuoteArgument, " ..."); 612 } 613 else if (!quoting) { 575 if (!quoting) { 614 576 if (priv->text.lastAtom()->type() == Atom::Code 615 577 && priv->text.lastAtom()->string().endsWith("\n\n")) … … 631 593 append(Atom::CodeQuoteArgument, arg); 632 594 } 633 #else634 if (!quoting) {635 if (priv->text.lastAtom()->type() == Atom::Code636 && priv->text.lastAtom()->string().endsWith("\n\n"))637 priv->text.lastAtom()->chopString();638 639 QString arg = getOptionalArgument();640 int indent = 4;641 if (!arg.isEmpty())642 indent = arg.toInt();643 for (int i = 0; i < indent; ++i)644 appendToCode(" ");645 appendToCode("...\n");646 }647 else {648 append(Atom::CodeQuoteCommand, cmdStr);649 QString arg = getOptionalArgument();650 if (arg.isEmpty())651 arg = "4";652 append(Atom::CodeQuoteArgument, arg);653 }654 #endif655 595 } 656 596 break; … … 785 725 paraState = OutsidePara; // ### 786 726 } 727 break; 728 case CMD_ANNOTATEDLIST: 729 append(Atom::AnnotatedList, getArgument()); 730 break; 731 case CMD_SINCELIST: 732 append(Atom::SinceList, getArgument()); 787 733 break; 788 734 case CMD_GENERATELIST: … … 954 900 case CMD_OLDCODE: 955 901 leavePara(); 956 #ifdef QDOC2DOX957 if (DoxWriter::isDoxPass()) {958 append(Atom::CodeOld, getUnmarkedCode(CMD_OLDCODE));959 append(Atom::CodeNew, getUnmarkedCode(CMD_NEWCODE));960 }961 else {962 append(Atom::CodeOld, getCode(CMD_OLDCODE, marker));963 append(Atom::CodeNew, getCode(CMD_NEWCODE, marker));964 }965 #else966 902 append(Atom::CodeOld, getCode(CMD_OLDCODE, marker)); 967 903 append(Atom::CodeNew, getCode(CMD_NEWCODE, marker)); 968 #endif969 904 break; 970 905 case CMD_OMIT: … … 1148 1083 QString snippet = getArgument(); 1149 1084 QString identifier = getRestOfLine(); 1150 #ifdef QDOC2DOX1151 if (quoting || DoxWriter::isDoxPass()) {1152 append(Atom::SnippetCommand, cmdStr);1153 append(Atom::SnippetLocation, snippet);1154 append(Atom::SnippetIdentifier, identifier);1155 }1156 else {1157 Doc::quoteFromFile(location(),quoter,snippet);1158 appendToCode(quoter.quoteSnippet(location(),1159 identifier));1160 }1161 #else1162 1085 if (quoting) { 1163 1086 append(Atom::SnippetCommand, cmdStr); … … 1170 1093 identifier)); 1171 1094 } 1172 #endif1173 1095 } 1174 1096 break; … … 1252 1174 append(Atom::String, " "); 1253 1175 break; 1254 case CMD_OVERLOAD: // qdoc --> doxygen1176 case CMD_OVERLOAD: 1255 1177 priv->metacommandsUsed.insert(cmdStr); 1256 1178 x.clear(); … … 1266 1188 else { 1267 1189 append(Atom::ParaLeft); 1268 append(Atom::String, 1269 "This is an overloaded member function, " 1270 "provided for convenience."); 1190 append(Atom::String,"This is an overloaded function."); 1271 1191 append(Atom::ParaRight); 1272 1192 x = getMetaCommandArgument(cmdStr); … … 1766 1686 1767 1687 if (currentSectioningUnit == Doc::Book) { 1688 #if 0 1689 // mws didn't think this was necessary. 1768 1690 if (unit > Doc::Section1) 1769 1691 location().warning(tr("Unexpected '\\%1' without '\\%2'") 1770 1692 .arg(cmdName(cmd)) 1771 1693 .arg(cmdName(CMD_SECTION1))); 1694 #endif 1772 1695 currentSectioningUnit = (Doc::SectioningUnit) (unit - 1); 1773 1696 priv->constructExtra(); … … 2346 2269 2347 2270 /*! 2348 Used only for generating doxygen output.2271 Was used only for generating doxygen output. 2349 2272 */ 2350 2273 QString DocParser::getUnmarkedCode(int cmd) … … 2582 2505 #endif 2583 2506 2584 #ifdef QDOC2DOX2585 #define DOXYGEN_INDENT 22586 #define DOXYGEN_TAB_SIZE 42587 #define DOXYGEN_INDENT_STRING " "2588 #define DOXYGEN_TAB_STRING " "2589 2590 static QRegExp ws_rx("\\s");2591 static QRegExp not_ws_rx("\\S");2592 2593 int DoxWriter::doxPass = 0;2594 QString DoxWriter::currentClass;2595 QSet<QString> DoxWriter::anchors;2596 QStringMap DoxWriter::exampleTitles;2597 QStringMap DoxWriter::headerFileTitles;2598 QStringMap DoxWriter::fileTitles;2599 QStringMap DoxWriter::groupTitles;2600 QStringMap DoxWriter::moduleTitles;2601 QStringMap DoxWriter::pageTitles;2602 QStringMap DoxWriter::externalPageTitles;2603 QStringMap DoxWriter::exampleTitlesInverse;2604 QStringMap DoxWriter::headerFileTitlesInverse;2605 QStringMap DoxWriter::fileTitlesInverse;2606 QStringMap DoxWriter::groupTitlesInverse;2607 QStringMap DoxWriter::moduleTitlesInverse;2608 QStringMap DoxWriter::pageTitlesInverse;2609 QStringMap DoxWriter::externalPageTitlesInverse;2610 QStringMultiMap DoxWriter::variables;2611 QStringMultiMap DoxWriter::properties;2612 QStringMultiMap DoxWriter::enums;2613 #endif2614 2507 2615 2508 Doc::Doc(const Location& start_loc, … … 2621 2514 DocParser parser; 2622 2515 parser.parse(source,priv,metaCommandSet); 2623 #ifdef QDOC2DOX2624 if (DoxWriter::isDoxPass()) {2625 DoxWriter doxWriter(source,priv);2626 if (DoxWriter::isDoxPass(1))2627 doxWriter.pass1();2628 else2629 doxWriter.pass2();2630 }2631 #endif2632 2516 } 2633 2517 … … 2758 2642 2759 2643 /* 2760 2761 2644 This code is really ugly. The entire \brief business 2645 should be rethought. 2762 2646 */ 2763 while (atom && (atom->type() == Atom::AutoLink || atom->type() == Atom::String)) { 2764 briefStr += atom->string(); 2647 while (atom) { 2648 if (atom->type() == Atom::AutoLink || atom->type() == Atom::String) { 2649 briefStr += atom->string(); 2650 } 2765 2651 atom = atom->next(); 2766 2652 } 2767 2653 2768 2654 QStringList w = briefStr.split(" "); 2769 if (!w.isEmpty() && w.first() == " The")2770 w.removeFirst(); 2655 if (!w.isEmpty() && w.first() == "Returns") { 2656 } 2771 2657 else { 2772 location().warning( 2773 tr("Nonstandard wording in '\\%1' text for '%2' (expected 'The')") 2774 .arg(COMMAND_BRIEF).arg(className)); 2775 standardWording = false; 2658 if (!w.isEmpty() && w.first() == "The") 2659 w.removeFirst(); 2660 else { 2661 location().warning( 2662 tr("Nonstandard wording in '\\%1' text for '%2' (expected 'The')") 2663 .arg(COMMAND_BRIEF).arg(className)); 2664 standardWording = false; 2665 } 2666 2667 if (!w.isEmpty() && (w.first() == className || w.first() == classNameOnly)) 2668 w.removeFirst(); 2669 else { 2670 location().warning( 2671 tr("Nonstandard wording in '\\%1' text for '%2' (expected '%3')") 2672 .arg(COMMAND_BRIEF).arg(className).arg(className)); 2673 standardWording = false; 2674 } 2675 2676 if (!w.isEmpty() && ((w.first() == "class") || 2677 (w.first() == "function") || 2678 (w.first() == "macro") || 2679 (w.first() == "widget") || 2680 (w.first() == "namespace") || 2681 (w.first() == "header"))) 2682 w.removeFirst(); 2683 else { 2684 location().warning( 2685 tr("Nonstandard wording in '\\%1' text for '%2' (" 2686 "expected 'class', 'function', 'macro', 'widget', " 2687 "'namespace' or 'header')") 2688 .arg(COMMAND_BRIEF).arg(className)); 2689 standardWording = false; 2690 } 2691 2692 if (!w.isEmpty() && (w.first() == "is" || w.first() == "provides")) 2693 w.removeFirst(); 2694 2695 if (!w.isEmpty() && (w.first() == "a" || w.first() == "an")) 2696 w.removeFirst(); 2776 2697 } 2777 2698 2778 if (!w.isEmpty() && (w.first() == className || w.first() == classNameOnly))2779 w.removeFirst();2780 else {2781 location().warning(2782 tr("Nonstandard wording in '\\%1' text for '%2' (expected '%3')")2783 .arg(COMMAND_BRIEF).arg(className).arg(className));2784 standardWording = false;2785 }2786 2787 if (!w.isEmpty() && (w.first() == "class" || w.first() == "widget"2788 || w.first() == "namespace" || w.first() == "header"))2789 w.removeFirst();2790 else {2791 location().warning(2792 tr("Nonstandard wording in '\\%1' text for '%2' ("2793 "expected 'class', 'widget', 'namespace' or 'header')")2794 .arg(COMMAND_BRIEF).arg(className));2795 standardWording = false;2796 }2797 2798 if (!w.isEmpty() && (w.first() == "is" || w.first() == "provides"))2799 w.removeFirst();2800 2801 if (!w.isEmpty() && (w.first() == "a" || w.first() == "an"))2802 w.removeFirst();2803 2804 2699 whats = w.join(" "); 2700 2805 2701 if (whats.endsWith(".")) 2806 2702 whats.truncate(whats.length() - 1); … … 2945 2841 DocParser::sourceDirs = config.getStringList(CONFIG_SOURCEDIRS); 2946 2842 DocParser::quoting = config.getBool(CONFIG_QUOTINGINFORMATION); 2843 2844 #ifdef QDOC_QML 2845 QmlClassNode::qmlOnly = config.getBool(CONFIG_QMLONLY); 2846 #endif 2947 2847 2948 2848 QStringMap reverseAliasMap; … … 3183 3083 } 3184 3084 3185 #ifdef QDOC2DOX3186 /*!3187 Sets the doxygen writer pass to \a pass. You can use3188 isDoxPass(), with or without a parameter, to test if3189 you are in a doxygen writer run or in a specific pass3190 of a doxygen writer run.3191 3192 This function is only called from main() if either the3193 \e doxygen1 or \e doxygen2 flag is passed to qdoc3 on3194 the command line.3195 */3196 void DoxWriter::setDoxPass(int pass)3197 {3198 qDebug() << "SETTING doxygen pass to " << pass3199 << " in DoxWriter::setDoxPass()";3200 doxPass = pass;3201 }3202 3203 /*!3204 Returns true if the doxygen pass is set to \a pass,3205 which means we are in the specified \a pass of a doxygen3206 writer run of qdoc3.3207 */3208 bool DoxWriter::isDoxPass(int pass) { return (doxPass == pass); }3209 3210 /*!3211 Returns true if the doxygen pass is 1 or 2, which3212 means this is a doxygen writer run to transform qdoc3213 comments into doxygen comments.3214 */3215 bool DoxWriter::isDoxPass() { return (doxPass > 0); }3216 3217 bool DoxWriter::conversionRequired() const3218 {3219 /*3220 Loop through all the topic commands searching for3221 one that must be transformed to doxygen format. If3222 one is found, return true.3223 */3224 QCommandMap::const_iterator i;3225 i = priv->metaCommandMap.constBegin();3226 while (i != priv->metaCommandMap.constEnd()) {3227 QString s = i.key();3228 if (s == "enum")3229 return true;3230 else if (s == "example")3231 return true;3232 else if (s == "externalpage")3233 return true;3234 else if (s == "group")3235 return true;3236 else if (s == "headerfile")3237 return true;3238 else if (s == "module")3239 return true;3240 else if (s == "page")3241 return true;3242 else if (s == "property")3243 return true;3244 else if (s == "typedef")3245 return true;3246 else if (s == "variable")3247 return true;3248 else if (s == "overload")3249 return true;3250 else if (s == "reimp")3251 return true;3252 else if (s == "relates")3253 return true;3254 else if (s == "macro")3255 return true;3256 else {3257 #if 03258 if (s == "class")3259 else if (s == "namespace")3260 else if (s == "service")3261 else if (s == "inheaderfile")3262 else if (s == "file")3263 else if (s == "fn")3264 else if (s == "contentspage")3265 else if (s == "nextpage")3266 else if (s == "previous")3267 else if (s == "indexpage")3268 else if (s == "startpage")3269 #endif3270 }3271 ++i;3272 }3273 3274 /*3275 Loop through all the qdoc atoms searching for one3276 that must be transformed to doxygen format. If one3277 is found, return true.3278 */3279 const Atom* next = priv->text.firstAtom();3280 while (next != 0) {3281 Atom::Type atomType = next->type();3282 switch (atomType) {3283 case Atom::C:3284 case Atom::CaptionLeft:3285 case Atom::Code:3286 case Atom::CodeBad:3287 case Atom::CodeNew:3288 case Atom::CodeOld:3289 case Atom::CodeQuoteArgument:3290 case Atom::CodeQuoteCommand:3291 case Atom::FootnoteLeft:3292 case Atom::FormatElse:3293 case Atom::FormatEndif:3294 case Atom::FormatIf:3295 case Atom::GeneratedList:3296 case Atom::Image:3297 case Atom::ImageText:3298 case Atom::InlineImage:3299 case Atom::LegaleseLeft:3300 case Atom::LineBreak:3301 case Atom::Link:3302 case Atom::LinkNode:3303 case Atom::ListLeft:3304 case Atom::ListItemNumber:3305 case Atom::ListTagLeft:3306 case Atom::ListItemLeft:3307 case Atom::QuotationLeft:3308 case Atom::RawString:3309 case Atom::SectionLeft:3310 case Atom::SectionHeadingLeft:3311 case Atom::SidebarLeft:3312 case Atom::SnippetCommand:3313 case Atom::SnippetIdentifier:3314 case Atom::SnippetLocation:3315 case Atom::TableLeft:3316 case Atom::TableHeaderLeft:3317 case Atom::TableRowLeft:3318 case Atom::TableItemLeft:3319 case Atom::TableOfContents:3320 case Atom::Target:3321 return true;3322 case Atom::AbstractLeft:3323 case Atom::AbstractRight:3324 case Atom::AutoLink:3325 case Atom::BaseName:3326 case Atom::BriefLeft:3327 case Atom::BriefRight:3328 case Atom::CaptionRight:3329 case Atom::FormattingLeft:3330 case Atom::FormattingRight:3331 case Atom::Nop:3332 case Atom::ParaLeft:3333 case Atom::ParaRight:3334 case Atom::FootnoteRight:3335 case Atom::LegaleseRight:3336 case Atom::ListTagRight:3337 case Atom::ListItemRight:3338 case Atom::ListRight:3339 case Atom::QuotationRight:3340 case Atom::SectionRight:3341 case Atom::SectionHeadingRight:3342 case Atom::SidebarRight:3343 case Atom::String:3344 case Atom::TableRight:3345 case Atom::TableHeaderRight:3346 case Atom::TableRowRight:3347 case Atom::TableItemRight:3348 default:3349 break;3350 }3351 next = next->next();3352 }3353 return false;3354 }3355 3356 /*!3357 A convenience function to write a qdoc metacommand as a3358 doxygen command, without conversion. i.e., some of the3359 qdoc metacommands don't require conversion for doxygen.3360 */3361 void DoxWriter::writeCommand(QCommandMap::const_iterator cmd)3362 {3363 concatenate("\\" + cmd.key() + " " + cmd.value()[0]);3364 newLine();3365 }3366 3367 /*!3368 Convert the qdoc commands in the metacommand map to3369 doxygen format. This function is called only in pass2().3370 The metacommand map contains all the metacommands that3371 were found in the qdoc comment that is being converted.3372 The metacommands are the ones that begin with the '\'.3373 These are not considered part of the text of the comment.3374 The text is converted by convertText().3375 */3376 void DoxWriter::convertMetaCommands()3377 {3378 QCommandMap& metaCmdMap = priv->metaCommandMap;3379 QCommandMap::iterator cmd;3380 int c;3381 3382 currentPage.clear();3383 currentFn.clear();3384 currentTitle.clear();3385 currentEnum.clear();3386 currentProperty.clear();3387 currentVariable.clear();3388 currentClass.clear();3389 currentExample.clear();3390 currentGroup.clear();3391 currentModule.clear();3392 currentMacro.clear();3393 currentService.clear();3394 currentTypedef.clear();3395 currentHeaderFile.clear();3396 commentType = OtherComment;3397 3398 if ((cmd = metaCmdMap.find("class")) != metaCmdMap.end()) {3399 currentClass = cmd.value()[0];3400 if ((c = currentClass.indexOf(' ')) > 0)3401 currentClass = currentClass.left(c);3402 writeCommand(cmd);3403 metaCmdMap.erase(cmd);3404 commentType = ClassComment;3405 }3406 else if ((cmd = metaCmdMap.find("fn")) != metaCmdMap.end()) {3407 currentFn = cmd.value()[0];3408 writeCommand(cmd);3409 metaCmdMap.erase(cmd);3410 commentType = FnComment;3411 }3412 else if ((cmd = metaCmdMap.find("enum")) != metaCmdMap.end()) {3413 currentEnum = cmd.value()[0];3414 if ((c = currentEnum.lastIndexOf("::")) > 0) {3415 currentClass = currentEnum.left(c);3416 currentEnum = currentEnum.right(currentEnum.size()-c-2);3417 qDebug() << "currentEnum =" << currentEnum;3418 qDebug() << "currentClass =" << currentClass;3419 }3420 writeCommand(cmd);3421 metaCmdMap.erase(cmd);3422 commentType = EnumComment;3423 }3424 else if ((cmd = metaCmdMap.find("property")) != metaCmdMap.end()) {3425 currentClass = cmd.value()[0];3426 if ((c = currentClass.lastIndexOf("::")) > 0) {3427 currentProperty = currentClass.right(currentClass.size()-c-2);3428 currentClass = currentClass.left(c);3429 qDebug() << "currentProperty =" << currentProperty;3430 qDebug() << "currentClass =" << currentClass;3431 }3432 writeCommand(cmd);3433 metaCmdMap.erase(cmd);3434 commentType = PropertyComment;3435 }3436 else if ((cmd = metaCmdMap.find("variable")) != metaCmdMap.end()) {3437 currentClass = cmd.value()[0];3438 if ((c = currentClass.lastIndexOf("::")) > 0) {3439 currentVariable = currentClass.right(currentClass.size()-c-2);3440 currentClass = currentClass.left(c);3441 qDebug() << "currentVariable =" << currentVariable;3442 qDebug() << "currentClass =" << currentClass;3443 }3444 concatenate("\\var " + cmd.value()[0]);3445 newLine();3446 metaCmdMap.erase(cmd);3447 commentType = VariableComment;3448 }3449 3450 if ((cmd = metaCmdMap.find("page")) != metaCmdMap.end()) {3451 currentPage = cmd.value()[0];3452 QString htmlFile = currentPage;3453 const QString* title = getPageTitle(htmlFile);3454 QStringList parts = htmlFile.split('.');3455 metaCmdMap.erase(cmd);3456 if (title) {3457 concatenate("\\page " + parts[0] + " " + *title);3458 newLine();3459 }3460 commentType = PageComment;3461 qDebug() << "currentPage =" << currentPage;3462 }3463 3464 if ((cmd = metaCmdMap.find("example")) != metaCmdMap.end()) {3465 currentExample = cmd.value()[0];3466 metaCmdMap.erase(cmd);3467 commentType = ExampleComment;3468 qDebug() << "currentExample =" << currentExample;3469 }3470 3471 if ((cmd = metaCmdMap.find("macro")) != metaCmdMap.end()) {3472 currentMacro = cmd.value()[0];3473 metaCmdMap.erase(cmd);3474 commentType = MacroComment;3475 qDebug() << "currentMacro =" << currentMacro;3476 }3477 3478 if ((cmd = metaCmdMap.find("group")) != metaCmdMap.end()) {3479 currentGroup = cmd.value()[0];3480 metaCmdMap.erase(cmd);3481 commentType = GroupComment;3482 qDebug() << "currentGroup =" << currentGroup;3483 }3484 3485 if ((cmd = metaCmdMap.find("module")) != metaCmdMap.end()) {3486 currentModule = cmd.value()[0];3487 metaCmdMap.erase(cmd);3488 commentType = ModuleComment;3489 qDebug() << "currentModule =" << currentModule;3490 }3491 3492 if ((cmd = metaCmdMap.find("headerfile")) != metaCmdMap.end()) {3493 currentHeaderFile = cmd.value()[0];3494 metaCmdMap.erase(cmd);3495 commentType = HeaderFileComment;3496 qDebug() << "currentHeaderFile =" << currentHeaderFile;3497 }3498 3499 if ((cmd = metaCmdMap.find("typedef")) != metaCmdMap.end()) {3500 currentClass = cmd.value()[0];3501 if ((c = currentClass.lastIndexOf("::")) > 0) {3502 currentTypedef = currentClass.right(currentClass.size()-c-2);3503 currentClass = currentClass.left(c);3504 }3505 metaCmdMap.erase(cmd);3506 commentType = TypedefComment;3507 qDebug() << "currentTypedef =" << currentTypedef;3508 qDebug() << "currentClass =" << currentClass;3509 }3510 3511 cmd = priv->metaCommandMap.begin();3512 while (cmd != priv->metaCommandMap.end()) {3513 for (int i=0; i<cmd.value().size(); i++) {3514 concatenate("\\" + cmd.key() + " " + cmd.value()[i]);3515 newLine();3516 }3517 //qDebug() << " " << cmd.key() << ": " << cmd.value();3518 ++cmd;3519 }3520 }3521 3522 /*!3523 Convert the qdoc text to doxygen format. The metacommands3524 are converted by convertMetaCommands(). This function is3525 called in pass2().3526 */3527 void DoxWriter::convertText()3528 {3529 const Atom* prev = 0;3530 const Atom* next = priv->text.firstAtom();3531 while (next != 0) {3532 next->dump();3533 Atom::Type atomType = next->type();3534 switch (atomType) {3535 case Atom::AbstractLeft:3536 break;3537 case Atom::AbstractRight:3538 break;3539 case Atom::AutoLink:3540 concatenate(next->string());3541 break;3542 case Atom::BaseName:3543 break;3544 case Atom::BriefLeft:3545 concatenate("\\brief ");3546 break;3547 case Atom::BriefRight:3548 newLine();3549 break;3550 case Atom::C:3551 tt(next);3552 break;3553 case Atom::CaptionLeft:3554 unhandled(next);3555 break;3556 case Atom::CaptionRight:3557 unhandled(next);3558 break;3559 case Atom::Code:3560 code(next);3561 break;3562 case Atom::CodeBad:3563 code(next);3564 break;3565 case Atom::CodeNew:3566 newLine();3567 concatenate("you can rewrite it as");3568 code(next);3569 break;3570 case Atom::CodeOld:3571 newLine();3572 concatenate("For example, if you have code like");3573 code(next);3574 break;3575 case Atom::CodeQuoteArgument:3576 unhandled(next);3577 break;3578 case Atom::CodeQuoteCommand:3579 next = codeQuoteCommand(next);3580 break;3581 case Atom::FootnoteLeft:3582 break;3583 case Atom::FootnoteRight:3584 break;3585 case Atom::FormatElse:3586 formatElse();3587 break;3588 case Atom::FormatEndif:3589 formatEndif();3590 break;3591 case Atom::FormatIf:3592 formatIf(next);3593 break;3594 case Atom::FormattingLeft:3595 formattingLeft(next,next->next());3596 break;3597 case Atom::FormattingRight:3598 formattingRight(next,prev);3599 break;3600 case Atom::GeneratedList:3601 break;3602 case Atom::Image:3603 break;3604 case Atom::ImageText:3605 break;3606 case Atom::InlineImage:3607 break;3608 case Atom::LegaleseLeft:3609 break;3610 case Atom::LegaleseRight:3611 break;3612 case Atom::LineBreak:3613 break;3614 case Atom::Link:3615 next = link(next);3616 break;3617 case Atom::LinkNode:3618 break;3619 case Atom::ListLeft:3620 {3621 bool nested = false;3622 if (structs.isEmpty()) {3623 const Atom* i = next->next();3624 while (i->type() != Atom::ListRight) {3625 if ((i->type() == Atom::ListLeft) ||3626 (i->type() == Atom::TableLeft)) {3627 nested = true;3628 break;3629 }3630 i = i->next();3631 }3632 }3633 else3634 nested = true;3635 StructDesc d(BulletList,nested);3636 if (next->string() == "numeric")3637 d.structType = NumericList;3638 else if (next->string() == "value") {3639 d.structType = ValueList;3640 }3641 else if (next->string() != "bullet")3642 qDebug() << "UNKNOWN LIST TYPE" << next->string();3643 structs.push(d);3644 if (nested || (d.structType != BulletList)) {3645 if (d.structType == BulletList)3646 concatenate("<ul>");3647 else if (d.structType == NumericList)3648 concatenate("<ol>");3649 else if (d.structType == ValueList)3650 concatenate("<dl>");3651 newLine();3652 }3653 }3654 break;3655 case Atom::ListItemNumber:3656 structs.top().count = next->string().toInt();3657 break;3658 case Atom::ListTagLeft:3659 {3660 structs.top().count++;3661 concatenate("<dt>");3662 const Atom* n = next->next();3663 if (n->type() == Atom::String) {3664 qDebug() << "ENUM VALUE" << n->string();3665 }3666 else3667 qDebug() << "NOT EN ENUM";3668 }3669 break;3670 case Atom::ListTagRight:3671 concatenate("</dt>");3672 break;3673 case Atom::ListItemLeft:3674 {3675 newLine();3676 const StructDesc& d = structs.top();3677 if (d.structType == BulletList) {3678 if (!d.nested)3679 concatenate("\\arg ");3680 else3681 concatenate("<li>");3682 }3683 else if (d.structType == NumericList)3684 concatenate("<li>");3685 else if (d.structType == ValueList)3686 concatenate("<dd>");3687 }3688 break;3689 case Atom::ListItemRight:3690 {3691 const StructDesc& d = structs.top();3692 if (d.structType == BulletList) {3693 if (d.nested) {3694 concatenate("</li>");3695 newLine();3696 }3697 }3698 else if (d.structType == NumericList) {3699 concatenate("</li>");3700 newLine();3701 }3702 else if (d.structType == ValueList) {3703 concatenate("</dd>");3704 newLine();3705 }3706 }3707 break;3708 case Atom::ListRight:3709 {3710 if (!structs.isEmpty()) {3711 const StructDesc& d = structs.top();3712 if (d.nested || (d.structType != BulletList)) {3713 if (d.structType == BulletList)3714 concatenate("</ul>");3715 else if (d.structType == NumericList)3716 concatenate("</ol>");3717 else if (d.structType == ValueList)3718 concatenate("</dl>");3719 newLine();3720 }3721 structs.pop();3722 }3723 }3724 break;3725 case Atom::Nop:3726 // nothing.3727 break;3728 case Atom::ParaLeft:3729 if (structs.isEmpty())3730 newLine();3731 break;3732 case Atom::ParaRight:3733 {3734 if (structs.isEmpty())3735 newLine();3736 else {3737 const StructDesc& d = structs.top();3738 if (d.nested || (d.structType != BulletList)) {3739 Atom::Type t = next->next()->type();3740 if ((t != Atom::ListItemRight) &&3741 (t != Atom::TableItemRight))3742 newLine();3743 }3744 else3745 newLine();3746 }3747 }3748 break;3749 case Atom::QuotationLeft:3750 break;3751 case Atom::QuotationRight:3752 break;3753 case Atom::RawString:3754 concatenate(next->string());3755 break;3756 case Atom::SectionLeft:3757 // nothing.3758 break;3759 case Atom::SectionRight:3760 // nothing.3761 break;3762 case Atom::SectionHeadingLeft:3763 next = sectionHeading(next);3764 break;3765 case Atom::SectionHeadingRight:3766 newLine();3767 break;3768 case Atom::SidebarLeft:3769 break;3770 case Atom::SidebarRight:3771 break;3772 case Atom::SnippetCommand:3773 newLine();3774 concatenate("\\snippet ");3775 break;3776 case Atom::SnippetIdentifier:3777 newText += next->string();3778 lineLength += next->string().size();3779 newLine();3780 break;3781 case Atom::SnippetLocation:3782 newText += next->string() + " ";3783 lineLength += next->string().size() + 1;3784 break;3785 case Atom::String:3786 wrap(next->string());3787 break;3788 case Atom::TableLeft:3789 {3790 bool nested = false;3791 if (structs.isEmpty()) {3792 const Atom* i = next->next();3793 while (i->type() != Atom::TableRight) {3794 if ((i->type() == Atom::ListLeft) ||3795 (i->type() == Atom::TableLeft)) {3796 nested = true;3797 break;3798 }3799 i = i->next();3800 }3801 }3802 else3803 nested = true;3804 StructDesc d(Table,nested);3805 structs.push(d);3806 if (next->string().isEmpty())3807 concatenate("<table>");3808 else {3809 QString attrs = "width=\"" + next->string() + "\"";3810 attrs += " align=\"center\"";3811 concatenate("<table " + attrs + ">");3812 }3813 newLine();3814 }3815 break;3816 case Atom::TableRight:3817 concatenate("</table>");3818 if (!structs.isEmpty())3819 structs.pop();3820 newLine();3821 break;3822 case Atom::TableHeaderLeft:3823 concatenate("<tr>");3824 if (!structs.isEmpty())3825 structs.top().inTableHeader = true;3826 newLine();3827 break;3828 case Atom::TableHeaderRight:3829 concatenate("</tr>");3830 if (!structs.isEmpty())3831 structs.top().inTableHeader = false;3832 newLine();3833 break;3834 case Atom::TableRowLeft:3835 if (!structs.isEmpty()) {3836 structs.top().inTableRow = true;3837 concatenate("<tr valign=\"top\" class=\"");3838 if (structs.top().odd)3839 concatenate("odd\">");3840 else3841 concatenate("even\">");3842 structs.top().odd = !structs.top().odd;3843 }3844 newLine();3845 break;3846 case Atom::TableRowRight:3847 concatenate("</tr>");3848 if (!structs.isEmpty())3849 structs.top().inTableRow = false;3850 newLine();3851 break;3852 case Atom::TableItemLeft:3853 if (!structs.isEmpty()) {3854 structs.top().inTableItem = true;3855 concatenate("<td>");3856 if (structs.top().inTableHeader)3857 concatenate("<b> ");3858 }3859 break;3860 case Atom::TableItemRight:3861 if (!structs.isEmpty()) {3862 structs.top().inTableItem = false;3863 if (structs.top().inTableHeader)3864 concatenate(" </b>");3865 concatenate("</td>");3866 }3867 newLine();3868 break;3869 case Atom::TableOfContents:3870 break;3871 case Atom::Target:3872 {3873 QString text = next->string();3874 text.remove(ws_rx);3875 newLine();3876 concatenate("\\anchor ");3877 newText += text;3878 lineLength += text.size();3879 newLine();3880 }3881 break;3882 case Atom::UnhandledFormat:3883 unhandled(next);3884 break;3885 case Atom::UnknownCommand:3886 unhandled(next);3887 break;3888 default:3889 //next->dump();3890 break;3891 }3892 prev = next;3893 next = next->next();3894 }3895 }3896 3897 /*!3898 3899 Pass one looks for topic commands and target and section3900 commands, and maybe other stuff. These are serialized to3901 text files, which are read back in by pass2().3902 */3903 void DoxWriter::pass1()3904 {3905 QCommandMap& metaCmdMap = priv->metaCommandMap;3906 if (!metaCmdMap.isEmpty()) {3907 int c;3908 QCommandMap::iterator cmd;3909 if ((cmd = metaCmdMap.find("enum")) != metaCmdMap.end()) {3910 commentType = EnumComment;3911 currentEnum = cmd.value()[0];3912 if ((c = currentEnum.lastIndexOf("::")) > 0) {3913 currentClass = currentEnum.left(c);3914 currentEnum = currentEnum.right(currentEnum.size()-c-2);3915 qDebug() << "currentEnum =" << currentEnum;3916 qDebug() << "currentClass =" << currentClass;3917 if (enums.contains(currentEnum,currentClass)) {3918 qWarning() << "DoxWriter::pass1():"3919 << "Duplicate enum:"3920 << currentClass << currentEnum;3921 }3922 else3923 enums.insert(currentEnum,currentClass);3924 }3925 }3926 else if ((cmd = metaCmdMap.find("property")) != metaCmdMap.end()) {3927 commentType = PropertyComment;3928 currentClass = cmd.value()[0];3929 if ((c = currentClass.lastIndexOf("::")) > 0) {3930 currentProperty = currentClass.right(currentClass.size()-c-2);3931 currentClass = currentClass.left(c);3932 qDebug() << "currentProperty =" << currentProperty;3933 qDebug() << "currentClass =" << currentClass;3934 if (properties.contains(currentProperty,currentClass)) {3935 qWarning() << "DoxWriter::pass1():"3936 << "Duplicate property:"3937 << currentClass << currentProperty;3938 }3939 else3940 properties.insert(currentProperty,currentClass);3941 }3942 }3943 else if ((cmd = metaCmdMap.find("variable")) != metaCmdMap.end()) {3944 commentType = VariableComment;3945 currentClass = cmd.value()[0];3946 if ((c = currentClass.lastIndexOf("::")) > 0) {3947 currentVariable = currentClass.right(currentClass.size()-c-2);3948 currentClass = currentClass.left(c);3949 qDebug() << "currentVariable =" << currentVariable;3950 qDebug() << "currentClass =" << currentClass;3951 if (variables.contains(currentVariable,currentClass)) {3952 qWarning() << "DoxWriter::pass1():"3953 << "Duplicate variable:"3954 << currentClass << currentVariable;3955 }3956 else3957 variables.insert(currentVariable,currentClass);3958 }3959 }3960 }3961 3962 /*3963 */3964 const Atom* next = priv->text.firstAtom();3965 while (next != 0) {3966 switch (next->type()) {3967 case Atom::SectionHeadingLeft:3968 {3969 QString text;3970 next = next->next();3971 while (next) {3972 if (next->type() == Atom::SectionHeadingRight)3973 break;3974 else3975 text += next->string();3976 next = next->next();3977 }3978 //text.remove(ws_rx);3979 insertAnchor(text);3980 }3981 break;3982 case Atom::Target:3983 {3984 QString text = next->string();3985 //text.remove(ws_rx);3986 insertAnchor(text);3987 }3988 default:3989 break;3990 }3991 next = next->next();3992 }3993 }3994 3995 /*!3996 Output a parsed, tokenized qdoc comment as a doxygen3997 comment in diff format for input to the patch command.3998 */3999 void DoxWriter::pass2()4000 {4001 if (!conversionRequired()) {4002 qDebug() << "NO CONVERSION - FILE:" << priv->start_loc.fileName()4003 << "START:" << priv->start_loc.lineNo()4004 << "END:" << priv->end_loc.lineNo() - 1;4005 return;4006 }4007 4008 /*4009 Transformation to doxygen required...4010 */4011 newText = "\n/*! \n";4012 convertMetaCommands();4013 convertText();4014 if (newText[newText.size()-1] == ' ')4015 newText.remove(newText.size()-1,1);4016 newText += " */\n";4017 qDebug() << "CONVERTED COMMENT - FILE:" << priv->start_loc.fileName()4018 << "START:" << priv->start_loc.lineNo()4019 << "END:" << priv->end_loc.lineNo() - 1;4020 qDebug() << newText;4021 }4022 4023 /*!4024 Unparse the second parameter of a "\l" command.4025 */4026 const Atom* DoxWriter::link(const Atom* atom)4027 {4028 QString first_text = atom->string();4029 QString second_text;4030 const QString* value = 0;4031 4032 const Atom* next = atom->next(Atom::FormattingLeft,Atom::LINK_);4033 if (next) {4034 next->dump();4035 while (1) {4036 next = next->next();4037 next->dump();4038 if (next->type() == Atom::FormattingRight) {4039 if (next->string() == Atom::LINK_)4040 break;4041 else {4042 // ignore it.4043 }4044 }4045 else4046 second_text += next->string();4047 }4048 int i = first_text.indexOf('#');4049 if (i >= 0)4050 first_text = first_text.right(first_text.size() - i - 1);4051 //newLine();4052 if ((value = getExternalPage(first_text))) {4053 //qDebug() << "USED AN EXTERNAL PAGE TITLE" << first_text;4054 QString href = "<a href=\""+*value+"\">"+first_text+"</a>";4055 concatenate(href);4056 }4057 else if (first_text.startsWith("http:",Qt::CaseInsensitive)) {4058 if (first_text == second_text) {4059 concatenate(first_text);4060 }4061 else {4062 QString href = "<a href=\""+first_text+"\">"+second_text+"</a>";4063 concatenate(href);4064 }4065 }4066 else if ((value = getPageFile(first_text))) {4067 //qDebug() << "USED A PAGE TITLE" << first_text;4068 QStringList parts = (*value).split('.');4069 QString ref = "\\ref " + parts[0] + " \"" + second_text + "\"";4070 concatenate(ref);4071 }4072 else if ((value = getGroup(first_text))) {4073 //qDebug() << "USED A GROUP TITLE" << first_text;4074 concatenate("\\ref " + *value + " \"" + second_text + "\"");4075 }4076 else if ((value = getModule(first_text))) {4077 //qDebug() << "USED A MODULE TITLE" << first_text;4078 concatenate("\\ref " + *value + " \"" + second_text + "\"");4079 }4080 else if ((value = getExamplePath(first_text))) {4081 //qDebug() << "USED AN EXAMPLE TITLE" << first_text;4082 first_text.remove(ws_rx);4083 QString ref = "\\ref " + first_text + " \"" + second_text + "\"";4084 concatenate(ref);4085 }4086 else if ((value = getFile(first_text))) {4087 //qDebug() << "USED A FILE TITLE" << first_text;4088 // I think this command is no longer available.4089 first_text.remove(ws_rx);4090 QString ref = "\\ref " + first_text + " \"" + second_text + "\"";4091 concatenate(ref);4092 }4093 else if ((value = getHeaderFile(first_text))) {4094 //qDebug() << "USED A HEADER FILE TITLE" << first_text;4095 first_text.remove(ws_rx);4096 QString ref = "\\ref " + first_text + " \"" + second_text + "\"";4097 concatenate(ref);4098 }4099 else if (isAnchor(first_text)) {4100 //qDebug() << "USED AN ANCHOR" << first_text;4101 first_text.remove(ws_rx);4102 QString ref = "\\ref " + first_text + " \"" + second_text + "\"";4103 concatenate(ref);4104 }4105 else if ((value = getPageTitle(first_text))) {4106 //qDebug() << "USED AN INVERSE PAGE TITLE" << first_text;4107 QStringList parts = first_text.split('.');4108 QString ref = "\\ref " + parts[0] + " \"" + second_text + "\"";4109 concatenate(ref);4110 }4111 else if ((value = getExampleTitle(first_text))) {4112 //qDebug() << "USED AN INVERSE EXAMPLE TITLE" << first_text;4113 QString title = *value;4114 title.remove(ws_rx);4115 QString ref = "\\ref " + title + " \"" + second_text + "\"";4116 concatenate(ref);4117 }4118 else if ((value = getGroupTitle(first_text))) {4119 //qDebug() << "USED AN INVERSE GROUP TITLE" << first_text;4120 concatenate("\\ref " + first_text + " \"" + second_text + "\"");4121 }4122 else if ((value = getModuleTitle(first_text))) {4123 //qDebug() << "USED AN INVERSE MODULE TITLE" << first_text;4124 concatenate("\\ref " + first_text + " \"" + second_text + "\"");4125 }4126 else if ((value = getFileTitle(first_text))) {4127 qDebug() << "USED AN INVERSE FILE TITLE" << first_text;4128 }4129 else if ((value = getHeaderFileTitle(first_text))) {4130 qDebug() << "USED AN INVERSE HEADER FILE TITLE" << first_text;4131 }4132 else if ((first_text.indexOf("::") >= 0) ||4133 (first_text.indexOf("()") >= 0) ||4134 (first_text[0] == 'Q')) {4135 //qDebug() << "AUTO-LINKABLE" << first_text;4136 if (first_text == second_text)4137 concatenate(first_text);4138 else {4139 QString link = first_text + " " + second_text;4140 concatenate("\\link " + link + "\\endlink");4141 }4142 }4143 else {4144 QString link;4145 QStringList propertyClasses;4146 QStringList variableClasses;4147 QStringList enumClasses;4148 bool p = isProperty(first_text,propertyClasses);4149 bool v = isVariable(first_text,variableClasses);4150 bool e = isEnum(first_text,enumClasses);4151 if (e) {4152 if (enumClasses.size() == 1)4153 link = enumClasses[0];4154 else if (enumClasses.contains(currentClass))4155 link = currentClass;4156 else {4157 QString msg = "Unqualified enum name: " + first_text;4158 QString details = "Classes: " + enumClasses.join(", ");4159 priv->start_loc.error(msg,details);4160 }4161 if (!link.isEmpty())4162 qDebug() << "FOUND ENUM" << link << first_text;4163 }4164 else if (p && v) {4165 if (propertyClasses.size() == 1) {4166 if (variableClasses.size() == 1) {4167 if (propertyClasses[0] == variableClasses[0])4168 link = propertyClasses[0];4169 }4170 }4171 if (link.isEmpty()) {4172 if (propertyClasses.contains(currentClass) ||4173 variableClasses.contains(currentClass))4174 link = currentClass;4175 else {4176 propertyClasses += variableClasses;4177 QString msg = "Unqualified property or variable name: "4178 + first_text;4179 QString details = "Classes: " +4180 propertyClasses.join(", ");4181 priv->start_loc.error(msg,details);4182 }4183 }4184 }4185 else if (p) {4186 if (propertyClasses.size() == 1)4187 link = propertyClasses[0];4188 else if (propertyClasses.contains(currentClass))4189 link = currentClass;4190 else {4191 QString msg = "Unqualified property name: " + first_text;4192 QString details = "Classes: " + propertyClasses.join(", ");4193 priv->start_loc.error(msg,details);4194 }4195 }4196 else if (v) {4197 if (variableClasses.size() == 1)4198 link = variableClasses[0];4199 else if (variableClasses.contains(currentClass))4200 link = currentClass;4201 else {4202 QString msg = "Unqualified variable name: " + first_text;4203 QString details = "Classes: " + variableClasses.join(", ");4204 priv->start_loc.error(msg,details);4205 }4206 }4207 else {4208 qDebug() << "NOT AUTO-LINKABLE" << first_text;4209 QString s = first_text + " " + second_text;4210 concatenate("\\link " + s + "\\endlink");4211 }4212 if (!link.isEmpty()) {4213 link += "::" + first_text + " " + second_text;4214 concatenate("\\link " + link + "\\endlink");4215 }4216 }4217 }4218 else4219 qDebug() << "LINK with no second parameter!!!!";4220 return next? next : atom;4221 }4222 4223 /*!4224 If the current line length is 0, the current line is4225 indented according to the context.4226 */4227 void DoxWriter::indentLine()4228 {4229 if (lineLength == 0) {4230 newText += DOXYGEN_INDENT_STRING;4231 lineLength = DOXYGEN_INDENT;4232 if (!structs.isEmpty()) {4233 for (int i=1; i<structs.size(); ++i) {4234 newText += DOXYGEN_TAB_STRING;4235 lineLength += DOXYGEN_TAB_SIZE;4236 }4237 }4238 }4239 }4240 4241 /*!4242 Concatenates a newline to the doxygen text, increments the4243 line count, and resets the line length to 0.4244 */4245 void DoxWriter::newLine()4246 {4247 newText += "\n";4248 ++lineCount;4249 lineLength = 0;4250 }4251 4252 static const int maxLineLength = 70;4253 4254 /*!4255 Concatenate the \a text to the doxygen comment currently4256 under construction and increment the current line length4257 by the size of the \a text.4258 4259 If incrementing the current line length by the \a text size4260 would make the current line length longer than the maximum4261 line length, then call newLine() and indentLine() \e before4262 concatenating the \a text.4263 */4264 void DoxWriter::concatenate(QString text)4265 {4266 if ((lineLength + text.size()) > maxLineLength)4267 newLine();4268 indentLine();4269 newText += text;4270 lineLength += text.size();4271 }4272 4273 static bool punctuation(QChar c)4274 {4275 switch (c.toAscii()) {4276 case '.':4277 case ',':4278 case ':':4279 case ';':4280 case '/':4281 case '+':4282 case '-':4283 case '?':4284 case '!':4285 case '\"':4286 return true;4287 default:4288 break;4289 }4290 return false;4291 }4292 4293 /*!4294 Concatenate the \a text string to the doxygen text, doing4295 line wrapping where necessary.4296 */4297 void DoxWriter::wrap(QString text)4298 {4299 int from = 0;4300 int to = -1;4301 4302 if ((lineLength == 0) || (lineLength >= maxLineLength)) {4303 if (!text.isEmpty() && (text[0] == ' '))4304 text = text.right(text.size() - 1);4305 }4306 4307 indentLine();4308 while (text.size()) {4309 int avail = maxLineLength - lineLength;4310 from = text.indexOf(' ',from);4311 if (from >= 0) {4312 if (from < avail)4313 to = from++;4314 else if (from == 1 && punctuation(text[0]))4315 to = from++;4316 else {4317 if (to >= 0) {4318 newText += text.left(to+1);4319 lineLength += to + 1;4320 text = text.right(text.size() - to - 1);4321 }4322 else {4323 newLine();4324 indentLine();4325 newText += text.left(from+1);4326 lineLength += from + 1;4327 text = text.right(text.size() - from - 1);4328 }4329 from = 0;4330 to = -1;4331 if (text.size() && (lineLength > maxLineLength)) {4332 newLine();4333 indentLine();4334 }4335 }4336 }4337 else4338 break;4339 }4340 if (text.size()) {4341 if (lineLength >= maxLineLength) {4342 newLine();4343 indentLine();4344 }4345 newText += text;4346 lineLength += text.size();4347 }4348 }4349 4350 /*!4351 This will output something, but it depends on what the4352 \a atom string and the \a next atom string are.4353 */4354 void DoxWriter::formattingLeft(const Atom* atom, const Atom* next)4355 {4356 if (atom->string() == "parameter") {4357 concatenate("\\a ");4358 return;4359 }4360 else if (atom->string() == "underline") {4361 concatenate("<u>");4362 return;4363 }4364 else if (atom->string() == "superscript") {4365 concatenate("<sup>");4366 return;4367 }4368 else if (atom->string() == "subscript") {4369 concatenate("<sub>");4370 return;4371 }4372 int ws = -1;4373 if (next)4374 ws = next->string().indexOf(ws_rx);4375 if (atom->string() == "bold") {4376 if (ws < 0)4377 concatenate("\\b ");4378 else4379 concatenate("<b>");4380 }4381 else if (atom->string() == "italic") {4382 if (ws < 0)4383 concatenate("\\e ");4384 else4385 concatenate("<i>");4386 }4387 else if (atom->string() == "teletype") {4388 if (ws < 0)4389 concatenate("\\c ");4390 else4391 concatenate("<tt>");4392 }4393 else4394 qDebug() << "UNHANDLED FormattingLeft: " << atom->string();4395 }4396 4397 /*!4398 This will output something, but it depends on what the4399 \a atom string and the \a prev atom string are.4400 */4401 void DoxWriter::formattingRight(const Atom* atom, const Atom* prev)4402 {4403 if (atom->string() == "parameter")4404 return;4405 else if (atom->string() == "underline") {4406 concatenate("</u>");4407 return;4408 }4409 else if (atom->string() == "superscript") {4410 concatenate("</sup>");4411 return;4412 }4413 else if (atom->string() == "subscript") {4414 concatenate("</sub>");4415 return;4416 }4417 int ws = -1;4418 if (prev)4419 ws = prev->string().indexOf(ws_rx);4420 if (ws < 0)4421 return;4422 if (atom->string() == "bold")4423 concatenate("</b>");4424 else if (atom->string() == "italic")4425 concatenate("</i>");4426 else if (atom->string() == "teletype")4427 concatenate("</tt>");4428 else4429 qDebug() << "UNHANDLED FormattingRight: " << atom->string();4430 }4431 4432 /*!4433 Output a \c or a <tt>...</tt>.4434 */4435 void DoxWriter::tt(const Atom* atom)4436 {4437 if (atom->string().indexOf(ws_rx) < 0) {4438 concatenate("\\c ");4439 concatenate(atom->string());4440 }4441 else {4442 concatenate("<tt>");4443 concatenate(atom->string());4444 concatenate("</tt>");4445 }4446 }4447 4448 /*!4449 */4450 void DoxWriter::formatIf(const Atom* atom)4451 {4452 if (atom->string() == "HTML") {4453 newLine();4454 concatenate("\\htmlonly");4455 newLine();4456 }4457 }4458 4459 /*!4460 */4461 void DoxWriter::formatEndif()4462 {4463 newLine();4464 concatenate("\\endhtmlonly");4465 newLine();4466 }4467 4468 /*!4469 */4470 void DoxWriter::formatElse()4471 {4472 // nothing.4473 }4474 4475 /*!4476 Pass 1: Construct a section identifier and insert it into4477 the anchor set.4478 4479 Pass 2: Convert section1, section2, and section3 commands4480 to section, subsection, and subsubsection respectively.4481 Warn if a section command higher than 3 is seen.4482 */4483 const Atom* DoxWriter::sectionHeading(const Atom* atom)4484 {4485 QString heading_level = atom->string();4486 QString heading_text;4487 const Atom* next = atom->next();4488 while (next) {4489 next->dump();4490 if (next->type() == Atom::SectionHeadingRight) {4491 if (next->string() == heading_level)4492 break;4493 else {4494 qDebug() << "WRONG SectionHeading number!!!!";4495 }4496 }4497 else4498 heading_text += next->string();4499 next = next->next();4500 }4501 4502 QString heading_identifier = heading_text;4503 heading_identifier.remove(ws_rx);4504 4505 newLine();4506 if (heading_level == "1")4507 heading_level = "\\section ";4508 else if (heading_level == "2")4509 heading_level = "\\subsection ";4510 else if (heading_level == "3")4511 heading_level = "\\subsubsection ";4512 else if (heading_level == "4") {4513 heading_level = "\\subsubsection ";4514 qDebug() << "WARNING section4 converted to \\subsubsection";4515 }4516 else {4517 heading_level = "\\subsubsection ";4518 qDebug() << "WARNING section5 converted to \\subsubsection";4519 }4520 concatenate(heading_level);4521 newText += heading_identifier + " ";4522 lineLength += heading_identifier.size() + 1;4523 newText += heading_text;4524 lineLength += heading_text.size();4525 newLine();4526 return next? next : atom;4527 }4528 4529 /*!4530 Report an unhandled atom.4531 */4532 void DoxWriter::unhandled(const Atom* atom)4533 {4534 qDebug() << "UNHANDLED ATOM";4535 atom->dump();4536 }4537 4538 /*!4539 Output a code/endcode block.4540 */4541 void DoxWriter::code(const Atom* atom)4542 {4543 newLine();4544 concatenate("\\code");4545 writeCode(atom->string());4546 concatenate("\\endcode");4547 newLine();4548 }4549 4550 /*!4551 Output a code/endcode block depending on the4552 CodeQuote Command and CodeQuoteArgument parameters.4553 */4554 const Atom* DoxWriter::codeQuoteCommand(const Atom* atom)4555 {4556 QString command = atom->string();4557 atom = atom->next();4558 concatenate("\\code");4559 if (command == "codeline") {4560 newLine();4561 concatenate(atom->string());4562 newLine();4563 }4564 else if (command == "dots") {4565 newLine();4566 concatenate(atom->string());4567 newLine();4568 }4569 else {4570 writeCode(atom->string());4571 }4572 concatenate("\\endcode");4573 return atom;4574 }4575 4576 /*!4577 Appends a block of code to the comment.4578 */4579 void DoxWriter::writeCode(QString text)4580 {4581 int cr_count = text.count('\n') - 1;4582 if (cr_count >= 0) {4583 int last_cr = text.lastIndexOf('\n');4584 newText += text.left(last_cr);4585 lineCount += cr_count;4586 }4587 else4588 newText += text;4589 newLine();4590 }4591 4592 /*!4593 Inserts \a text into the anchor set. This function is called4594 during doxygen pass 1.4595 */4596 void DoxWriter::insertAnchor(const QString& text)4597 {4598 anchors.insert(text);4599 }4600 4601 /*!4602 Returns true if \a text identifies an anchor, section,4603 subsection, subsubsection, or page.4604 */4605 bool DoxWriter::isAnchor(const QString& text)4606 {4607 return anchors.contains(text);4608 }4609 4610 /*!4611 Write the set of anchors to a file, one per line.4612 */4613 void DoxWriter::writeAnchors()4614 {4615 QFile file("anchors.txt");4616 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {4617 qWarning("Unable to open anchors.txt for writing.");4618 return;4619 }4620 4621 QTextStream out(&file);4622 QSet<QString>::const_iterator i = anchors.constBegin();4623 while (i != anchors.constEnd()) {4624 out << *i << "\n";4625 ++i;4626 }4627 file.close();4628 }4629 4630 /*!4631 Read the set of anchors from the anchors file, one per line,4632 and insert each one into the anchor set.4633 */4634 void DoxWriter::readAnchors()4635 {4636 QFile file("anchors.txt");4637 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {4638 qWarning("Unable to open anchors.txt for reading.");4639 return;4640 }4641 4642 QTextStream in(&file);4643 while (!in.atEnd()) {4644 QString line = in.readLine();4645 anchors.insert(line);4646 }4647 file.close();4648 #if 04649 QSet<QString>::const_iterator i = anchors.constBegin();4650 while (i != anchors.constEnd()) {4651 qDebug() << *i;4652 ++i;4653 }4654 #endif4655 }4656 4657 /*!4658 Inserts \a title into one of the title maps. \a title is4659 mapped to the \a node name. This function is called during4660 doxygen pass 1.4661 */4662 void DoxWriter::insertTitle(FakeNode* node, const QString& title)4663 {4664 switch (node->subType()) {4665 case FakeNode::Example:4666 if (exampleTitles.contains(title)) {4667 qWarning() << "DoxWriter::insertTitle():"4668 << "Duplicate example title:"4669 << title;4670 }4671 else {4672 exampleTitles[title] = node->name();4673 exampleTitlesInverse[node->name()] = title;4674 }4675 break;4676 case FakeNode::HeaderFile:4677 if (headerFileTitles.contains(title)) {4678 qWarning() << "DoxWriter::insertTitle():"4679 << "Duplicate header file title:"4680 << title;4681 }4682 else {4683 headerFileTitles[title] = node->name();4684 headerFileTitlesInverse[node->name()] = title;4685 }4686 break;4687 case FakeNode::File:4688 if (fileTitles.contains(title)) {4689 qWarning() << "DoxWriter::insertTitle():"4690 << "Duplicate file title:"4691 << title;4692 }4693 else {4694 fileTitles[title] = node->name();4695 fileTitlesInverse[node->name()] = title;4696 }4697 break;4698 case FakeNode::Group:4699 if (groupTitles.contains(title)) {4700 qWarning() << "DoxWriter::insertTitle():"4701 << "Duplicate group title:"4702 << title;4703 }4704 else {4705 groupTitles[title] = node->name();4706 groupTitlesInverse[node->name()] = title;4707 }4708 break;4709 case FakeNode::Module:4710 if (moduleTitles.contains(title)) {4711 qWarning() << "DoxWriter::insertTitle():"4712 << "Duplicate module title:"4713 << title;4714 }4715 else {4716 moduleTitles[title] = node->name();4717 moduleTitlesInverse[node->name()] = title;4718 }4719 break;4720 case FakeNode::Page:4721 if (pageTitles.contains(title)) {4722 qWarning() << "DoxWriter::insertTitle():"4723 << "Duplicate page title:"4724 << title;4725 }4726 else {4727 pageTitles[title] = node->name();4728 pageTitlesInverse[node->name()] = title;4729 }4730 break;4731 case FakeNode::ExternalPage:4732 if (externalPageTitles.contains(title)) {4733 qWarning() << "DoxWriter::insertTitle():"4734 << "Duplicate external page title:"4735 << title;4736 }4737 else {4738 externalPageTitles[title] = node->name();4739 externalPageTitlesInverse[node->name()] = title;4740 }4741 break;4742 default:4743 break;4744 }4745 }4746 4747 /*!4748 */4749 const QString* DoxWriter::getPageFile(const QString& title)4750 {4751 QStringMapEntry entry = pageTitles.find(title);4752 return (entry == pageTitles.end()) ? 0 : &entry.value();4753 }4754 4755 /*!4756 */4757 const QString* DoxWriter::getExamplePath(const QString& title)4758 {4759 QStringMapEntry entry = exampleTitles.find(title);4760 return (entry == exampleTitles.end()) ? 0 : &entry.value();4761 }4762 4763 /*!4764 */4765 const QString* DoxWriter::getFile(const QString& title)4766 {4767 QStringMapEntry entry = fileTitles.find(title);4768 return (entry == fileTitles.end()) ? 0 : &entry.value();4769 }4770 4771 /*!4772 */4773 const QString* DoxWriter::getHeaderFile(const QString& title)4774 {4775 QStringMapEntry entry = headerFileTitles.find(title);4776 return (entry == headerFileTitles.end()) ? 0 : &entry.value();4777 }4778 4779 /*!4780 */4781 const QString* DoxWriter::getGroup(const QString& title)4782 {4783 QStringMapEntry entry = groupTitles.find(title);4784 return (entry == groupTitles.end()) ? 0 : &entry.value();4785 }4786 4787 /*!4788 */4789 const QString* DoxWriter::getModule(const QString& title)4790 {4791 QStringMapEntry entry = moduleTitles.find(title);4792 return (entry == moduleTitles.end()) ? 0 : &entry.value();4793 }4794 4795 /*!4796 */4797 const QString* DoxWriter::getExternalPage(const QString& title)4798 {4799 QStringMapEntry entry = externalPageTitles.find(title);4800 return (entry == externalPageTitles.end()) ? 0 : &entry.value();4801 }4802 4803 /*!4804 */4805 const QString* DoxWriter::getPageTitle(const QString& text)4806 {4807 QStringMapEntry entry = pageTitlesInverse.find(text);4808 return (entry == pageTitlesInverse.end()) ? 0 : &entry.value();4809 }4810 4811 /*!4812 */4813 const QString* DoxWriter::getExampleTitle(const QString& text)4814 {4815 QStringMapEntry entry = exampleTitlesInverse.find(text);4816 return (entry == exampleTitlesInverse.end()) ? 0 : &entry.value();4817 }4818 4819 /*!4820 */4821 const QString* DoxWriter::getFileTitle(const QString& text)4822 {4823 QStringMapEntry entry = fileTitlesInverse.find(text);4824 return (entry == fileTitlesInverse.end()) ? 0 : &entry.value();4825 }4826 4827 /*!4828 */4829 const QString* DoxWriter::getHeaderFileTitle(const QString& text)4830 {4831 QStringMapEntry entry = headerFileTitlesInverse.find(text);4832 return (entry == headerFileTitlesInverse.end()) ? 0 : &entry.value();4833 }4834 4835 /*!4836 */4837 const QString* DoxWriter::getGroupTitle(const QString& text)4838 {4839 QStringMapEntry entry = groupTitlesInverse.find(text);4840 return (entry == groupTitlesInverse.end()) ? 0 : &entry.value();4841 }4842 4843 /*!4844 */4845 const QString* DoxWriter::getModuleTitle(const QString& text)4846 {4847 QStringMapEntry entry = moduleTitlesInverse.find(text);4848 return (entry == moduleTitlesInverse.end()) ? 0 : &entry.value();4849 }4850 4851 /*!4852 */4853 const QString* DoxWriter::getExternalPageTitle(const QString& text)4854 {4855 QStringMapEntry entry = externalPageTitlesInverse.find(text);4856 return (entry == externalPageTitlesInverse.end()) ? 0 : &entry.value();4857 }4858 4859 /*!4860 Serialize \a map to file \a name.4861 */4862 void DoxWriter::writeMap(const QStringMap& map, const QString& name)4863 {4864 4865 QFile file(name);4866 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {4867 qWarning() << "Unable to open" << name << "for writing.";4868 return;4869 }4870 4871 QTextStream out(&file);4872 QStringMap::const_iterator i = map.constBegin();4873 while (i != map.constEnd()) {4874 out << i.key() << "\n";4875 out << i.value() << "\n";4876 ++i;4877 }4878 file.close();4879 }4880 4881 /*!4882 Read file \a name into the \a map.4883 */4884 void DoxWriter::readMap(QStringMap& map, QStringMap& inverseMap, const QString& name)4885 {4886 QFile file(name);4887 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {4888 qWarning() << "Unable to open" << name << "for reading.";4889 return;4890 }4891 4892 QTextStream in(&file);4893 while (!in.atEnd()) {4894 QString title = in.readLine();4895 QString value = in.readLine();4896 map[title] = value;4897 inverseMap[value] = title;4898 }4899 file.close();4900 }4901 4902 /*!4903 Write the sets of titles to text files, one per line.4904 */4905 void DoxWriter::writeTitles()4906 {4907 if (!pageTitles.isEmpty())4908 writeMap(pageTitles,"pagetitles.txt");4909 if (!fileTitles.isEmpty())4910 writeMap(fileTitles,"filetitles.txt");4911 if (!headerFileTitles.isEmpty())4912 writeMap(headerFileTitles,"headerfiletitles.txt");4913 if (!exampleTitles.isEmpty())4914 writeMap(exampleTitles,"exampletitles.txt");4915 if (!moduleTitles.isEmpty())4916 writeMap(moduleTitles,"moduletitles.txt");4917 if (!groupTitles.isEmpty())4918 writeMap(groupTitles,"grouptitles.txt");4919 if (!externalPageTitles.isEmpty())4920 writeMap(externalPageTitles,"externalpagetitles.txt");4921 }4922 4923 /*!4924 Read the sets of titles from the titles files, one per line,4925 and insert each one into the appropriate title set.4926 */4927 void DoxWriter::readTitles()4928 {4929 readMap(pageTitles,pageTitlesInverse,"pagetitles.txt");4930 readMap(fileTitles,fileTitlesInverse,"filetitles.txt");4931 readMap(headerFileTitles,headerFileTitlesInverse,"headerfiletitles.txt");4932 readMap(exampleTitles,exampleTitlesInverse,"exampletitles.txt");4933 readMap(moduleTitles,moduleTitlesInverse,"moduletitles.txt");4934 readMap(groupTitles,groupTitlesInverse,"grouptitles.txt");4935 readMap(externalPageTitles,4936 externalPageTitlesInverse,4937 "externalpagetitles.txt");4938 }4939 4940 /*!4941 Serialize \a map to file \a name.4942 */4943 void DoxWriter::writeMultiMap(const QStringMultiMap& map, const QString& name)4944 {4945 4946 QFile file(name);4947 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {4948 qWarning() << "Unable to open" << name << "for writing.";4949 return;4950 }4951 4952 QTextStream out(&file);4953 QStringMultiMap::const_iterator i = map.constBegin();4954 while (i != map.constEnd()) {4955 out << i.key() << "\n";4956 out << i.value() << "\n";4957 ++i;4958 }4959 file.close();4960 }4961 4962 /*!4963 Write the4 property names and variable names to text files.4964 */4965 void DoxWriter::writeMembers()4966 {4967 if (!variables.isEmpty())4968 writeMultiMap(variables,"variables.txt");4969 if (!properties.isEmpty())4970 writeMultiMap(properties,"properties.txt");4971 if (!enums.isEmpty())4972 writeMultiMap(enums,"enums.txt");4973 }4974 4975 /*!4976 Read file \a name into the \a map.4977 */4978 void DoxWriter::readMultiMap(QStringMultiMap& map, const QString& name)4979 {4980 QFile file(name);4981 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {4982 qWarning() << "Unable to open" << name << "for reading.";4983 return;4984 }4985 4986 QTextStream in(&file);4987 while (!in.atEnd()) {4988 QString member = in.readLine();4989 QString className = in.readLine();4990 map.insert(member,className);4991 }4992 file.close();4993 }4994 4995 /*!4996 Read the property names and variable names from the test files.4997 */4998 void DoxWriter::readMembers()4999 {5000 readMultiMap(variables,"variables.txt");5001 readMultiMap(properties,"properties.txt");5002 readMultiMap(enums,"enums.txt");5003 }5004 5005 /*!5006 Return true if \a name is a property. Loads \a classes with5007 the names of all the classes in which \a name is a property.5008 */5009 bool DoxWriter::isProperty(const QString& name, QStringList& classes)5010 {5011 classes = properties.values(name);5012 return !classes.isEmpty();5013 }5014 5015 /*!5016 Return true if \a name is a variable. Loads \a classes with5017 the names of all the classes in which \a name is a variable.5018 */5019 bool DoxWriter::isVariable(const QString& name, QStringList& classes)5020 {5021 classes = variables.values(name);5022 return !classes.isEmpty();5023 }5024 5025 /*!5026 Return true if \a name is an enum type. Loads \a classes with5027 the names of all the classes in which \a name is an enum type.5028 */5029 bool DoxWriter::isEnum(const QString& name, QStringList& classes)5030 {5031 classes = enums.values(name);5032 return !classes.isEmpty();5033 }5034 #endif5035 5036 3085 QT_END_NAMESPACE
Note:
See TracChangeset
for help on using the changeset viewer.