00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "docindexdlg.h"
00013
00014 #include <qapplication.h>
00015 #include <qcheckbox.h>
00016 #include <qfile.h>
00017 #include <qfileinfo.h>
00018 #include <qlabel.h>
00019 #include <qlayout.h>
00020 #include <qpushbutton.h>
00021 #include <qvbuttongroup.h>
00022 #include <qregexp.h>
00023 #include <kbuttonbox.h>
00024 #include <kcombobox.h>
00025 #include <kdebug.h>
00026 #include <kdialog.h>
00027 #include <kglobal.h>
00028 #include <kinstance.h>
00029 #include <klocale.h>
00030 #include <kmessagebox.h>
00031 #include <kstandarddirs.h>
00032 #include <kprocess.h>
00033 #include <kdeversion.h>
00034 #include <kstdguiitem.h>
00035
00036 #include "kdevcore.h"
00037 #include "kdevpartcontroller.h"
00038 #include "domutil.h"
00039
00040 #include "misc.h"
00041 #include "doctreeviewfactory.h"
00042 #include "doctreeviewpart.h"
00043
00044
00045 DocIndexDialog::DocIndexDialog(DocTreeViewPart *part, QWidget *parent, const char *name)
00046 : QDialog(parent, name)
00047 {
00048 setCaption(i18n("Documentation Index"));
00049
00050 QLabel *term_label = new QLabel(i18n("Search term:"), this);
00051
00052 term_combo = new KComboBox(true, this);
00053 term_combo->setFocus();
00054 QFontMetrics fm(fontMetrics());
00055 term_combo->setMinimumWidth(fm.width('X')*40);
00056
00057 QApplication::setOverrideCursor(waitCursor);
00058
00059 readKDocIndex();
00060
00061 KStandardDirs *dirs = DocTreeViewFactory::instance()->dirs();
00062 QStringList books = dirs->findAllResources("docindices", QString::null, false, true);
00063
00064 QStringList::Iterator bit;
00065 for (bit = books.begin(); bit != books.end(); ++bit)
00066 readIndexFromFile(*bit);
00067
00068 QApplication::restoreOverrideCursor();
00069
00070 QVButtonGroup *book_group = new QVButtonGroup(this);
00071 book_group->setExclusive(false);
00072
00073 QPtrListIterator<DocIndex> iit(indices);
00074 for (; iit.current(); ++iit) {
00075 QCheckBox *box = new QCheckBox(iit.current()->title, book_group);
00076 box->setChecked(true);
00077 books_boxes.append(box);
00078 connect( box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged()) );
00079 }
00080
00081 QVButtonGroup *category_group = new QVButtonGroup(this);
00082 category_group->setExclusive(false);
00083
00084 concept_box = new QCheckBox(i18n("&Concept index"), category_group);
00085 concept_box->setChecked(true);
00086 ident_box = new QCheckBox(i18n("&Identifier index"), category_group);
00087 ident_box->setChecked(true);
00088 file_box = new QCheckBox(i18n("&File index"), category_group);
00089 file_box->setChecked(true);
00090
00091 connect( concept_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged()) );
00092 connect( ident_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged()) );
00093 connect( file_box, SIGNAL(toggled(bool)), this, SLOT(choiceChanged()) );
00094
00095 #if 0
00096 QFrame *frame = new QFrame(this);
00097 frame->setFrameStyle(QFrame::HLine | QFrame::Sunken);
00098 layout->addWidget(frame, 0);
00099 #endif
00100
00101 KButtonBox *buttonbox = new KButtonBox(this);
00102 buttonbox->addStretch();
00103 #if KDE_IS_VERSION( 3, 2, 90 )
00104 QPushButton *ok_button = buttonbox->addButton(KStdGuiItem::ok());
00105 QPushButton *cancel_button = buttonbox->addButton(KStdGuiItem::cancel());
00106 #else
00107 QPushButton *ok_button = buttonbox->addButton(i18n("&OK"));
00108 QPushButton *cancel_button = buttonbox->addButton(i18n("Cancel"));
00109 #endif
00110
00111 ok_button->setDefault(true);
00112 connect( ok_button, SIGNAL(clicked()), this, SLOT(accept()) );
00113 connect( cancel_button, SIGNAL(clicked()), this, SLOT(reject()) );
00114 buttonbox->layout();
00115
00116 QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint());
00117 layout->addWidget(term_label, 0);
00118 layout->addWidget(term_combo, 0);
00119 layout->addWidget(book_group);
00120 layout->addWidget(category_group);
00121 layout->addWidget(buttonbox, 0);
00122
00123 indices.setAutoDelete(true);
00124 m_part = part;
00125 choiceChanged();
00126
00127 if (m_part->project())
00128 readConfig();
00129 }
00130
00131
00132 DocIndexDialog::~DocIndexDialog()
00133 {}
00134
00135
00136 void DocIndexDialog::projectChanged()
00137 {
00138 if (m_part->project())
00139 readConfig();
00140 }
00141
00142
00143 void DocIndexDialog::lookup(const QString &str)
00144 {
00145 term_combo->lineEdit()->setText(str);
00146 }
00147
00148
00149 void DocIndexDialog::readConfig()
00150 {
00151 QDomDocument &dom = *m_part->projectDom();
00152 QDomElement docEl = dom.documentElement();
00153 QDomElement doctreeviewEl = docEl.namedItem("kdevdoctreeview").toElement();
00154
00155 QStringList indexbooks;
00156 QDomElement indexbooksEl = doctreeviewEl.namedItem("indexbooks").toElement();
00157 QDomElement bookEl = indexbooksEl.firstChild().toElement();
00158 while (!bookEl.isNull()) {
00159 if (bookEl.tagName() == "book")
00160 indexbooks << bookEl.firstChild().toText().data();
00161 bookEl = bookEl.nextSibling().toElement();
00162 }
00163
00164 QPtrListIterator<QCheckBox> cit(books_boxes);
00165 QPtrListIterator<DocIndex> iit(indices);
00166 for (; cit.current() && iit.current(); ++cit,++iit)
00167 (*cit)->setChecked(indexbooks.isEmpty() || indexbooks.contains(iit.current()->indexName));
00168
00169 concept_box->setChecked(DomUtil::readBoolEntry(dom, "/kdevdoctreeview/categories/concept"));
00170 ident_box->setChecked(DomUtil::readBoolEntry(dom, "/kdevdoctreeview/categories/identifier"));
00171 file_box->setChecked(DomUtil::readBoolEntry(dom, "/kdevdoctreeview/categories/file"));
00172 }
00173
00174
00175 void DocIndexDialog::storeConfig()
00176 {
00177 QDomDocument &dom = *m_part->projectDom();
00178 QDomElement docEl = dom.documentElement();
00179 QDomElement doctreeviewEl = docEl.namedItem("kdevdoctreeview").toElement();
00180
00181 QDomElement indexbooksEl = doctreeviewEl.namedItem("indexbooks").toElement();
00182 if (indexbooksEl.isNull()) {
00183 indexbooksEl = dom.createElement("indexbooks");
00184 doctreeviewEl.appendChild(indexbooksEl);
00185 }
00186
00187
00188 while (!indexbooksEl.firstChild().isNull())
00189 indexbooksEl.removeChild(indexbooksEl.firstChild());
00190
00191 QPtrListIterator<QCheckBox> cit(books_boxes);
00192 QPtrListIterator<DocIndex> iit(indices);
00193 for (; cit.current() && iit.current(); ++cit,++iit)
00194 if ((*cit)->isChecked()) {
00195 QDomElement bookEl = dom.createElement("book");
00196 bookEl.appendChild(dom.createTextNode((*iit)->indexName));
00197 indexbooksEl.appendChild(bookEl);
00198 kdDebug() << "Appending " << ((*iit)->indexName) << endl;
00199 }
00200
00201 DomUtil::writeBoolEntry(dom, "/kdevdoctreeview/categories/concept", concept_box->isChecked());
00202 DomUtil::writeBoolEntry(dom, "/kdevdoctreeview/categories/identifier", ident_box->isChecked());
00203 DomUtil::writeBoolEntry(dom, "/kdevdoctreeview/categories/file", file_box->isChecked());
00204 }
00205
00206
00207 void DocIndexDialog::readKDocIndex()
00208 {
00209 DocIndex *index = new DocIndex;
00210 indices.append(index);
00211
00212 index->indexName = "qt";
00213 index->title = i18n("Qt/KDE API");
00214
00215 QStringList itemNames, fileNames, hiddenNames;
00216 DocTreeViewTool::getAllLibraries(&itemNames, &fileNames);
00217 DocTreeViewTool::getHiddenLibraries(&hiddenNames);
00218
00219 QStringList::Iterator it;
00220 for (it = fileNames.begin(); it != fileNames.end(); ++it)
00221 if (!hiddenNames.contains(*it)) {
00222 FILE *f;
00223 if ((*it).right(3) != QString::fromLatin1(".gz")) {
00224 if ( (f = fopen(QFile::encodeName( *it ).data(), "r")) != 0) {
00225 readKDocEntryList(f, &index->identNames, &index->identUrls);
00226 fclose(f);
00227 }
00228 } else {
00229 QString cmd = "gzip -c -d ";
00230 #if (KDE_VERSION > 305)
00231 cmd += KProcess::quote(*it);
00232 #else
00233 cmd += KShellProcess::quote(*it);
00234 #endif
00235 cmd += " 2>/dev/null";
00236 if ( (f = popen(QFile::encodeName(cmd), "r")) != 0) {
00237 readKDocEntryList(f, &index->identNames, &index->identUrls);
00238 pclose(f);
00239 }
00240 }
00241 }
00242 }
00243
00244
00245 void DocIndexDialog::readKDocEntryList(FILE *f,
00246 QStringList *nameList, QStringList *urlList)
00247 {
00248 char buf[1024];
00249 int pos0;
00250 QString classname, membername, base, filename;
00251
00252 while (fgets(buf, sizeof buf, f)) {
00253 QString s = buf;
00254 if (s.left(pos0=11) == "<BASE URL=\"") {
00255 int pos2 = s.find("\">", pos0);
00256 if (pos2 != -1)
00257 base = s.mid(pos0, pos2-pos0);
00258 }
00259 else if (s.left(pos0=9) == "<C NAME=\"") {
00260 int pos1 = s.find("\" REF=\"", pos0);
00261 if (pos1 == -1)
00262 continue;
00263 int pos2 = s.find("\">", pos1+7);
00264 if (pos2 == -1)
00265 continue;
00266 classname = s.mid(pos0, pos1-pos0);
00267 filename = s.mid(pos1+7, pos2-(pos1+7));
00268 filename.replace(QRegExp("::"), "__");
00269 (*nameList) << classname;
00270 (*urlList) << (base + "/" + filename);
00271 }
00272 else if (s.left(pos0=9) == "<M NAME=\"" || s.left(pos0=10) == "<ME NAME=\"")
00273 {
00274 int pos1 = s.find("\" REF=\"", pos0);
00275 if (pos1 == -1)
00276 continue;
00277 int pos2 = s.find("\">", pos1+7);
00278 if (pos2 == -1)
00279 continue;
00280
00281
00282 membername = s.mid(pos0, pos1-pos0);
00283 filename = s.mid(pos1+7, pos2-(pos1+7));
00284 filename.replace(QRegExp("::"), "__");
00285 (*nameList) << (membername + " (" + classname + ")");
00286 (*urlList) << (base + "/" + filename);
00287 }
00288 }
00289 }
00290
00291
00292 void DocIndexDialog::readIndexFromFile(const QString &fileName)
00293 {
00294 QFileInfo fi(fileName);
00295 QString name = fi.baseName();
00296
00297 QFile f(fileName);
00298 if (!f.open(IO_ReadOnly)) {
00299 kdDebug(9002) << "Could not read doc index: " << fileName << endl;
00300 return;
00301 }
00302
00303 QDomDocument doc;
00304 if (!doc.setContent(&f) || doc.doctype().name() != "kdevelopindex") {
00305 kdDebug() << "Not a valid kdevelopindex file: " << fileName << endl;
00306 return;
00307 }
00308
00309 f.close();
00310
00311 kdDebug(9002) << "Parsing: " << fileName << endl;
00312
00313 DocIndex *index = new DocIndex;
00314 indices.append(index);
00315
00316 QDomElement docEl = doc.documentElement();
00317 QDomElement titleEl = docEl.namedItem("title").toElement();
00318 QDomElement baseEl = docEl.namedItem("base").toElement();
00319 QDomElement conceptEl = docEl.namedItem("conceptindex").toElement();
00320 QDomElement identEl = docEl.namedItem("identindex").toElement();
00321 QDomElement fileEl = docEl.namedItem("fileindex").toElement();
00322 index->indexName = name;
00323 index->title = titleEl.firstChild().toText().data();
00324 index->base = baseEl.attribute("href");
00325 if (!index->base.isEmpty())
00326 index->base += "/";
00327 readEntryList(conceptEl, &index->conceptNames, &index->conceptUrls);
00328 readEntryList(identEl, &index->identNames, &index->identUrls);
00329 readEntryList(fileEl, &index->fileNames, &index->fileUrls);
00330 }
00331
00332
00333 void DocIndexDialog::readEntryList(const QDomElement &el,
00334 QStringList *nameList, QStringList *urlList)
00335 {
00336 QDomElement childEl = el.firstChild().toElement();
00337 while (!childEl.isNull()) {
00338 if (childEl.tagName() == "entry") {
00339 nameList->append(childEl.attribute("name"));
00340 urlList->append(childEl.attribute("url"));
00341 }
00342
00343 childEl = childEl.nextSibling().toElement();
00344 }
00345 }
00346
00347
00348 void DocIndexDialog::accept()
00349 {
00350 QString term = term_combo->currentText();
00351 QString url;
00352 int pos;
00353
00354 if (term.isEmpty())
00355 return;
00356
00357 QPtrListIterator<QCheckBox> cit(books_boxes);
00358 QPtrListIterator<DocIndex> iit(indices);
00359 for (; cit.current() && iit.current(); ++cit,++iit)
00360 if ((*cit)->isChecked()) {
00361 if (concept_box->isChecked())
00362 if ( (pos = (*iit)->conceptNames.findIndex(term)) != -1) {
00363 kdDebug(9002) << "found in concept index of " << (*iit)->title << endl;
00364 url = (*iit)->base + (*iit)->conceptUrls[pos];
00365 break;
00366 }
00367 if (ident_box->isChecked())
00368 if ( (pos = (*iit)->identNames.findIndex(term)) != -1) {
00369 kdDebug(9002) << "found in ident index of " << (*iit)->title << endl;
00370 url = (*iit)->base + (*iit)->identUrls[pos];
00371 break;
00372 }
00373 if (file_box->isChecked())
00374 if ( (pos = (*iit)->fileNames.findIndex(term)) != -1) {
00375 kdDebug(9002) << "found in file index of " << (*iit)->title << endl;
00376 url = (*iit)->base + (*iit)->fileUrls[pos];
00377 break;
00378 }
00379 }
00380
00381 if (url.isEmpty()) {
00382 KMessageBox::sorry(this, i18n("Term not found in the indices."));
00383 return;
00384 }
00385
00386 m_part->partController()->showDocument(KURL(url));
00387
00388 if (m_part->project())
00389 storeConfig();
00390
00391 QDialog::accept();
00392 }
00393
00394
00395 void DocIndexDialog::choiceChanged()
00396 {
00397 QStringList completions;
00398
00399 QPtrListIterator<QCheckBox> cit(books_boxes);
00400 QPtrListIterator<DocIndex> iit(indices);
00401 for (; cit.current() && iit.current(); ++cit,++iit)
00402 if ((*cit)->isChecked()) {
00403 if (concept_box->isChecked())
00404 completions += (*iit)->conceptNames;
00405 if (ident_box->isChecked())
00406 completions += (*iit)->identNames;
00407 if (file_box->isChecked())
00408 completions += (*iit)->fileNames;
00409 }
00410
00411 term_combo->completionObject()->setItems(completions);
00412 }
00413 #include "docindexdlg.moc"