keditcl1.cpp Source File (kdeui Library)

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

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 12:56:43 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001