Orb/Doxygen/src/docsets.cpp
changeset 0 42188c7ea2d9
child 4 468f4c8d3d5b
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /******************************************************************************
       
     2  *
       
     3  * Copyright (C) 1997-2008 by Dimitri van Heesch.
       
     4  *
       
     5  * Permission to use, copy, modify, and distribute this software and its
       
     6  * documentation under the terms of the GNU General Public License is hereby 
       
     7  * granted. No representations are made about the suitability of this software 
       
     8  * for any purpose. It is provided "as is" without express or implied warranty.
       
     9  * See the GNU General Public License for more details.
       
    10  *
       
    11  * Documents produced by Doxygen are derivative works derived from the
       
    12  * input used in their production; they are not affected by this license.
       
    13  *
       
    14  */
       
    15 
       
    16 #include "docsets.h"
       
    17 #include "config.h"
       
    18 #include "message.h"
       
    19 #include "doxygen.h"
       
    20 #include <qfile.h>
       
    21 
       
    22 
       
    23 DocSets::DocSets() : m_nodes(17), m_scopes(17)
       
    24 {
       
    25   m_nf = 0;
       
    26   m_tf = 0;
       
    27   m_dc = 0;
       
    28   m_id = 0;
       
    29   m_nodes.setAutoDelete(TRUE);
       
    30 }
       
    31 
       
    32 DocSets::~DocSets()
       
    33 {
       
    34   delete m_nf;
       
    35   delete m_tf;
       
    36 }
       
    37 
       
    38 void DocSets::initialize()
       
    39 {
       
    40   // -- get config options
       
    41   QCString projectName = Config_getString("PROJECT_NAME");
       
    42   if (projectName.isEmpty()) projectName="root";
       
    43   QCString bundleId = Config_getString("DOCSET_BUNDLE_ID");
       
    44   if (bundleId.isEmpty()) bundleId="org.doxygen.Project";
       
    45   QCString feedName = Config_getString("DOCSET_FEEDNAME");
       
    46   if (feedName.isEmpty()) feedName="FeedName";
       
    47 
       
    48   // -- write Makefile
       
    49   {
       
    50   QCString mfName = Config_getString("HTML_OUTPUT") + "/Makefile";
       
    51   QFile makefile(mfName);
       
    52   if (!makefile.open(IO_WriteOnly))
       
    53   {
       
    54     err("Could not open file %s for writing\n",mfName.data());
       
    55     exit(1);
       
    56   }
       
    57   QTextStream ts(&makefile);
       
    58   ts.setEncoding(QTextStream::UnicodeUTF8);
       
    59 
       
    60   ts << "DOCSET_NAME=" << bundleId << ".docset\n" 
       
    61         "DOCSET_CONTENTS=$(DOCSET_NAME)/Contents\n"
       
    62         "DOCSET_RESOURCES=$(DOCSET_CONTENTS)/Resources\n"
       
    63         "DOCSET_DOCUMENTS=$(DOCSET_RESOURCES)/Documents\n"
       
    64         "DESTDIR=~/Library/Developer/Shared/Documentation/DocSets\n"
       
    65         "XCODE_INSTALL=$(shell xcode-select -print-path)\n"
       
    66         "\n"
       
    67         "all: docset\n"
       
    68         "\n"
       
    69         "docset:\n"
       
    70         "\tmkdir -p $(DOCSET_DOCUMENTS)\n"
       
    71         "\tcp Nodes.xml $(DOCSET_RESOURCES)\n"
       
    72         "\tcp Tokens.xml $(DOCSET_RESOURCES)\n"
       
    73         "\tcp Info.plist $(DOCSET_CONTENTS)\n"
       
    74         "\ttar --exclude $(DOCSET_NAME) \\\n"
       
    75         "\t    --exclude Nodes.xml \\\n"
       
    76         "\t    --exclude Tokens.xml \\\n"
       
    77         "\t    --exclude Info.plist \\\n"
       
    78         "\t    --exclude Makefile -c -f - . \\\n"
       
    79         "\t    | (cd $(DOCSET_DOCUMENTS); tar xvf -)\n"
       
    80         "\t$(XCODE_INSTALL)/usr/bin/docsetutil index $(DOCSET_NAME)\n"
       
    81         "\trm -f $(DOCSET_DOCUMENTS)/Nodes.xml\n"
       
    82         "\trm -f $(DOCSET_DOCUMENTS)/Info.plist\n"
       
    83         "\trm -f $(DOCSET_DOCUMENTS)/Makefile\n"
       
    84         "\trm -f $(DOCSET_RESOURCES)/Nodes.xml\n"
       
    85         "\trm -f $(DOCSET_RESOURCES)/Tokens.xml\n"
       
    86         "\n"
       
    87         "install: docset\n"
       
    88         "\tmkdir -p $(DESTDIR)\n"
       
    89         "\tcp -R $(DOCSET_NAME) $(DESTDIR)\n"
       
    90         "\n"
       
    91         "uninstall:\n"
       
    92         "\trm -rf $(DESTDIR)/$(DOCSET_NAME)\n"
       
    93         "\n"
       
    94         "always:\n";
       
    95   }
       
    96 
       
    97   // -- write Info.plist
       
    98   {
       
    99   QCString plName = Config_getString("HTML_OUTPUT") + "/Info.plist";
       
   100   QFile plist(plName);
       
   101   if (!plist.open(IO_WriteOnly))
       
   102   {
       
   103     err("Could not open file %s for writing\n",plName.data());
       
   104     exit(1);
       
   105   }
       
   106   QTextStream ts(&plist);
       
   107   ts.setEncoding(QTextStream::UnicodeUTF8);
       
   108 
       
   109   ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 
       
   110         "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"\n" 
       
   111         "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" 
       
   112         "<plist version=\"1.0\">\n" 
       
   113         "<dict>\n" 
       
   114         "     <key>CFBundleName</key>\n" 
       
   115         "     <string>" << projectName << "</string>\n" 
       
   116         "     <key>CFBundleIdentifier</key>\n"
       
   117         "     <string>" << bundleId << ".docset</string>\n" 
       
   118         "     <key>DocSetFeedName</key>\n" 
       
   119         "     <string>" << feedName << "</string>\n"
       
   120         "</dict>\n"
       
   121         "</plist>\n";
       
   122   }
       
   123 
       
   124   // -- start Nodes.xml
       
   125   QCString notes = Config_getString("HTML_OUTPUT") + "/Nodes.xml";
       
   126   m_nf = new QFile(notes);
       
   127   if (!m_nf->open(IO_WriteOnly))
       
   128   {
       
   129     err("Could not open file %s for writing\n",notes.data());
       
   130     exit(1);
       
   131   }
       
   132   QCString indexName=Config_getBool("GENERATE_TREEVIEW")?"main":"index";
       
   133   m_nts.setDevice(m_nf);
       
   134   m_nts.setEncoding(QTextStream::UnicodeUTF8);
       
   135   m_nts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
       
   136   m_nts << "<DocSetNodes version=\"1.0\">" << endl;
       
   137   m_nts << "  <TOC>" << endl;
       
   138   m_nts << "    <Node>" << endl;
       
   139   m_nts << "      <Name>Root</Name>" << endl;
       
   140   m_nts << "      <Path>" << indexName << Doxygen::htmlFileExtension << "</Path>" << endl;
       
   141   m_nts << "      <Subnodes>" << endl;
       
   142   m_dc = 1;
       
   143   m_firstNode.resize(m_dc);
       
   144   m_firstNode.at(0)=TRUE;
       
   145 
       
   146   QCString tokens = Config_getString("HTML_OUTPUT") + "/Tokens.xml";
       
   147   m_tf = new QFile(tokens);
       
   148   if (!m_tf->open(IO_WriteOnly))
       
   149   {
       
   150     err("Could not open file %s for writing\n",tokens.data());
       
   151     exit(1);
       
   152   }
       
   153   m_tts.setDevice(m_tf);
       
   154   m_tts.setEncoding(QTextStream::UnicodeUTF8);
       
   155   m_tts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
       
   156   m_tts << "<Tokens version=\"1.0\">" << endl;
       
   157 }
       
   158 
       
   159 void DocSets::finalize()
       
   160 {
       
   161   m_nts << indent() << " </Node>" << endl;
       
   162   m_dc--;
       
   163   m_nts << "      </Subnodes>" << endl;
       
   164   m_nts << "    </Node>" << endl;
       
   165   m_nts << "  </TOC>" << endl;
       
   166   m_nts << "</DocSetNodes>" << endl;
       
   167   m_nf->close();
       
   168   delete m_nf;
       
   169   m_nf=0;
       
   170 
       
   171   m_tts << "</Tokens>" << endl;
       
   172   m_tf->close();
       
   173   delete m_tf;
       
   174   m_tf=0;
       
   175 }
       
   176 
       
   177 QCString DocSets::indent()
       
   178 {
       
   179   QCString result;
       
   180   result.fill(' ',(m_dc+2)*2);
       
   181   return result;
       
   182 }
       
   183 
       
   184 void DocSets::incContentsDepth()
       
   185 {
       
   186   ++m_dc;
       
   187   m_nts << indent() << "<Subnodes>" << endl;
       
   188   m_firstNode.resize(m_dc);
       
   189   if (m_dc>0)
       
   190   {
       
   191     m_firstNode.at(m_dc-1)=TRUE;
       
   192   }
       
   193 }
       
   194 
       
   195 void DocSets::decContentsDepth()
       
   196 {
       
   197   if (!m_firstNode.at(m_dc-1))
       
   198   {
       
   199     m_nts << indent() << " </Node>" << endl;
       
   200   }
       
   201   m_nts << indent() << "</Subnodes>" << endl;
       
   202   --m_dc;
       
   203 }
       
   204 
       
   205 void DocSets::addContentsItem(bool isDir,
       
   206                               const char *name, 
       
   207                               const char *ref, 
       
   208                               const char *file,
       
   209                               const char *anchor)
       
   210 {
       
   211   (void)isDir;
       
   212   if (file && ref==0)
       
   213   {
       
   214     if (!m_firstNode.at(m_dc-1))
       
   215     {
       
   216       m_nts << indent() << " </Node>" << endl;
       
   217     }
       
   218     m_firstNode.at(m_dc-1)=FALSE;
       
   219     m_nts << indent() << " <Node>" << endl;
       
   220     m_nts << indent() << "  <Name>" << convertToXML(name) << "</Name>" << endl;
       
   221     m_nts << indent() << "  <Path>" << file << Doxygen::htmlFileExtension;
       
   222     if (anchor)
       
   223     {
       
   224       m_nts << "#" << anchor;
       
   225     }
       
   226     m_nts << "</Path>" << endl;
       
   227   }
       
   228 }
       
   229 
       
   230 void DocSets::addIndexItem(Definition *context,MemberDef *md,
       
   231                            const char *anchor,const char *word)
       
   232 {
       
   233   (void)anchor;
       
   234   (void)word;
       
   235   if (md==0 || context==0) return; // TODO: also index non members...
       
   236 
       
   237   FileDef *fd      = 0;
       
   238   ClassDef *cd     = 0;
       
   239   NamespaceDef *nd = 0;
       
   240 
       
   241   if (md)
       
   242   {
       
   243     fd = md->getFileDef();
       
   244     cd = md->getClassDef();
       
   245     nd = md->getNamespaceDef();
       
   246     if (!md->isLinkable()) return; // internal symbol
       
   247   }
       
   248 
       
   249   QCString scope;
       
   250   QCString type;
       
   251   QCString decl;
       
   252 
       
   253   // determine language
       
   254   QCString lang;
       
   255   SrcLangExt langExt = SrcLangExt_Cpp;
       
   256   if (fd) langExt = getLanguageFromFileName(fd->name());
       
   257   switch (langExt)
       
   258   {
       
   259     case SrcLangExt_Cpp:
       
   260     case SrcLangExt_ObjC:
       
   261       {
       
   262         if (md && (md->isObjCMethod() || md->isObjCProperty()))
       
   263           lang="occ";  // Objective C/C++
       
   264         else if (fd && fd->name().right(2).lower()==".c") 
       
   265           lang="c";    // Plain C
       
   266         else if (cd==0 && nd==0)
       
   267           lang="c";    // Plain C symbol outside any class or namespace
       
   268         else
       
   269           lang="cpp";  // C++
       
   270       }
       
   271       break;
       
   272     case SrcLangExt_IDL:    lang="idl"; break;        // IDL
       
   273     case SrcLangExt_CSharp: lang="csharp"; break;     // C#
       
   274     case SrcLangExt_PHP:    lang="php"; break;        // PHP4/5
       
   275     case SrcLangExt_D:      lang="d"; break;          // D
       
   276     case SrcLangExt_Java:   lang="java"; break;       // Java
       
   277     case SrcLangExt_JS:     lang="javascript"; break; // Javascript
       
   278     case SrcLangExt_Python: lang="python"; break;     // Python
       
   279     case SrcLangExt_F90:    lang="fortran"; break;    // Fortran
       
   280     case SrcLangExt_VHDL:   lang="vhdl"; break;       // VHDL
       
   281     case SrcLangExt_XML:    lang="xml"; break;        // DBUS XML
       
   282   }
       
   283 
       
   284   if (md)
       
   285   {
       
   286     if (!md->isLinkable()) return; // internal symbol
       
   287     if (context==0)
       
   288     {
       
   289       if (md->getGroupDef())
       
   290         context = md->getGroupDef();
       
   291       else if (md->getFileDef())
       
   292         context = md->getFileDef();
       
   293       if (context==0) return; // should not happen
       
   294 
       
   295       switch (md->memberType())
       
   296       {
       
   297         case MemberDef::Define:
       
   298           type="macro"; break;
       
   299         case MemberDef::Function:
       
   300           if (cd && (cd->compoundType()==ClassDef::Interface ||
       
   301                      cd->compoundType()==ClassDef::Class))
       
   302           {
       
   303             if (md->isStatic())
       
   304               type="clm";         // class member
       
   305             else
       
   306               type="instm";       // instance member
       
   307           }
       
   308           else if (cd && cd->compoundType()==ClassDef::Protocol)
       
   309           {
       
   310             if (md->isStatic())
       
   311               type="intfcm";     // interface class member
       
   312             else
       
   313               type="intfm";      // interface member
       
   314           }
       
   315           else
       
   316             type="func";
       
   317           break;
       
   318         case MemberDef::Variable:
       
   319           type="data"; break;
       
   320         case MemberDef::Typedef:
       
   321           type="tdef"; break;
       
   322         case MemberDef::Enumeration:
       
   323           type="enum"; break;
       
   324         case MemberDef::EnumValue:
       
   325           type="econst"; break;
       
   326           //case MemberDef::Prototype:
       
   327           //  type="prototype"; break;
       
   328         case MemberDef::Signal:
       
   329           type="signal"; break;
       
   330         case MemberDef::Slot:
       
   331           type="slot"; break;
       
   332         case MemberDef::Friend:
       
   333           type="ffunc"; break;
       
   334         case MemberDef::DCOP:
       
   335           type="dcop"; break;
       
   336         case MemberDef::Property:
       
   337           if (cd && cd->compoundType()==ClassDef::Protocol) 
       
   338             type="intfp";         // interface property
       
   339           else 
       
   340             type="instp";         // instance property
       
   341           break;
       
   342         case MemberDef::Event:
       
   343           type="event"; break;
       
   344       }
       
   345       writeToken(m_tts,md,type,lang,scope,md->anchor());
       
   346     }
       
   347   }
       
   348   else if (context && context->isLinkable())
       
   349   {
       
   350     if (fd==0 && context->definitionType()==Definition::TypeFile)
       
   351     {
       
   352       fd = (FileDef*)context;
       
   353     }
       
   354     if (cd==0 && context->definitionType()==Definition::TypeClass)
       
   355     {
       
   356       cd = (ClassDef*)context;
       
   357     }
       
   358     if (nd==0 && context->definitionType()==Definition::TypeNamespace)
       
   359     {
       
   360       nd = (NamespaceDef*)context;
       
   361     }
       
   362     if (fd)
       
   363     {
       
   364       type="file";
       
   365     }
       
   366     else if (cd) 
       
   367     {
       
   368       scope = cd->qualifiedName();
       
   369       if (cd->isTemplate())
       
   370       {
       
   371         type="tmplt";
       
   372       }
       
   373       else if (cd->compoundType()==ClassDef::Protocol) 
       
   374       {
       
   375         type="intf";
       
   376         if (scope.right(2)=="-p") scope=scope.left(scope.length()-2);
       
   377       }
       
   378       else if (cd->compoundType()==ClassDef::Interface)
       
   379       {
       
   380         type="cl";
       
   381       }
       
   382       else if (cd->compoundType()==ClassDef::Category)
       
   383       {
       
   384         type="cat";
       
   385       }
       
   386       else 
       
   387       {
       
   388         type = "cl";
       
   389       }
       
   390       IncludeInfo *ii = cd->includeInfo();
       
   391       if (ii)
       
   392       {
       
   393         decl=ii->includeName;
       
   394         if (decl.isEmpty())
       
   395         {
       
   396           decl=ii->local;
       
   397         }
       
   398       }
       
   399     }
       
   400     else if (nd)
       
   401     {
       
   402       scope = nd->name();
       
   403       type = "ns";
       
   404     }
       
   405     if (m_scopes.find(context->getOutputFileBase())==0)
       
   406     {
       
   407       writeToken(m_tts,context,type,lang,0,0,decl);
       
   408       m_scopes.append(context->getOutputFileBase(),(void*)0x8);
       
   409     }
       
   410   }
       
   411 }
       
   412 
       
   413 void DocSets::writeToken(QTextStream &t,
       
   414                          const Definition *d,
       
   415                          const QCString &type,
       
   416                          const QCString &lang,
       
   417                          const char *scope,
       
   418                          const char *anchor,
       
   419                          const char *decl)
       
   420 {
       
   421   t << "  <Token>" << endl;
       
   422   t << "    <TokenIdentifier>" << endl;
       
   423   QString name = d->name();
       
   424   if (name.right(2)=="-p")  name=name.left(name.length()-2);
       
   425   t << "      <Name>" << convertToXML(name) << "</Name>" << endl;
       
   426   if (!lang.isEmpty())
       
   427   {
       
   428     t << "      <APILanguage>" << lang << "</APILanguage>" << endl;
       
   429   }
       
   430   if (!type.isEmpty())
       
   431   {
       
   432     t << "      <Type>" << type << "</Type>" << endl;
       
   433   }
       
   434   if (scope)
       
   435   {
       
   436     t << "      <Scope>" << convertToXML(scope) << "</Scope>" << endl;
       
   437   }
       
   438   t << "    </TokenIdentifier>" << endl;
       
   439   t << "    <Path>" << d->getOutputFileBase() 
       
   440                     << Doxygen::htmlFileExtension << "</Path>" << endl;
       
   441   if (anchor)
       
   442   {
       
   443     t << "    <Anchor>" << anchor << "</Anchor>" << endl;
       
   444   }
       
   445   QCString tooltip = d->briefDescriptionAsTooltip();
       
   446   if (!tooltip.isEmpty())
       
   447   {
       
   448     t << "    <Abstract>" << convertToXML(tooltip) << "</Abstract>" << endl;
       
   449   }
       
   450   if (decl)
       
   451   {
       
   452     t << "    <DeclaredIn>" << convertToXML(decl) << "</DeclaredIn>" << endl;
       
   453   }
       
   454   t << "  </Token>" << endl;
       
   455 }
       
   456 
       
   457 void DocSets::addIndexFile(const char *name)
       
   458 {
       
   459   (void)name;
       
   460 }
       
   461