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