kdeui Library API Documentation

keditcl1.cpp

00001 /* This file is part of the KDE libraries 00002 00003 Copyright (C) 1997 Bernd Johannes Wuebben <wuebben@math.cornell.edu> 00004 Copyright (C) 2000 Waldo Bastian <bastian@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00019 Boston, MA 02111-1307, USA. 00020 */ 00021 00022 #include <qdragobject.h> 00023 #include <qpopupmenu.h> 00024 #include <qtextstream.h> 00025 #include <qtimer.h> 00026 00027 #include <kapplication.h> 00028 #include <kcursor.h> 00029 #include <kdebug.h> 00030 #include <kcmenumngr.h> 00031 #include <kfontdialog.h> 00032 #include <klocale.h> 00033 #include <kmessagebox.h> 00034 #include <kstdaccel.h> 00035 #include <kurldrag.h> 00036 00037 #include "keditcl.h" 00038 #include "keditcl.moc" 00039 00040 class KEdit::KEditPrivate 00041 { 00042 public: 00043 bool overwriteEnabled:1; 00044 bool posDirty:1; 00045 }; 00046 00047 00048 KEdit::KEdit(QWidget *_parent, const char *name) 00049 : QMultiLineEdit(_parent, name) 00050 { 00051 d = new KEditPrivate; 00052 d->overwriteEnabled = false; 00053 d->posDirty = true; 00054 00055 parent = _parent; 00056 00057 // set some defaults 00058 00059 line_pos = col_pos = 0; 00060 00061 srchdialog = NULL; 00062 replace_dialog= NULL; 00063 gotodialog = NULL; 00064 00065 setAcceptDrops(true); 00066 KCursor::setAutoHideCursor( this, true ); 00067 00068 connect(this, SIGNAL(cursorPositionChanged(int,int)), 00069 this, SLOT(slotCursorPositionChanged())); 00070 } 00071 00072 00073 KEdit::~KEdit() 00074 { 00075 delete d; 00076 } 00077 00078 void 00079 KEdit::insertText(QTextStream *stream) 00080 { 00081 // setAutoUpdate(false); 00082 int line, col; 00083 getCursorPosition(&line, &col); 00084 int saveline = line; 00085 int savecol = col; 00086 QString textLine; 00087 00088 // MS: Patch by Martin Schenk <martin@schenk.com> 00089 // MS: disable UNDO, or QMultiLineEdit remembers every textLine !!! 00090 // memory usage is: 00091 // textLine: 2*size rounded up to nearest power of 2 (520Kb -> 1024Kb) 00092 // widget: about (2*size + 60bytes*lines) 00093 // -> without disabling undo, it often needs almost 8*size 00094 int oldUndoDepth = undoDepth(); 00095 setUndoDepth( 0 ); // ### -1? 00096 00097 // MS: read everything at once if file <= 1MB, 00098 // else read in 5000-line chunks to keep memory usage acceptable. 00099 QIODevice *dev=stream->device(); 00100 if (dev && dev->size()>(1024*1024)) { 00101 while(1) { 00102 int i; 00103 textLine=""; 00104 for (i=0; i<5000; i++) { 00105 QString line=stream->readLine(); 00106 if (line.isNull()) break; // EOF 00107 textLine+=line+'\n'; 00108 } 00109 insertAt(textLine, line, col); 00110 line+=i; col=0; 00111 if (i!=5000) break; 00112 } 00113 } 00114 else { 00115 textLine = stream->read(); // Read all ! 00116 insertAt( textLine, line, col); 00117 } 00118 setUndoDepth( oldUndoDepth ); 00119 00120 setCursorPosition(saveline, savecol); 00121 // setAutoUpdate(true); 00122 00123 // repaint(); 00124 00125 setModified(true); 00126 setFocus(); 00127 00128 // Bernd: Please don't leave debug message like that lying around 00129 // they cause ENORMOUSE performance hits. Once upon a day 00130 // kedit used to be really really fast using memmap etc ..... 00131 // oh well .... 00132 00133 // QString str = text(); 00134 // for (int i = 0; i < (int) str.length(); i++) 00135 // printf("KEdit: U+%04X\n", str[i].unicode()); 00136 00137 } 00138 00139 void 00140 KEdit::cleanWhiteSpace() 00141 { 00142 setAutoUpdate(false); 00143 if (!hasMarkedText()) 00144 selectAll(); 00145 QString oldText = markedText(); 00146 QString newText; 00147 QStringList lines = QStringList::split('\n', oldText, true); 00148 bool addSpace = false; 00149 bool firstLine = true; 00150 QChar lastChar = oldText[oldText.length()-1]; 00151 QChar firstChar = oldText[0]; 00152 for(QStringList::Iterator it = lines.begin(); 00153 it != lines.end();) 00154 { 00155 QString line = (*it).simplifyWhiteSpace(); 00156 if (line.isEmpty()) 00157 { 00158 if (addSpace) 00159 newText += QString::fromLatin1("\n\n"); 00160 if (firstLine) 00161 { 00162 if (firstChar.isSpace()) 00163 newText += '\n'; 00164 firstLine = false; 00165 } 00166 addSpace = false; 00167 } 00168 else 00169 { 00170 if (addSpace) 00171 newText += ' '; 00172 if (firstLine) 00173 { 00174 if (firstChar.isSpace()) 00175 newText += ' '; 00176 firstLine = false; 00177 } 00178 newText += line; 00179 addSpace = true; 00180 } 00181 it = lines.remove(it); 00182 } 00183 if (addSpace) 00184 { 00185 if (lastChar == '\n') 00186 newText += '\n'; 00187 else if (lastChar.isSpace()) 00188 newText += ' '; 00189 } 00190 00191 if (oldText == newText) 00192 { 00193 deselect(); 00194 setAutoUpdate(true); 00195 repaint(); 00196 return; 00197 } 00198 if (wordWrap() == NoWrap) 00199 { 00200 // If wordwrap is off, we have to do some line-wrapping ourselves now 00201 // We use another QMultiLineEdit for this, so that we get nice undo 00202 // behavior. 00203 QMultiLineEdit *we = new QMultiLineEdit(); 00204 we->setWordWrap(FixedColumnWidth); 00205 we->setWrapColumnOrWidth(78); 00206 we->setText(newText); 00207 newText = QString::null; 00208 for(int i = 0; i < we->numLines(); i++) 00209 { 00210 QString line = we->textLine(i); 00211 if (line.right(1) != "\n") 00212 line += '\n'; 00213 newText += line; 00214 } 00215 delete we; 00216 } 00217 00218 insert(newText); 00219 setAutoUpdate(true); 00220 repaint(); 00221 00222 setModified(true); 00223 setFocus(); 00224 } 00225 00226 00227 void 00228 KEdit::saveText(QTextStream *stream) 00229 { 00230 saveText(stream, false); 00231 } 00232 00233 void 00234 KEdit::saveText(QTextStream *stream, bool softWrap) 00235 { 00236 int line_count = numLines()-1; 00237 if (line_count < 0) 00238 return; 00239 00240 if (softWrap || (wordWrap() == NoWrap)) 00241 { 00242 for(int i = 0; i < line_count; i++) 00243 { 00244 (*stream) << textLine(i) << '\n'; 00245 } 00246 (*stream) << textLine(line_count); 00247 } 00248 else 00249 { 00250 for(int i = 0; i <= line_count; i++) 00251 { 00252 int lines_in_parag = linesOfParagraph(i); 00253 if (lines_in_parag == 1) 00254 { 00255 (*stream) << textLine(i); 00256 } 00257 else 00258 { 00259 QString parag_text = textLine(i); 00260 int pos = 0; 00261 int first_pos = 0; 00262 int current_line = 0; 00263 while(true) { 00264 while(lineOfChar(i, pos) == current_line) pos++; 00265 (*stream) << parag_text.mid(first_pos, pos - first_pos - 1) << '\n'; 00266 current_line++; 00267 first_pos = pos; 00268 if (current_line+1 == lines_in_parag) 00269 { 00270 // Last line 00271 (*stream) << parag_text.mid(pos); 00272 break; 00273 } 00274 } 00275 } 00276 if (i < line_count) 00277 (*stream) << '\n'; 00278 } 00279 } 00280 } 00281 00282 int KEdit::currentLine(){ 00283 00284 computePosition(); 00285 return line_pos; 00286 00287 } 00288 00289 int KEdit::currentColumn(){ 00290 00291 computePosition(); 00292 return col_pos; 00293 } 00294 00295 void KEdit::slotCursorPositionChanged() 00296 { 00297 d->posDirty = true; 00298 emit CursorPositionChanged(); 00299 } 00300 00301 void KEdit::computePosition() 00302 { 00303 if (!d->posDirty) return; 00304 d->posDirty = false; 00305 00306 int line, col; 00307 00308 getCursorPosition(&line,&col); 00309 00310 // line is expressed in paragraphs, we now need to convert to lines 00311 line_pos = 0; 00312 if (wordWrap() == NoWrap) 00313 { 00314 line_pos = line; 00315 } 00316 else 00317 { 00318 for(int i = 0; i < line; i++) 00319 line_pos += linesOfParagraph(i); 00320 } 00321 00322 int line_offset = lineOfChar(line, col); 00323 line_pos += line_offset; 00324 00325 // We now calculate where the current line starts in the paragraph. 00326 QString linetext = textLine(line); 00327 int start_of_line = 0; 00328 if (line_offset > 0) 00329 { 00330 start_of_line = col; 00331 while(lineOfChar(line, --start_of_line) == line_offset); 00332 start_of_line++; 00333 } 00334 00335 00336 // O.K here is the deal: The function getCursorPositoin returns the character 00337 // position of the cursor, not the screenposition. I.e,. assume the line 00338 // consists of ab\tc then the character c will be on the screen on position 8 00339 // whereas getCursorPosition will return 3 if the cursors is on the character c. 00340 // Therefore we need to compute the screen position from the character position. 00341 // That's what all the following trouble is all about: 00342 00343 int coltemp = col-start_of_line; 00344 int pos = 0; 00345 int find = 0; 00346 int mem = 0; 00347 bool found_one = false; 00348 00349 // if you understand the following algorithm you are worthy to look at the 00350 // kedit+ sources -- if not, go away ;-) 00351 00352 00353 while(find >=0 && find <= coltemp- 1 ){ 00354 find = linetext.find('\t', find+start_of_line, true )-start_of_line; 00355 if( find >=0 && find <= coltemp - 1 ){ 00356 found_one = true; 00357 pos = pos + find - mem; 00358 pos = pos + 8 - pos % 8; 00359 mem = find; 00360 find ++; 00361 } 00362 } 00363 00364 pos = pos + coltemp - mem; // add the number of characters behind the 00365 // last tab on the line. 00366 00367 if (found_one){ 00368 pos = pos - 1; 00369 } 00370 00371 col_pos = pos; 00372 } 00373 00374 00375 void KEdit::keyPressEvent ( QKeyEvent *e) 00376 { 00377 // ignore Ctrl-Return so that KDialogBase can catch them 00378 if ( e->key() == Key_Return && e->state() == ControlButton ) { 00379 e->ignore(); 00380 return; 00381 } 00382 00383 KKey key(e); 00384 int keyQt = key.keyCodeQt(); 00385 00386 if ( keyQt == CTRL+Key_K ){ 00387 00388 int line = 0; 00389 int col = 0; 00390 QString killstring; 00391 00392 if(!killing){ 00393 killbufferstring = ""; 00394 killtrue = false; 00395 lastwasanewline = false; 00396 } 00397 00398 if(!atEnd()){ 00399 00400 getCursorPosition(&line,&col); 00401 killstring = textLine(line); 00402 killstring = killstring.mid(col,killstring.length()); 00403 00404 00405 if(!killbufferstring.isEmpty() && !killtrue && !lastwasanewline){ 00406 killbufferstring += '\n'; 00407 } 00408 00409 if( (killstring.length() == 0) && !killtrue){ 00410 killbufferstring += '\n'; 00411 lastwasanewline = true; 00412 } 00413 00414 if(killstring.length() > 0){ 00415 00416 killbufferstring += killstring; 00417 lastwasanewline = false; 00418 killtrue = true; 00419 00420 }else{ 00421 00422 lastwasanewline = false; 00423 killtrue = !killtrue; 00424 00425 } 00426 00427 }else{ 00428 00429 if(killbufferstring.isEmpty() && !killtrue && !lastwasanewline){ 00430 killtrue = true; 00431 } 00432 00433 } 00434 00435 killing = true; 00436 00437 QMultiLineEdit::keyPressEvent(e); 00438 setModified(true); 00439 return; 00440 } 00441 else if ( keyQt == CTRL+Key_Y ){ 00442 00443 int line = 0; 00444 int col = 0; 00445 00446 getCursorPosition(&line,&col); 00447 00448 QString tmpstring = killbufferstring; 00449 if(!killtrue) 00450 tmpstring += '\n'; 00451 00452 insertAt(tmpstring,line,col); 00453 00454 killing = false; 00455 setModified(true); 00456 return; 00457 } 00458 00459 killing = false; 00460 00461 if ( KStdAccel::copy().contains( key ) ) 00462 copy(); 00463 else if ( isReadOnly() ) 00464 QMultiLineEdit::keyPressEvent( e ); 00465 // If this is an unmodified printable key, send it directly to QMultiLineEdit. 00466 else if ( (key.keyCodeQt() & (CTRL | ALT)) == 0 && !e->text().isEmpty() && e->text().unicode()->isPrint() ) 00467 QMultiLineEdit::keyPressEvent( e ); 00468 else if ( KStdAccel::paste().contains( key ) ) { 00469 paste(); 00470 setModified(true); 00471 slotCursorPositionChanged(); 00472 } 00473 else if ( KStdAccel::cut().contains( key ) ) { 00474 cut(); 00475 setModified(true); 00476 slotCursorPositionChanged(); 00477 } 00478 else if ( KStdAccel::undo().contains( key ) ) { 00479 undo(); 00480 setModified(true); 00481 slotCursorPositionChanged(); 00482 } 00483 else if ( KStdAccel::redo().contains( key ) ) { 00484 redo(); 00485 setModified(true); 00486 slotCursorPositionChanged(); 00487 } 00488 else if ( KStdAccel::deleteWordBack().contains( key ) ) { 00489 moveCursor(MoveWordBackward, true); 00490 if (hasSelectedText()) 00491 del(); 00492 setModified(true); 00493 slotCursorPositionChanged(); 00494 } 00495 else if ( KStdAccel::deleteWordForward().contains( key ) ) { 00496 moveCursor(MoveWordForward, true); 00497 if (hasSelectedText()) 00498 del(); 00499 setModified(true); 00500 slotCursorPositionChanged(); 00501 } 00502 else if ( key == Key_Insert ) { 00503 if (d->overwriteEnabled) 00504 { 00505 this->setOverwriteMode(!this->isOverwriteMode()); 00506 emit toggle_overwrite_signal(); 00507 } 00508 } 00509 else 00510 QMultiLineEdit::keyPressEvent(e); 00511 } 00512 00513 void KEdit::installRBPopup(QPopupMenu *p) { 00514 KContextMenuManager::insert( this, p ); 00515 } 00516 00517 void KEdit::selectFont(){ 00518 00519 QFont font = this->font(); 00520 KFontDialog::getFont(font); 00521 this->setFont(font); 00522 00523 } 00524 00525 void KEdit::doGotoLine() { 00526 00527 if( !gotodialog ) 00528 gotodialog = new KEdGotoLine( parent, "gotodialog" ); 00529 00530 this->clearFocus(); 00531 00532 gotodialog->exec(); 00533 // this seems to be not necessary 00534 // gotodialog->setFocus(); 00535 if( gotodialog->result() != KEdGotoLine::Accepted) 00536 return; 00537 int target_line = gotodialog->getLineNumber()-1; 00538 if (wordWrap() == NoWrap) 00539 { 00540 setCursorPosition( target_line, 0 ); 00541 setFocus(); 00542 return; 00543 } 00544 00545 int max_parag = paragraphs(); 00546 00547 int line = 0; 00548 int parag = -1; 00549 int lines_in_parag = 0; 00550 while ((++parag < max_parag) && (line + lines_in_parag < target_line)) 00551 { 00552 line += lines_in_parag; 00553 lines_in_parag = linesOfParagraph(parag); 00554 } 00555 00556 int col = 0; 00557 if (parag >= max_parag) 00558 { 00559 target_line = line + lines_in_parag - 1; 00560 parag = max_parag-1; 00561 } 00562 00563 while(1+line+lineOfChar(parag,col) < target_line) col++; 00564 setCursorPosition( parag, col ); 00565 setFocus(); 00566 } 00567 00568 00569 void KEdit::dragMoveEvent(QDragMoveEvent* e) { 00570 00571 if(KURLDrag::canDecode(e)) 00572 e->accept(); 00573 else if(QTextDrag::canDecode(e)) 00574 QMultiLineEdit::dragMoveEvent(e); 00575 } 00576 00577 void KEdit::contentsDragMoveEvent(QDragMoveEvent* e) { 00578 00579 if(KURLDrag::canDecode(e)) 00580 e->accept(); 00581 else if(QTextDrag::canDecode(e)) 00582 QMultiLineEdit::contentsDragMoveEvent(e); 00583 } 00584 00585 void KEdit::dragEnterEvent(QDragEnterEvent* e) { 00586 00587 kdDebug() << "KEdit::dragEnterEvent()" << endl; 00588 e->accept(KURLDrag::canDecode(e) || QTextDrag::canDecode(e)); 00589 } 00590 00591 void KEdit::contentsDragEnterEvent(QDragEnterEvent* e) { 00592 00593 kdDebug() << "KEdit::contentsDragEnterEvent()" << endl; 00594 e->accept(KURLDrag::canDecode(e) || QTextDrag::canDecode(e)); 00595 } 00596 00597 00598 void KEdit::dropEvent(QDropEvent* e) { 00599 00600 kdDebug() << "KEdit::dropEvent()" << endl; 00601 00602 if(KURLDrag::canDecode(e)) { 00603 emit gotUrlDrop(e); 00604 } 00605 else if(QTextDrag::canDecode(e)) 00606 QMultiLineEdit::dropEvent(e); 00607 } 00608 00609 void KEdit::contentsDropEvent(QDropEvent* e) { 00610 00611 kdDebug() << "KEdit::contentsDropEvent()" << endl; 00612 00613 if(KURLDrag::canDecode(e)) { 00614 emit gotUrlDrop(e); 00615 } 00616 else if(QTextDrag::canDecode(e)) 00617 QMultiLineEdit::contentsDropEvent(e); 00618 } 00619 00620 void KEdit::setOverwriteEnabled(bool b) 00621 { 00622 d->overwriteEnabled = b; 00623 } 00624 00625 // QWidget::create() turns off mouse-Tracking which would break auto-hiding 00626 void KEdit::create( WId id, bool initializeWindow, bool destroyOldWindow ) 00627 { 00628 QMultiLineEdit::create( id, initializeWindow, destroyOldWindow ); 00629 KCursor::setAutoHideCursor( this, true ); 00630 } 00631 00632 00633 void KEdGotoLine::virtual_hook( int id, void* data ) 00634 { KDialogBase::virtual_hook( id, data ); } 00635 00636 void KEdFind::virtual_hook( int id, void* data ) 00637 { KDialogBase::virtual_hook( id, data ); } 00638 00639 void KEdReplace::virtual_hook( int id, void* data ) 00640 { KDialogBase::virtual_hook( id, data ); } 00641 00642 void KEdit::virtual_hook( int, void* ) 00643 { /*BASE::virtual_hook( id, data );*/ } 00644
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 12 15:08:15 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003