/***************************************************************************
* Copyright ( C ) 2004 by Alexander Dymo *
* cloudtemple @ mksat . net *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , write to the *
* Free Software Foundation , Inc . , *
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "docdoxygenplugin.h"
# include <unistd.h>
# include <tqdom.h>
# include <tqfile.h>
# include <tqfileinfo.h>
# include <tqdialog.h>
# include <tqregexp.h>
# include <tqvaluestack.h>
# include <kurl.h>
# include <kaboutdata.h>
# include <kconfig.h>
# include <klocale.h>
# include <kstandarddirs.h>
# include <urlutil.h>
# include <kdevgenericfactory.h>
# include <kdevplugininfo.h>
# include "../../../../config.h"
class DoxyDocumentationCatalogItem : public DocumentationCatalogItem
{
public :
DoxyDocumentationCatalogItem ( const TQString & origUrl , DocumentationPlugin * plugin ,
KListView * parent , const TQString & name )
: DocumentationCatalogItem ( plugin , parent , name ) , m_origUrl ( origUrl )
{
}
DoxyDocumentationCatalogItem ( const TQString & origUrl , DocumentationPlugin * plugin ,
DocumentationItem * parent , const TQString & name )
: DocumentationCatalogItem ( plugin , parent , name ) , m_origUrl ( origUrl )
{
}
TQString origUrl ( ) const { return m_origUrl ; }
private :
TQString m_origUrl ;
} ;
static const KDevPluginInfo data ( " docdoxygenplugin " ) ;
typedef KDevGenericFactory < DocDoxygenPlugin > DocDoxygenPluginFactory ;
K_EXPORT_COMPONENT_FACTORY ( libdocdoxygenplugin , DocDoxygenPluginFactory ( data ) )
DocDoxygenPlugin : : DocDoxygenPlugin ( TQObject * parent , const char * name , const TQStringList )
: DocumentationPlugin ( DocDoxygenPluginFactory : : instance ( ) - > config ( ) , parent , name )
{
setCapabilities ( Index | FullTextSearch | ProjectDocumentation | CustomDocumentationTitles ) ;
autoSetup ( ) ;
}
DocDoxygenPlugin : : ~ DocDoxygenPlugin ( )
{
}
TQPair < KFile : : Mode , TQString > DocDoxygenPlugin : : catalogLocatorProps ( )
{
return TQPair < KFile : : Mode , TQString > ( KFile : : File , " index.html *.tag " ) ;
}
TQString DocDoxygenPlugin : : catalogTitle ( const TQString & url )
{
TQFileInfo fi ( url ) ;
if ( ! fi . exists ( ) )
return TQString ( ) ;
if ( fi . extension ( false ) = = " html " )
{
TQFile f ( url ) ;
if ( ! f . open ( IO_ReadOnly ) )
return TQString ( ) ;
TQTextStream ts ( & f ) ;
TQString contents = ts . read ( ) ;
TQRegExp re ( " .*<title>(.*) < / title > . * " ) ;
re . setCaseSensitive ( false ) ;
re . search ( contents ) ;
return re . cap ( 1 ) ;
}
else if ( fi . extension ( false ) = = " tag " )
{
TQFile * f = 0 ;
TQFile f1 ( fi . dirPath ( true ) + " /html/index.html " ) ;
if ( f1 . open ( IO_ReadOnly ) )
f = & f1 ;
TQFile f2 ( fi . dirPath ( true ) + " /index.html " ) ;
if ( f2 . open ( IO_ReadOnly ) )
f = & f2 ;
if ( f ! = 0 )
{
TQTextStream ts ( f ) ;
TQString contents = ts . read ( ) ;
TQRegExp re ( " .*<title>(.*) < / title > . * " ) ;
re . setCaseSensitive ( false ) ;
re . search ( contents ) ;
return re . cap ( 1 ) ;
}
}
return TQString ( ) ;
}
TQString DocDoxygenPlugin : : pluginName ( ) const
{
return i18n ( " Doxygen Documentation Collection " ) ;
}
TQStringList DocDoxygenPlugin : : fullTextSearchLocations ( )
{
TQStringList locs ;
TQMap < TQString , TQString > entryMap = config - > entryMap ( " Locations " ) ;
for ( TQMap < TQString , TQString > : : const_iterator it = entryMap . begin ( ) ;
it ! = entryMap . end ( ) ; + + it )
{
config - > setGroup ( " Search Settings " ) ;
if ( config - > readBoolEntry ( it . key ( ) , false ) )
{
config - > setGroup ( " Locations " ) ;
TQFileInfo fi ( config - > readPathEntry ( it . key ( ) ) ) ;
locs < < fi . dirPath ( true ) ;
}
}
return locs ;
}
void DocDoxygenPlugin : : setCatalogURL ( DocumentationCatalogItem * item )
{
if ( item - > url ( ) . url ( ) . endsWith ( " tag " ) )
{
TQFileInfo fi ( item - > url ( ) . directory ( false ) + " html/index.html " ) ;
if ( fi . exists ( ) )
{
item - > setURL ( KURL : : fromPathOrURL ( fi . absFilePath ( ) ) ) ;
return ;
}
TQFileInfo fi2 ( item - > url ( ) . directory ( false ) + " index.html " ) ;
if ( fi2 . exists ( ) )
{
item - > setURL ( KURL : : fromPathOrURL ( fi2 . absFilePath ( ) ) ) ;
return ;
}
item - > setURL ( KURL ( ) ) ;
}
}
bool DocDoxygenPlugin : : needRefreshIndex ( DocumentationCatalogItem * item )
{
DoxyDocumentationCatalogItem * doxyItem = dynamic_cast < DoxyDocumentationCatalogItem * > ( item ) ;
if ( ! doxyItem )
return false ;
TQFileInfo fi ( doxyItem - > origUrl ( ) ) ;
config - > setGroup ( " Index " ) ;
if ( fi . lastModified ( ) > config - > readDateTimeEntry ( item - > text ( 0 ) , new TQDateTime ( ) ) )
{
kdDebug ( ) < < " need rebuild index for " < < item - > text ( 0 ) < < endl ;
config - > writeEntry ( item - > text ( 0 ) , fi . lastModified ( ) ) ;
return true ;
}
else
return false ;
}
void DocDoxygenPlugin : : autoSetupPlugin ( )
{
autoSetupDocs ( KDELIBS_DOXYDIR , " en/kdelibs-apidocs " , " The KDE API Reference (The KDE API Reference) " ) ;
autoSetupDocs ( " " , " en/kdevelop-apidocs " , " The KDevelop Platform API Documentation (KDevelop) " ) ;
}
void DocDoxygenPlugin : : autoSetupDocs ( const TQString & defaultDir , const TQString & searchDir ,
const TQString & name )
{
TQString doxyDocDir ( defaultDir ) ;
doxyDocDir = URLUtil : : envExpand ( doxyDocDir ) ;
if ( doxyDocDir . isEmpty ( ) )
{
TQStringList apiDirs = DocDoxygenPluginFactory : : instance ( ) - > dirs ( ) - > findDirs ( " html " , searchDir ) ;
for ( TQStringList : : const_iterator it = apiDirs . begin ( ) ; it ! = apiDirs . end ( ) ; + + it )
{
doxyDocDir = * it ;
TQString indexFile = doxyDocDir + " index.html " ;
if ( TQFile : : exists ( indexFile ) )
{
doxyDocDir = doxyDocDir + " / " + searchDir ;
break ;
}
doxyDocDir = " " ;
}
}
if ( ! doxyDocDir . isEmpty ( ) )
{
config - > setGroup ( " Search Settings " ) ;
config - > writeEntry ( name , true ) ;
config - > setGroup ( " Index Settings " ) ;
config - > writeEntry ( name , true ) ;
config - > setGroup ( " Locations " ) ;
config - > writePathEntry ( name , doxyDocDir + TQString ( " /index.html " ) ) ;
}
}
void DocDoxygenPlugin : : createIndex ( IndexBox * index , DocumentationCatalogItem * item )
{
TQFileInfo fi ( item - > url ( ) . path ( ) ) ;
if ( ! fi . exists ( ) )
return ;
DoxyDocumentationCatalogItem * doxyItem = dynamic_cast < DoxyDocumentationCatalogItem * > ( item ) ;
if ( ! doxyItem )
return ;
//doxygen documentation mode (if catalog points to a .tag)
if ( doxyItem - > origUrl ( ) . endsWith ( " tag " ) )
{
TQString htmlUrl ;
TQFileInfo fi2 ( item - > url ( ) . directory ( false ) + " index.html " ) ;
if ( fi2 . exists ( ) )
htmlUrl = fi2 . dirPath ( true ) + " / " ;
TQFileInfo fi ( item - > url ( ) . directory ( false ) + " html/index.html " ) ;
if ( fi . exists ( ) )
htmlUrl = fi . dirPath ( true ) + " / " ;
createBookIndex ( doxyItem - > origUrl ( ) , index , item , htmlUrl ) ;
}
//KDE doxygen documentation mode (if catalog points to a index.html)
TQDir d ;
TQValueStack < TQString > dirStack ;
dirStack . push ( fi . dirPath ( true ) ) ;
do {
d . setPath ( dirStack . pop ( ) ) ;
if ( ! d . exists ( ) )
continue ;
const TQFileInfoList * dirEntries = d . entryInfoList ( ) ;
if ( ! dirEntries ) continue ;
TQPtrListIterator < TQFileInfo > it ( * dirEntries ) ;
for ( ; it . current ( ) ; + + it )
{
TQString fileName = it . current ( ) - > fileName ( ) ;
if ( fileName = = " . " | | fileName = = " .. " | | fileName = = " common " | | fileName = = " html " )
continue ;
if ( it . current ( ) - > isDir ( ) )
dirStack . push ( it . current ( ) - > absFilePath ( ) ) ;
}
if ( TQFile : : exists ( d . absPath ( ) + " /html/index.html " ) )
createBookIndex ( d . absPath ( ) + " / " + d . dirName ( ) + " .tag " , index , item ) ;
} while ( ! dirStack . isEmpty ( ) ) ;
}
void DocDoxygenPlugin : : createTOC ( DocumentationCatalogItem * item )
{
TQFileInfo fi ( item - > url ( ) . path ( ) ) ;
if ( ! fi . exists ( ) )
return ;
DoxyDocumentationCatalogItem * doxyItem = dynamic_cast < DoxyDocumentationCatalogItem * > ( item ) ;
if ( ! doxyItem )
return ;
//doxygen documentation mode (if catalog points to a .tag)
if ( doxyItem - > origUrl ( ) . endsWith ( " tag " ) )
{
TQString htmlUrl ;
TQFileInfo fi2 ( item - > url ( ) . directory ( false ) + " index.html " ) ;
if ( fi2 . exists ( ) )
htmlUrl = fi2 . dirPath ( true ) + " / " ;
TQFileInfo fi ( item - > url ( ) . directory ( false ) + " html/index.html " ) ;
if ( fi . exists ( ) )
htmlUrl = fi . dirPath ( true ) + " / " ;
if ( ! htmlUrl . isEmpty ( ) )
createBookTOC ( item , doxyItem - > origUrl ( ) , htmlUrl ) ;
}
//KDE doxygen documentation mode (if catalog points to a index.html)
TQDir d ;
TQValueStack < TQString > dirStack ;
dirStack . push ( fi . dirPath ( true ) ) ;
do {
d . setPath ( dirStack . pop ( ) ) ;
if ( ! d . exists ( ) )
continue ;
const TQFileInfoList * dirEntries = d . entryInfoList ( ) ;
if ( ! dirEntries ) continue ;
TQPtrListIterator < TQFileInfo > it ( * dirEntries ) ;
for ( ; it . current ( ) ; + + it )
{
TQString fileName = it . current ( ) - > fileName ( ) ;
if ( fileName = = " . " | | fileName = = " .. " | | fileName = = " common " | | fileName = = " html " )
continue ;
if ( it . current ( ) - > isDir ( ) )
dirStack . push ( it . current ( ) - > absFilePath ( ) ) ;
}
if ( TQFile : : exists ( d . absPath ( ) + " /html/index.html " ) )
{
DocumentationItem * docItem = new DocumentationItem ( DocumentationItem : : Book , item , d . dirName ( ) ) ;
docItem - > setURL ( KURL ( d . absPath ( ) + " /html/index.html " ) ) ;
docItem - > setExpandable ( true ) ;
createBookTOC ( docItem ) ;
}
} while ( ! dirStack . isEmpty ( ) ) ;
}
DocumentationCatalogItem * DocDoxygenPlugin : : createCatalog ( KListView * contents , const TQString & title , const TQString & url )
{
kdDebug ( ) < < " DocDoxygenPlugin::createCatalog: url= " < < url < < endl ;
DocumentationCatalogItem * item = new DoxyDocumentationCatalogItem ( url , this , contents , title ) ;
item - > setURL ( url ) ;
return item ;
}
void DocDoxygenPlugin : : createBookTOC ( DocumentationItem * item , const TQString & tagUrl , const TQString & baseHtmlUrl )
{
TQString tagName ;
if ( tagUrl . isEmpty ( ) )
tagName = item - > url ( ) . upURL ( ) . directory ( false ) + item - > text ( 0 ) + " .tag " ;
else
tagName = tagUrl ;
TQString baseUrl ;
if ( baseHtmlUrl . isEmpty ( ) )
baseUrl = item - > url ( ) . directory ( false ) ;
else
baseUrl = baseHtmlUrl ;
//@todo list html files in the directory if tag was not found
if ( ! TQFile : : exists ( tagName ) )
return ;
TQStringList tagFileList ;
if ( tagName . endsWith ( " .tag " ) )
tagFileList = tagFiles ( TQFileInfo ( tagName ) . dirPath ( ) + " / " ) ;
else
tagFileList + = tagName ;
TQStringList : : ConstIterator end = tagFileList . constEnd ( ) ;
for ( TQStringList : : ConstIterator it = tagFileList . constBegin ( ) ; it ! = end ; + + it )
{
TQFile f ( * it ) ;
if ( ! f . open ( IO_ReadOnly ) )
{
kdDebug ( 9002 ) < < " Could not open tag file: " < < f . name ( ) < < endl ;
return ;
}
TQDomDocument dom ;
if ( ! dom . setContent ( & f ) | | dom . documentElement ( ) . nodeName ( ) ! = " tagfile " )
{
kdDebug ( 9002 ) < < " No valid tag file " < < endl ;
return ;
}
f . close ( ) ;
TQDomElement docEl = dom . documentElement ( ) ;
TQDomElement childEl = docEl . lastChild ( ) . toElement ( ) ;
while ( ! childEl . isNull ( ) )
{
if ( childEl . tagName ( ) = = " compound " & & childEl . attribute ( " kind " ) = = " class " )
{
TQString classname = childEl . namedItem ( " name " ) . firstChild ( ) . toText ( ) . data ( ) ;
TQString filename = childEl . namedItem ( " filename " ) . firstChild ( ) . toText ( ) . data ( ) ;
if ( TQFile : : exists ( baseUrl + filename ) )
{
DocumentationItem * docItem = new DocumentationItem ( DocumentationItem : : Document ,
item , classname ) ;
docItem - > setURL ( KURL ( baseUrl + filename ) ) ;
}
}
childEl = childEl . previousSibling ( ) . toElement ( ) ;
}
}
}
void DocDoxygenPlugin : : createBookIndex ( const TQString & tagfile , IndexBox * index , DocumentationCatalogItem * item , const TQString & baseHtmlUrl )
{
TQString tagName = tagfile ;
kdDebug ( ) < < tagfile < < endl ;
if ( ! TQFile : : exists ( tagName ) )
return ;
TQString prefix = baseHtmlUrl . isEmpty ( ) ? KURL ( tagfile ) . directory ( false ) + " html/ " : baseHtmlUrl ;
TQStringList tagFileList = tagFiles ( TQFileInfo ( tagName ) . dirPath ( ) + " / " ) ;
TQStringList : : ConstIterator end = tagFileList . constEnd ( ) ;
for ( TQStringList : : ConstIterator it = tagFileList . constBegin ( ) ; it ! = end ; + + it )
{
TQFile f ( * it ) ;
if ( ! f . open ( IO_ReadOnly ) )
{
kdDebug ( 9002 ) < < " Could not open tag file: " < < f . name ( ) < < endl ;
return ;
}
TQDomDocument dom ;
if ( ! dom . setContent ( & f ) | | dom . documentElement ( ) . nodeName ( ) ! = " tagfile " )
{
kdDebug ( 9002 ) < < " No valid tag file " < < endl ;
return ;
}
f . close ( ) ;
TQDomElement docEl = dom . documentElement ( ) ;
createIndexFromTag ( dom , index , item , docEl , prefix ) ;
}
}
void DocDoxygenPlugin : : createIndexFromTag ( TQDomDocument & dom , IndexBox * index ,
DocumentationCatalogItem * item , TQDomElement & parentEl , const TQString & prefix )
{
TQDomElement docEl = parentEl ;
TQDomElement childEl = docEl . firstChild ( ) . toElement ( ) ;
while ( ! childEl . isNull ( ) )
{
if ( childEl . tagName ( ) = = " compound " & &
( ( childEl . attribute ( " kind " ) = = " class " )
| | ( childEl . attribute ( " kind " ) = = " struct " )
| | ( childEl . attribute ( " kind " ) = = " namespace " ) ) )
{
TQString classname = childEl . namedItem ( " name " ) . firstChild ( ) . toText ( ) . data ( ) ;
TQString filename = childEl . namedItem ( " filename " ) . firstChild ( ) . toText ( ) . data ( ) ;
IndexItemProto * indexItem = new IndexItemProto ( this , item , index , classname ,
i18n ( " %1 Class Reference " ) . tqarg ( classname ) ) ;
indexItem - > addURL ( KURL ( prefix + filename ) ) ;
createIndexFromTag ( dom , index , item , childEl , prefix + filename ) ;
}
else if ( ( childEl . tagName ( ) = = " member " ) & &
( ( childEl . attribute ( " kind " ) = = " function " )
| | ( childEl . attribute ( " kind " ) = = " slot " )
| | ( childEl . attribute ( " kind " ) = = " signal " ) ) )
{
TQString classname = parentEl . namedItem ( " name " ) . firstChild ( ) . toText ( ) . data ( ) ;
TQString membername = childEl . namedItem ( " name " ) . firstChild ( ) . toText ( ) . data ( ) ;
TQString anchor = childEl . namedItem ( " anchor " ) . firstChild ( ) . toText ( ) . data ( ) ;
TQString arglist = childEl . namedItem ( " arglist " ) . firstChild ( ) . toText ( ) . data ( ) ;
if ( classname ! = membername )
{
IndexItemProto * indexItem = new IndexItemProto ( this , item , index , membername , i18n ( " %1::%2%3 Member Reference " ) . tqarg ( classname ) . tqarg ( membername ) . tqarg ( arglist ) ) ;
indexItem - > addURL ( KURL ( prefix + " # " + anchor ) ) ;
}
}
childEl = childEl . nextSibling ( ) . toElement ( ) ;
}
}
ProjectDocumentationPlugin * DocDoxygenPlugin : : projectDocumentationPlugin ( ProjectDocType type )
{
if ( type = = APIDocs )
return new ProjectDocumentationPlugin ( this , type ) ;
return DocumentationPlugin : : projectDocumentationPlugin ( type ) ;
}
TQStringList DocDoxygenPlugin : : tagFiles ( const TQString & path , int level )
{
TQStringList r ;
TQDir dir ( path ) ;
if ( level > 10 ) return r ;
if ( ! dir . isReadable ( ) ) return r ;
if ( ! dir . exists ( ) ) return r ;
TQStringList dirList ;
TQStringList fileList ;
TQStringList : : Iterator it ;
dir . setFilter ( TQDir : : Dirs ) ;
dirList = dir . entryList ( ) ;
dirList . remove ( " . " ) ;
dirList . remove ( " .. " ) ;
dir . setFilter ( TQDir : : Files | TQDir : : Hidden | TQDir : : System ) ;
fileList = dir . entryList ( ) ;
TQStringList : : Iterator end = dirList . end ( ) ;
for ( it = dirList . begin ( ) ; it ! = end ; + + it )
{
TQString name = * it ;
if ( TQFileInfo ( dir , * it ) . isSymLink ( ) )
continue ;
r + = tagFiles ( path + name + " / " , level + 1 ) ;
}
TQStringList : : Iterator fend = fileList . end ( ) ;
for ( it = fileList . begin ( ) ; it ! = fend ; + + it )
{
TQString name = * it ;
TQFileInfo fi ( dir , * it ) ;
if ( fi . isSymLink ( ) | | ! fi . isFile ( ) )
continue ;
if ( TQDir : : match ( TQString ( " *.tag " ) , name ) )
r + = ( path + name ) ;
}
return r ;
}
# include "docdoxygenplugin.moc"