?? qmultilineedit.cpp
字號:
/************************************************************************ $Id: qt/src/widgets/qmultilineedit.cpp 2.3.12 edited 2005-10-27 $**** Implementation of QMultiLineEdit widget class**** Created : 961005**** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.**** This file is part of the widgets module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition** licenses may use this file in accordance with the Qt Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qmultilineedit.h"#ifndef QT_NO_MULTILINEEDIT#include "qpainter.h"#include "qscrollbar.h"#include "qclipboard.h"#include "qpixmap.h"#include "qregexp.h"#include "qapplication.h"#include "qdragobject.h"#include "qpopupmenu.h"#include "qtimer.h"#include "qdict.h"#include <ctype.h>#ifdef _WS_QWS_#include <qwsdisplay_qws.h>#ifndef QT_NO_QWS_IM#include "../kernel/qinputcontext_p.h"#endif#endif#ifdef QT_KEYPAD_MODEextern bool qt_modalEditingEnabled;#endifclass QMultiLineEditCommand{public: enum Commands { Invalid, Begin, End, Insert, Delete }; virtual ~QMultiLineEditCommand() {}; virtual Commands type() { return Invalid; }; virtual int terminator() { return 0; } virtual bool merge( QMultiLineEditCommand* ) { return FALSE;}};class QBeginCommand : public QMultiLineEditCommand{public: QBeginCommand() {} int terminator() { return 1; } Commands type() { return Begin; };};class QEndCommand : public QMultiLineEditCommand{public: QEndCommand() {} int terminator() { return -1; } Commands type() { return End; };};// QMultiLineEditUndoRedo methodsclass QDelTextCmd : public QMultiLineEditCommand{public: int mOffset; QString mStr; // have to handle deletion of current selection QDelTextCmd(int offset, const QString &str ) : mOffset( offset ), mStr ( str ) { } Commands type() { return Delete; }; bool merge( QMultiLineEditCommand* other) { if ( other->type() == type() ) { QDelTextCmd* o = (QDelTextCmd*) other; if ( mOffset + int(mStr.length()) == o->mOffset ) { o->mStr.prepend( mStr ); o->mOffset = mOffset; return TRUE; } } return FALSE; }};class QInsTextCmd : public QDelTextCmd{public: QInsTextCmd(int offset,const QString &str ) : QDelTextCmd( offset, str ) { } Commands type() { return Insert; }; bool merge( QMultiLineEditCommand* other) { if ( other->type() == type() ) { QInsTextCmd* o = (QInsTextCmd*) other; if ( mOffset == o->mOffset + int(o->mStr.length()) ) { o->mStr += mStr; return TRUE; } } return FALSE; }};// NOT REVISED/*! \class QMultiLineEdit qmultilineedit.h \brief The QMultiLineEdit widget is a simple editor for inputting text. \ingroup advanced The QMultiLineEdit widget provides multiple line text input and display. It is intended for moderate amounts of text. There are no arbitrary limitations, but if you try to handle megabytes of data, performance will suffer. Per default, the edit widget does not perform any word wrapping. This can be adjusted by calling setWordWrap(). Both dynamic wrapping according to the visible width or a fixed number of character or pixels is supported. The widget can be used to display text by calling setReadOnly(TRUE) The default key bindings are described in keyPressEvent(); they cannot be customized except by inheriting the class. <img src=qmlined-m.png> <img src=qmlined-w.png>*/static const char * const arrow_xpm[] = { " 8 8 2 1", ". c None", "# c #000000", "........", "..####..", "..#####.", ".....##.", ".#..###.", ".#####..", ".####...", ".#####.."};enum { IdUndo, IdRedo,#ifndef QT_NO_CLIPBOARD IdCut, IdCopy, IdPaste, IdPasteSpecial,#endif IdClear, IdSelectAll, IdCount};struct QMultiLineData{ QMultiLineData() : isHandlingEvent(FALSE), edited(FALSE), maxLineWidth(0), align(Qt::AlignLeft), maxlines(-1), maxlinelen(-1), maxlen(-1), wordwrap( QMultiLineEdit::NoWrap ), wrapcol( -1 ), wrappolicy( QMultiLineEdit::AtWhiteSpace ), // This doesn't use font bearings, as textWidthWithTabs does that. // This is just an aesthetics value. // It should probably be QMAX(0,3-fontMetrics().minLeftBearing()) though, // as bearings give some border anyway. lr_marg(3), marg_extra(0), echomode(QMultiLineEdit::Normal), val(0), dnd_primed(FALSE), dnd_forcecursor(FALSE), undo( TRUE ), undodepth( 256 ) {#ifndef QT_NO_QWS_IM preeditStartY = -1;#endif#ifdef QT_KEYPAD_MODE deleteAllTimerId = -1; extraNewLineCount = 0;#endif undoList.setAutoDelete( TRUE ); redoList.setAutoDelete( TRUE ); clearChartable(); } bool isHandlingEvent; bool edited; int maxLineWidth; int scrollTime; int scrollAccel; int align; int numlines; int maxlines; int maxlinelen; int maxlen; QMultiLineEdit::WordWrap wordwrap; int wrapcol; int lr_marg; int marg_extra; QMultiLineEdit::EchoMode echomode; const QValidator* val; bool dnd_primed; // If TRUE, user has pressed bool dnd_forcecursor; // If TRUE show cursor for DND feedback, // even if !hasFocus() QList<QMultiLineEditCommand> undoList; QList<QMultiLineEditCommand> redoList; bool undo; int undodepth; short chartable[256]; void clearChartable() { int i = 256; while ( i ) chartable[--i] = 0; } QPixmap arrow; QPoint dnd_startpos; QTimer *blinkTimer, *scrollTimer;#ifndef QT_NO_QWS_IM int preeditStartX, preeditStartY, preeditEndX, preeditEndY; int preeditCPos, preeditLength, preeditSelLen;#endif#ifdef QT_KEYPAD_MODE QString orgTxt; int extraNewLineCount; int deleteAllTimerId;#endif#ifndef QT_NO_DRAGANDDROP QTimer *dnd_timer;#endif};#ifndef QT_NO_QWS_IMbool QMultiLineEdit::composeMode() const{ return d->preeditStartY >= 0;}#endifstatic bool inBlinkTimer = FALSE;#ifndef QT_NO_QWS_IMextern QBrush *qt_im_compose_background;#endif#define CLEAR_UNDO {d->undoList.clear(); emit undoAvailable( FALSE );\ d->redoList.clear(); emit redoAvailable( FALSE );}void QMultiLineEdit::addUndoCmd(QMultiLineEditCommand* c){ if ( d->undoList.isEmpty() ) emit undoAvailable(TRUE); else if ( c->merge( d->undoList.last() ) ) { delete c; return; } if ( int(d->undoList.count()) >= d->undodepth ) d->undoList.removeFirst(); d->undoList.append(c); if ( !d->redoList.isEmpty() ) { d->redoList.clear(); emit redoAvailable( FALSE ); }}void QMultiLineEdit::addRedoCmd(QMultiLineEditCommand* c){ if ( d->redoList.isEmpty() ) emit redoAvailable(TRUE); d->redoList.append(c);}static const int initialScrollTime = 50; // mark text scroll timestatic const int initialScrollAccel = 5; // mark text scroll accel (0=fastest)static const int scroll_margin = 16; // auto-scroll edge in DND#define WORD_WRAP ( d->wordwrap != QMultiLineEdit::NoWrap )#define DYNAMIC_WRAP ( d->wordwrap == QMultiLineEdit::WidgetWidth )#define FIXED_WIDTH_WRAP ( d->wordwrap == QMultiLineEdit::FixedPixelWidth )#define FIXED_COLUMN_WRAP ( d->wordwrap == QMultiLineEdit::FixedColumnWidth )#define BREAK_WITHIN_WORDS ( d->wrappolicy == QMultiLineEdit::Anywhere )static int defTabStop = 8;static int tabStopDist( const QFontMetrics &fm ){ int dist; dist = fm.width( QChar('x' )); if( dist == 0 ) dist = fm.maxWidth(); return defTabStop*dist;}/*! Sets the distance between tab stops for all QMultiLineEdit instances to \a ex, which is measured in multiples of the width of a lower case 'x' in the widget's font. The initial value is 8. \warning This function does not cause a redraw. It is best to call it before any QMultiLineEdit widgets are shown. \sa defaultTabStop()*/void QMultiLineEdit::setDefaultTabStop( int ex ){ defTabStop = ex;}/*! Returns the distance between tab stops. \sa setDefaultTabStop();*/int QMultiLineEdit::defaultTabStop(){ return defTabStop;}static int textWidthWithTabs( const QFontMetrics &fm, const QString &s, uint start, uint nChars, int align ){ if ( s.isEmpty() ) return 0; int dist = -fm.leftBearing( s[(int)start] ); int i = start; int tabDist = -1; // lazy eval while ( (uint)i < s.length() && (uint)i < start+nChars ) { if ( s[i] == '\t' && align == Qt::AlignLeft ) { if ( tabDist<0 ) tabDist = tabStopDist(fm); dist = ( (dist+tabDist+1)/tabDist ) * tabDist; i++; } else { int ii = i; while ( (uint)i < s.length() && (uint)i < start + nChars && ( align != Qt::AlignLeft || s[i] != '\t' ) ) i++; dist += fm.width( s.mid(ii,i-ii) ); } } return dist;}static int xPosToCursorPos( const QString &s, const QFontMetrics &fm, int xPos, int width, int align ){ int i = 0; int dist; int tabDist; if ( s.isEmpty() ) return 0; if ( xPos > width ) xPos = width; if ( xPos <= 0 ) return 0; dist = -fm.leftBearing( s[0] ); if ( align == Qt::AlignCenter || align == Qt::AlignHCenter ) dist = ( width - textWidthWithTabs( fm, s, 0, s.length(), align ) ) / 2; else if ( align == Qt::AlignRight ) dist = width - textWidthWithTabs( fm, s, 0, s.length(), align ); int distBeforeLastTab = dist; tabDist = tabStopDist(fm); while ( (uint)i < s.length() && dist < xPos ) { if ( s[i] == '\t' && align == Qt::AlignLeft ) { distBeforeLastTab = dist; dist = (dist/tabDist + 1) * tabDist; } else { dist += fm.width( s[i] ); } i++; } if ( dist > xPos ) { if ( dist > width ) { i--; } else { if ( s[i-1] == '\t' && align == Qt::AlignLeft ) { // dist equals a tab stop position if ( xPos - distBeforeLastTab < (dist - distBeforeLastTab)/2 ) i--; } else { if ( fm.width(s[i-1])/2 < dist-xPos ) i--; } } } return i;}/*! Constructs a new, empty, QMultiLineEdit.*/QMultiLineEdit::QMultiLineEdit( QWidget *parent , const char *name ) :QTableView( parent, name, WNorthWestGravity | WRepaintNoErase ){ d = new QMultiLineData; QFontMetrics fm( font() ); setCellHeight( fm.lineSpacing() ); setNumCols( 1 ); contents = new QList<QMultiLineEditRow>; contents->setAutoDelete( TRUE ); cursorX = 0; cursorY = 0; curXPos = 0; setTableFlags( Tbl_autoVScrollBar|Tbl_autoHScrollBar| Tbl_smoothVScrolling | Tbl_clipCellPainting ); setFrameStyle( QFrame::WinPanel | QFrame::Sunken );#ifdef QT_KEYPAD_MODE if( qt_modalEditingEnabled ) { setBackgroundMode( PaletteBackground ); // Until modal } else#else setBackgroundMode( PaletteBase );#endif setWFlags( WResizeNoErase ); setKeyCompression( TRUE ); setFocusPolicy( WheelFocus );#ifndef QT_NO_CURSOR setCursor( ibeamCursor ); verticalScrollBar()->setCursor( arrowCursor ); horizontalScrollBar()->setCursor( arrowCursor );#endif readOnly = FALSE; cursorOn = FALSE; markIsOn = FALSE; dragScrolling = FALSE; dragMarking = FALSE; textDirty = FALSE; wordMark = FALSE; overWrite = FALSE; markAnchorX = 0; markAnchorY = 0; markDragX = 0; markDragY = 0; d->blinkTimer = new QTimer( this ); connect( d->blinkTimer, SIGNAL( timeout() ), this, SLOT( blinkTimerTimeout() ) ); d->scrollTimer = new QTimer( this ); connect( d->scrollTimer, SIGNAL( timeout() ), this, SLOT( scrollTimerTimeout() ) );#ifndef QT_NO_DRAGANDDROP d->dnd_timer = new QTimer( this ); connect( d->dnd_timer, SIGNAL( timeout() ), this, SLOT( dndTimeout() ) );#endif d->scrollTime = 0; dummy = TRUE; int w = textWidth( QString::fromLatin1("") ); contents->append( new QMultiLineEditRow(QString::fromLatin1(""), w) ); (void)setNumRowsAndTruncate(); setWidth( w ); setAcceptDrops(TRUE); if ( d->maxlines >= 0 && d->maxlines <= 6 ) { setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) ); } else { setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); }}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -