KDevelop API Documentation

parts/texttools/texttoolswidget.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2002 by Bernd Gehrmann * 00003 * bernd@kdevelop.org * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 ***************************************************************************/ 00011 00012 #include "texttoolswidget.h" 00013 00014 #include <qheader.h> 00015 #include <qregexp.h> 00016 #include <qtimer.h> 00017 #include <kdebug.h> 00018 #include <klocale.h> 00019 #include <kparts/part.h> 00020 #include <kpopupmenu.h> 00021 #include <ktexteditor/viewcursorinterface.h> 00022 #include <ktexteditor/selectioninterface.h> 00023 #include <ktexteditor/editinterface.h> 00024 00025 #include "kdevmainwindow.h" 00026 #include "kdevpartcontroller.h" 00027 #include "texttoolspart.h" 00028 00029 00030 class TextStructItem : public QListViewItem 00031 { 00032 public: 00033 TextStructItem(QListView *parent) 00034 : QListViewItem(parent) 00035 {} 00036 TextStructItem(QListViewItem *parent) 00037 : QListViewItem(parent) 00038 { 00039 QListViewItem *item = this; 00040 while (item->nextSibling()) 00041 item = item->nextSibling(); 00042 if (item != this) 00043 moveItem(item); 00044 } 00045 00046 QString text(int) const 00047 { 00048 return extra.isNull()? tag : QString("%1: %2").arg(tag).arg(extra); 00049 } 00050 TextStructItem *parentStructItem() 00051 { return static_cast<TextStructItem*>(parent()); } 00052 00053 QString tag; 00054 QString extra; 00055 int pos; 00056 int endpos; 00057 }; 00058 00059 00060 TextToolsWidget::TextToolsWidget(TextToolsPart *part, QWidget *parent, const char *name) 00061 : KListView(parent, name) 00062 { 00063 setResizeMode(QListView::LastColumn); 00064 setSorting(-1); 00065 header()->hide(); 00066 addColumn(QString::null); 00067 00068 m_part = part; 00069 00070 m_timer = new QTimer(this); 00071 connect( this, SIGNAL(mouseButtonPressed(int, QListViewItem*, const QPoint&, int)), 00072 this, SLOT(slotItemPressed(int,QListViewItem*)) ); 00073 // connect( this, SIGNAL(doubleClicked(QListViewItem*)), 00074 // this, SLOT(slotItemPressed(int,QListViewItem*)) ); 00075 connect( this, SIGNAL(returnPressed(QListViewItem*)), 00076 this, SLOT(slotReturnPressed(QListViewItem*)) ); 00077 connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), 00078 this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) ); 00079 } 00080 00081 00082 TextToolsWidget::~TextToolsWidget() 00083 {} 00084 00085 00086 void TextToolsWidget::slotItemPressed(int button, QListViewItem *item) 00087 { 00088 if (!item) 00089 return; 00090 00091 TextStructItem *tsitem = static_cast<TextStructItem*>(item); 00092 int searchedPos = tsitem->pos; 00093 int searchedEndpos = tsitem->endpos; 00094 kdDebug(9030) << "Searched pos " << searchedPos << ", " << searchedEndpos << endl; 00095 00096 int endline = 0; 00097 int endcol = 0; 00098 int line = 0; 00099 int col = 0; 00100 00101 int len = m_cachedText.length(); 00102 int pos = 0; 00103 while (pos < len) { 00104 if (pos == searchedPos) { 00105 line = endline; 00106 col = endcol; 00107 } 00108 if (pos == searchedEndpos) 00109 break; 00110 QChar ch = m_cachedText[pos]; 00111 if (ch == '\n') { 00112 ++endline; 00113 endcol = 0; 00114 } else { 00115 ++endcol; 00116 } 00117 ++pos; 00118 } 00119 00120 KParts::Part *rwpart 00121 = dynamic_cast<KParts::Part*>(m_part->partController()->activePart()); 00122 QWidget *view = m_part->partController()->activeWidget(); 00123 00124 KTextEditor::ViewCursorInterface *cursorIface 00125 = dynamic_cast<KTextEditor::ViewCursorInterface*>(view); 00126 if (cursorIface) { 00127 kdDebug(9030) << "set cursor " << line << ", " << col << endl; 00128 cursorIface->setCursorPosition(line, col); 00129 } 00130 00131 if (button == MidButton) { 00132 KTextEditor::SelectionInterface *selectionIface 00133 = dynamic_cast<KTextEditor::SelectionInterface*>(rwpart); 00134 if (selectionIface) { 00135 kdDebug(9030) << "set selection " << line << ", " << col 00136 << ", " << endline << ", " << endcol << endl; 00137 selectionIface->setSelection((int)line, (int)col, (int)endline, (int)endcol+1); 00138 } 00139 } 00140 00141 m_part->mainWindow()->lowerView(this); 00142 } 00143 00144 00145 void TextToolsWidget::slotReturnPressed(QListViewItem *item) 00146 { 00147 slotItemPressed(LeftButton, item); 00148 } 00149 00150 00151 void TextToolsWidget::slotContextMenu(KListView *, QListViewItem *item, const QPoint &) 00152 { 00153 if (!item) 00154 return; 00155 00156 #if 0 00157 KPopupMenu popup(i18n("Text Structure"), this); 00158 popup.exec(p); 00159 #endif 00160 } 00161 00162 00163 void TextToolsWidget::stop() 00164 { 00165 disconnect( m_timer ); 00166 m_relevantTags.clear(); 00167 m_emptyTags.clear(); 00168 m_cachedText = QString::null; 00169 } 00170 00171 00172 void TextToolsWidget::setMode(Mode mode, KParts::Part *part) 00173 { 00174 connect( part, SIGNAL(textChanged()), 00175 this, SLOT(startTimer()) ); 00176 m_editIface = dynamic_cast<KTextEditor::EditInterface*>(part); 00177 00178 switch (mode) { 00179 case HTML: 00180 m_relevantTags << "h1" << "h2" << "h3" << "h4" 00181 << "table" << "tr"; 00182 m_emptyTags << "br" << "hr" << "img" << "input" << "p" << "meta"; 00183 00184 connect( m_timer, SIGNAL(timeout()), 00185 this, SLOT(parseXML()) ); 00186 break; 00187 case Docbook: 00188 m_relevantTags << "chapter" << "sect1" << "sect2" 00189 << "para" << "formalpara"; 00190 connect( m_timer, SIGNAL(timeout()), 00191 this, SLOT(parseXML()) ); 00192 break; 00193 case LaTeX: 00194 connect( m_timer, SIGNAL(timeout()), 00195 this, SLOT(parseLaTeX()) ); 00196 break; 00197 default: ; 00198 } 00199 00200 m_timer->start(0, true); 00201 } 00202 00203 00204 void TextToolsWidget::startTimer() 00205 { 00206 kdDebug(9030) << "Starting parse timer" << endl; 00207 m_timer->start(1000, true); 00208 } 00209 00210 00211 void TextToolsWidget::parseXML() 00212 { 00213 kdDebug(9030) << "Starting to parse XML" << endl; 00214 clear(); 00215 QString text = m_editIface->text(); 00216 m_cachedText = text; 00217 00218 TextStructItem *currentItem = new TextStructItem(this); 00219 currentItem->tag = "Root"; 00220 currentItem->pos = -1; 00221 currentItem->endpos = -1; 00222 00223 int len = text.length(); 00224 for (int pos=0; pos+1 < len; ++pos) { 00225 QChar ch1 = text[pos]; 00226 QChar ch2 = text[pos+1]; 00227 00228 if (ch1 == '<' && ch2 == '?') { 00229 00230 // PHP and other similar stuff 00231 QString tag; 00232 int endpos = pos+2; 00233 bool foundspace = false; 00234 while (endpos+1 < len) { 00235 QChar ch3 = text[endpos]; 00236 QChar ch4 = text[endpos+1]; 00237 if ((ch3 == ' ' || ch3 == '\t' || ch3 == '\n') && !foundspace) { 00238 tag = text.mid(pos+2, endpos-pos-2).lower(); 00239 foundspace = true; 00240 } else if (ch3 == '?' && ch4 == '>') { 00241 if (!foundspace) 00242 tag = text.mid(pos+2, endpos-pos-2).lower(); 00243 break; 00244 } 00245 ++endpos; 00246 } 00247 00248 TextStructItem *item = new TextStructItem(currentItem); 00249 item->tag = "<?" + tag + "?>"; 00250 item->pos = pos; 00251 item->endpos = endpos+1; 00252 00253 pos = endpos+1; 00254 00255 } else if (ch1 == '<' && ch2 == '!') { 00256 00257 // Processing instructions like !DOCTYPE 00258 QString tag; 00259 int endpos = pos+2; 00260 bool foundspace = false; 00261 while (endpos+1 < len) { 00262 QChar ch3 = text[endpos]; 00263 if ((ch3 == ' ' || ch3 == '\t' || ch3 == '\n') && !foundspace) { 00264 tag = text.mid(pos+2, endpos-pos-2).lower(); 00265 foundspace = true; 00266 } else if (ch3 == '>') { 00267 if (!foundspace) 00268 tag = text.mid(pos+2, endpos-pos-2).lower(); 00269 break; 00270 } 00271 ++endpos; 00272 } 00273 00274 TextStructItem *item = new TextStructItem(currentItem); 00275 item->tag = "<!" + tag + ">"; 00276 item->pos = pos; 00277 item->endpos = endpos+1; 00278 00279 pos = endpos+1; 00280 00281 } else if (ch1 == '<' && ch2 == '/') { 00282 00283 QString tag; 00284 int endpos = pos+2; 00285 while (endpos < len) { 00286 QChar ch3 = text[endpos]; 00287 if (ch3 == '>') { 00288 tag = text.mid(pos+2, endpos-pos-2).lower(); 00289 break; 00290 } 00291 ++endpos; 00292 } 00293 00294 if (!m_relevantTags.contains(tag)) { 00295 pos = endpos; 00296 continue; 00297 } 00298 00299 TextStructItem *closingItem = currentItem; 00300 while (closingItem->parent() && closingItem->tag != tag) 00301 closingItem = closingItem->parentStructItem(); 00302 if (closingItem->parent()) { 00303 closingItem->endpos = endpos; 00304 currentItem = closingItem->parentStructItem(); 00305 } else { 00306 kdDebug(9030) << "found no opening tag " << tag << "." << endl; 00307 } 00308 00309 pos = endpos; 00310 00311 } else if (ch1 == '<') { 00312 00313 QString tag; 00314 int endpos = pos+1; 00315 bool foundspace = false; 00316 while (endpos < len) { 00317 QChar ch3 = text[endpos]; 00318 if ((ch3 == ' ' || ch3 == '\t' || ch3 == '\n') && !foundspace) { 00319 tag = text.mid(pos+1, endpos-pos-1).lower(); 00320 foundspace = true; 00321 } else if (ch3 == '>') { 00322 if (!foundspace) { 00323 tag = text.mid(pos+1, endpos-pos-1).lower(); 00324 } 00325 break; 00326 } 00327 ++endpos; 00328 } 00329 00330 if (!m_relevantTags.contains(tag)) { 00331 pos = endpos; 00332 continue; 00333 } 00334 00335 TextStructItem *item = new TextStructItem(currentItem); 00336 item->tag = tag; 00337 item->pos = pos; 00338 item->endpos = -1; 00339 00340 if (m_emptyTags.contains(tag)) 00341 item->endpos = endpos; 00342 else 00343 currentItem = item; 00344 pos = endpos; 00345 00346 } 00347 } 00348 00349 // firstChild()->setOpen(true); 00350 QListViewItemIterator it(this); 00351 for (; it.current(); ++it) 00352 it.current()->setOpen(true); 00353 } 00354 00355 00356 void TextToolsWidget::parseLaTeX() 00357 { 00358 kdDebug(9030) << "Starting to parse LaTeX" << endl; 00359 clear(); 00360 QString text = m_editIface->text(); 00361 m_cachedText = text; 00362 00363 TextStructItem *currentItem = new TextStructItem(this); 00364 currentItem->tag = "Root"; 00365 currentItem->pos = -1; 00366 currentItem->endpos = -1; 00367 00368 QString hierarchyLevels = "Root,chapter,section,subsection,subsubsection"; 00369 QRegExp re("\n[ \t]*s*\\\\(chapter|section|subsection|subsubsection)\\{([^}]*)\\}"); 00370 00371 int pos=0; 00372 for (;;) { 00373 pos = re.search(text, pos); 00374 if (pos == -1) 00375 break; 00376 QString tag = re.cap(1); 00377 QString title = re.cap(2); 00378 kdDebug(9030) << "Match with " << tag << " and title " << title << endl; 00379 int level = hierarchyLevels.find(tag); 00380 while (currentItem->parent() && level <= hierarchyLevels.find(currentItem->tag)) 00381 currentItem = currentItem->parentStructItem(); 00382 00383 TextStructItem *item = new TextStructItem(currentItem); 00384 item->tag = tag; 00385 item->extra = title; 00386 item->pos = pos+1; 00387 item->endpos = pos+re.matchedLength()-1; // lie 00388 00389 if (level > hierarchyLevels.find(currentItem->tag)) 00390 currentItem = item; 00391 00392 pos = pos+re.matchedLength(); 00393 } 00394 00395 QListViewItemIterator it(this); 00396 for (; it.current(); ++it) 00397 it.current()->setOpen(true); 00398 } 00399 00400 #include "texttoolswidget.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Oct 19 08:01:52 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003