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.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Apr 21 18:43:15 2004 by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2003