/*************************************************************************** * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com * * Please do not use email address above for bug reports; see * * the README file * * * * 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 #include #include "kchmtreeviewitem.h" #include "kchmmainwindow.h" #include "kchmdialogchooseurlfromlist.h" #include "iconstorage.h" KCHMIndTocItem::KCHMIndTocItem( TQListViewItem * parent, TQListViewItem * after, TQString name, TQString aurl, int image) : TQListViewItem(parent, after, name), url(aurl), image_number(image) { } KCHMIndTocItem::KCHMIndTocItem( TQListView * parent, TQListViewItem * after, TQString name, TQString aurl, int image) : TQListViewItem(parent, after, name), url(aurl), image_number(image) { } const TQPixmap * KCHMIndTocItem::pixmap( int i ) const { int imagenum; if ( i || image_number == LCHMBookIcons::IMAGE_NONE || image_number == LCHMBookIcons::IMAGE_INDEX ) return 0; if ( firstChild () ) { if ( isOpen() ) imagenum = (image_number == LCHMBookIcons::IMAGE_AUTO) ? 1 : image_number; else imagenum = (image_number == LCHMBookIcons::IMAGE_AUTO) ? 0 : image_number + 1; } else imagenum = (image_number == LCHMBookIcons::IMAGE_AUTO) ? 10 : image_number; return ::mainWindow->chmFile()->getBookIconPixmap( imagenum ); } TQString KCHMIndTocItem::getUrl( ) const { if ( url.find ('|') == -1 ) return url; // Create a dialog with URLs, and show it, so user can select an URL he/she wants. TQStringList urls = TQStringList::split ('|', url); TQStringList titles; LCHMFile * xchm = ::mainWindow->chmFile(); for ( unsigned int i = 0; i < urls.size(); i++ ) { TQString title = xchm->getTopicByUrl (urls[i]); if ( !title ) { tqWarning ("Could not get item name for url '%s'", urls[i].ascii()); titles.push_back(TQString()); } else titles.push_back(title); } KCHMDialogChooseUrlFromList dlg (urls, titles, ::mainWindow); if ( dlg.exec() == TQDialog::Accepted ) return dlg.getSelectedItemUrl(); return TQString(); } void KCHMIndTocItem::paintBranches( TQPainter * p, const TQColorGroup & cg, int w, int y, int h ) { if ( image_number != LCHMBookIcons::IMAGE_INDEX ) TQListViewItem::paintBranches(p, cg, w, y, h); else { // Too bad that listView()->paintEmptyArea( p, TQRect( 0, 0, w, h ) ) is protected. // Taken from qt-x11-free-3.0.4/src/widgets/qlistview.cpp TQStyleOption opt( 0, 0 ); TQStyle::SFlags how = TQStyle::Style_Default | TQStyle::Style_Enabled; listView()->style().drawComplexControl( TQStyle::CC_ListView, p, listView(), TQRect( 0, 0, w, h ), cg, how, TQStyle::SC_ListView, TQStyle::SC_None, opt ); } } void KCHMIndTocItem::paintCell( TQPainter * p, const TQColorGroup & cg, int column, int width, int align ) { TQColorGroup newcg ( cg ); TQColor c = newcg.text(); if ( url.find ('|') != -1 ) newcg.setColor( TQColorGroup::Text, TQt::red ); else if ( url[0] == ':' ) newcg.setColor( TQColorGroup::Text, TQt::lightGray ); else { TQListViewItem::paintCell( p, cg, column, width, align ); return; } TQListViewItem::paintCell( p, newcg, column, width, align ); newcg.setColor( TQColorGroup::Text, c ); } void KCHMIndTocItem::setOpen( bool open ) { if ( image_number != LCHMBookIcons::IMAGE_INDEX || open ) TQListViewItem::setOpen (open); } void kchmFillListViewWithParsedData( TQListView * list, const TQValueVector< LCHMParsedEntry >& data, TQMap * map ) { TQValueVector< KCHMIndTocItem *> lastchild; TQValueVector< KCHMIndTocItem *> rootentry; if ( map ) map->clear(); list->clear(); for ( unsigned int i = 0; i < data.size(); i++ ) { unsigned int indent = data[i].indent; // Do we need to add another indent? if ( indent >= lastchild.size() ) { lastchild.resize( indent + 1 ); lastchild[indent] = 0; rootentry.resize( indent + 1 ); rootentry[indent] = 0; } // Create the node KCHMIndTocItem * item; TQString url = data[i].urls.join ("|"); if ( indent == 0 ) item = new KCHMIndTocItem( list, lastchild[indent], data[i].name, url, data[i].imageid ); else { // New non-root entry. It is possible (for some buggy CHMs) that there is no previous entry: previoous entry had indent 1, // and next entry has indent 3. Backtracking it up, creating missing entries. if ( rootentry[indent-1] == 0 ) tqFatal("Child entry indented as %d with no root entry!", indent); item = new KCHMIndTocItem( rootentry[indent-1], lastchild[indent], data[i].name, url, data[i].imageid ); } // Hack: if map is 0, we have index, so make it open if ( map ) { for ( unsigned int li = 0; li < data[i].urls.size(); li++ ) map->insert( data[i].urls[li], item ); } else item->setOpen( true ); lastchild[indent] = item; rootentry[indent] = item; } list->triggerUpdate(); /* KCHMMainTreeViewItem * item; if ( !root_indent_offset_set ) { root_indent_offset_set = true; root_indent_offset = indent; if ( root_indent_offset > 1 ) tqWarning("CHM has improper index; root indent offset is %d", root_indent_offset); } int real_indent = indent - root_indent_offset; TQString url = urls.join ("|"); if ( real_indent == 0 ) { // New root entry item = new KCHMMainTreeViewItem (tree, lastchild[real_indent], name, url, imagenum); DEBUGPARSER((": '%s', new rootentry %08X\n", name.ascii(), item)); } else { // New non-root entry if ( !rootentry[real_indent-1] ) tqFatal("CHMFile::ParseAndFillTopicsTree: child entry \"%s\" indented as %d with no root entry!", name.ascii(), real_indent); item = new KCHMMainTreeViewItem (rootentry[real_indent-1], lastchild[real_indent], name, url, imagenum); DEBUGPARSER((": '%s', indent %d, rootentry %08X, item %08X\n", name.ascii(), real_indent, rootentry[real_indent-1], item)); } lastchild[real_indent] = item; rootentry[real_indent] = item; if ( asIndex ) rootentry[real_indent]->setOpen(true); // There are no 'titles' in index file if ( add2treemap ) { for ( unsigned int li = 0; li < urls.size(); li++ ) m_treeUrlMap[urls[li]] = item; } } else { if ( !urls.isEmpty() ) tqDebug ("CHMFile::ParseAndFillTopicsTree: tag with url \"%s\" is parsed, but name is empty.", urls[0].ascii()); else tqDebug ("CHMFile::ParseAndFillTopicsTree: tag is parsed, but both name and url are empty."); } name = TQString(); urls.clear(); in_object = false; imagenum = defaultimagenum; } } else if ( tagword == "ul" ) // increase indent level { // Fix for buggy help files if ( ++indent >= MAX_NEST_DEPTH ) tqFatal("CHMFile::ParseAndFillTopicsTree: max nest depth (%d) is reached, error in help file", MAX_NEST_DEPTH); lastchild[indent] = 0; rootentry[indent] = 0; // This intended to fix
      , which was seen in some buggy chm files, // and brokes rootentry[indent-1] check int real_indent = indent - root_indent_offset; if ( real_indent > 1 && rootentry[real_indent - 1] == 0 && rootentry[real_indent - 2] != 0 ) { rootentry[real_indent - 1] = rootentry[real_indent - 2]; tqWarning("Broken CHM index/content: tree autocorrection enabled."); } DEBUGPARSER(("
        : new indent is %d, last rootentry was %08X\n", indent - root_indent_offset, rootentry[indent-1])); } else if ( tagword == "/ul" ) // decrease indent level { if ( --indent < root_indent_offset ) indent = root_indent_offset; rootentry[indent] = 0; DEBUGPARSER(("
      : new intent is %d\n", indent - root_indent_offset)); } pos = i; } return true; */ }