• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdeui

keditcl1.cpp

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, 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     CursorAction action = MoveWordBackward;
00512     int para, index;
00513     getCursorPosition( &para, & index );
00514     if (text(para).isRightToLeft())
00515        action = MoveWordForward;
00516     moveCursor(action, false );
00517     slotCursorPositionChanged();
00518   }
00519   else if ( KStdAccel::forwardWord().contains( key ) ) {
00520     CursorAction action = MoveWordForward;
00521     int para, index;
00522     getCursorPosition( &para, & index );
00523     if (text(para).isRightToLeft())
00524       action = MoveWordBackward;
00525     moveCursor( action, false );
00526     slotCursorPositionChanged();
00527   }
00528   else if ( KStdAccel::next().contains( key ) ) {
00529     moveCursor( MovePgDown, false );
00530     slotCursorPositionChanged();
00531   }
00532   else if ( KStdAccel::prior().contains( key ) ) {
00533     moveCursor( MovePgUp, false );
00534     slotCursorPositionChanged();
00535   }
00536   else if ( KStdAccel::home().contains( key ) ) {
00537     moveCursor( MoveHome, false );
00538     slotCursorPositionChanged();
00539   }
00540   else if ( KStdAccel::end().contains( key ) ) {
00541     moveCursor( MoveEnd, false );
00542     slotCursorPositionChanged();
00543   }
00544   else if ( KStdAccel::beginningOfLine().contains( key ) ) {
00545     moveCursor( MoveLineStart, false);
00546     slotCursorPositionChanged();
00547   }
00548   else if ( KStdAccel::endOfLine().contains( key ) ) {
00549     moveCursor( MoveLineEnd, false);
00550     slotCursorPositionChanged();
00551   }
00552   else if ( key == Key_Insert ) {
00553     if (d->overwriteEnabled)
00554     {
00555       this->setOverwriteMode(!this->isOverwriteMode());
00556       emit toggle_overwrite_signal();
00557     }
00558   }
00559   else
00560     QMultiLineEdit::keyPressEvent(e);
00561 }
00562 
00563 void KEdit::installRBPopup(QPopupMenu *p) {
00564   KContextMenuManager::insert( this, p );
00565 }
00566 
00567 void KEdit::selectFont(){
00568 
00569   QFont font = this->font();
00570   KFontDialog::getFont(font);
00571   this->setFont(font);
00572 
00573 }
00574 
00575 void KEdit::doGotoLine() {
00576 
00577    if( !gotodialog )
00578       gotodialog = new KEdGotoLine( parent, "gotodialog" );
00579 
00580    this->clearFocus();
00581 
00582    gotodialog->exec();
00583    // this seems to be not necessary
00584    // gotodialog->setFocus();
00585    if( gotodialog->result() != KEdGotoLine::Accepted)
00586       return;
00587    int target_line = gotodialog->getLineNumber()-1;
00588    if (wordWrap() == NoWrap)
00589    {
00590       setCursorPosition( target_line, 0 );
00591       setFocus();
00592       return;
00593    }
00594 
00595    int max_parag = paragraphs();
00596 
00597    int line = 0;
00598    int parag = -1;
00599    int lines_in_parag = 0;
00600    while ((++parag < max_parag) && (line + lines_in_parag < target_line))
00601    {
00602       line += lines_in_parag;
00603       lines_in_parag = linesOfParagraph(parag);
00604    }
00605 
00606    int col = 0;
00607    if (parag >= max_parag)
00608    {
00609       target_line = line + lines_in_parag - 1;
00610       parag = max_parag-1;
00611    }
00612 
00613    while(1+line+lineOfChar(parag,col) < target_line) col++;
00614    setCursorPosition( parag, col );
00615    setFocus();
00616 }
00617 
00618 
00619 void  KEdit::dragMoveEvent(QDragMoveEvent* e) {
00620 
00621   if(KURLDrag::canDecode(e))
00622     e->accept();
00623   else if(QTextDrag::canDecode(e))
00624     QMultiLineEdit::dragMoveEvent(e);
00625 }
00626 
00627 void  KEdit::contentsDragMoveEvent(QDragMoveEvent* e) {
00628 
00629   if(KURLDrag::canDecode(e))
00630     e->accept();
00631   else if(QTextDrag::canDecode(e))
00632     QMultiLineEdit::contentsDragMoveEvent(e);
00633 }
00634 
00635 void  KEdit::dragEnterEvent(QDragEnterEvent* e) {
00636 
00637   kdDebug() << "KEdit::dragEnterEvent()" << endl;
00638   e->accept(KURLDrag::canDecode(e) || QTextDrag::canDecode(e));
00639 }
00640 
00641 void  KEdit::contentsDragEnterEvent(QDragEnterEvent* e) {
00642 
00643   kdDebug() << "KEdit::contentsDragEnterEvent()" << endl;
00644   e->accept(KURLDrag::canDecode(e) || QTextDrag::canDecode(e));
00645 }
00646 
00647 
00648 void  KEdit::dropEvent(QDropEvent* e) {
00649 
00650   kdDebug() << "KEdit::dropEvent()" << endl;
00651 
00652   if(KURLDrag::canDecode(e)) {
00653    emit gotUrlDrop(e);
00654   }
00655   else if(QTextDrag::canDecode(e))
00656     QMultiLineEdit::dropEvent(e);
00657 }
00658 
00659 void  KEdit::contentsDropEvent(QDropEvent* e) {
00660 
00661   kdDebug() << "KEdit::contentsDropEvent()" << endl;
00662 
00663   if(KURLDrag::canDecode(e)) {
00664    emit gotUrlDrop(e);
00665   }
00666   else if(QTextDrag::canDecode(e))
00667     QMultiLineEdit::contentsDropEvent(e);
00668 }
00669 
00670 void KEdit::setOverwriteEnabled(bool b)
00671 {
00672   d->overwriteEnabled = b;
00673 }
00674 
00675 // QWidget::create() turns off mouse-Tracking which would break auto-hiding
00676 void KEdit::create( WId id, bool initializeWindow, bool destroyOldWindow )
00677 {
00678   QMultiLineEdit::create( id, initializeWindow, destroyOldWindow );
00679   KCursor::setAutoHideCursor( this, true );
00680 }
00681 
00682 void KEdit::ensureCursorVisible()
00683 {
00684   if (!d->autoUpdate)
00685     return;
00686 
00687   QMultiLineEdit::ensureCursorVisible();
00688 }
00689 
00690 void KEdit::setCursor( const QCursor &c )
00691 {
00692   if (!d->autoUpdate)
00693     return;
00694 
00695   QMultiLineEdit::setCursor(c);
00696 }
00697 
00698 void KEdit::viewportPaintEvent( QPaintEvent*pe )
00699 {
00700   if (!d->autoUpdate)
00701     return;
00702 
00703   QMultiLineEdit::viewportPaintEvent(pe);
00704 }
00705 
00706 
00707 void KEdGotoLine::virtual_hook( int id, void* data )
00708 { KDialogBase::virtual_hook( id, data ); }
00709 
00710 void KEdFind::virtual_hook( int id, void* data )
00711 { KDialogBase::virtual_hook( id, data ); }
00712 
00713 void KEdReplace::virtual_hook( int id, void* data )
00714 { KDialogBase::virtual_hook( id, data ); }
00715 
00716 void KEdit::virtual_hook( int, void* )
00717 { /*BASE::virtual_hook( id, data );*/ }
00718 

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal