# kdeui Library API Documentation

Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

# 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)) && !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

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:16 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003