summaryrefslogtreecommitdiffstats
path: root/src/attic
diff options
context:
space:
mode:
Diffstat (limited to 'src/attic')
-rw-r--r--src/attic/README6
-rw-r--r--src/attic/qtmultilineedit.cpp4236
-rw-r--r--src/attic/qtmultilineedit.h363
-rw-r--r--src/attic/qttableview.cpp2272
-rw-r--r--src/attic/qttableview.h250
5 files changed, 7127 insertions, 0 deletions
diff --git a/src/attic/README b/src/attic/README
new file mode 100644
index 0000000..7400da1
--- /dev/null
+++ b/src/attic/README
@@ -0,0 +1,6 @@
+This directory contains classes that has been obsoleted and moved out
+of the Qt API.
+
+To use these classes, simply include them in your project. Remember to
+rename the class references in your own code.
+
diff --git a/src/attic/qtmultilineedit.cpp b/src/attic/qtmultilineedit.cpp
new file mode 100644
index 0000000..3c8f346
--- /dev/null
+++ b/src/attic/qtmultilineedit.cpp
@@ -0,0 +1,4236 @@
+/**********************************************************************
+**
+** Implementation of QtMultiLineEdit widget class
+**
+** Created : 961005
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file contains a class moved out of the Qt GUI Toolkit API. It
+** may be used, distributed and modified without limitation.
+**
+**********************************************************************/
+
+#include "qtmultilineedit.h"
+#ifndef QT_NO_QTMULTILINEEDIT
+#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 "qcursor.h"
+#ifndef QT_NO_COMPAT
+#include "qstyle.h"
+#endif
+
+
+class QtMultiLineEditCommand
+{
+public:
+ enum Commands { Invalid, Begin, End, Insert, Delete };
+ virtual ~QtMultiLineEditCommand() {};
+ virtual Commands type() { return Invalid; };
+ virtual int terminator() { return 0; }
+
+ virtual bool merge( QtMultiLineEditCommand* ) { return FALSE;}
+};
+
+class QBeginCommand : public QtMultiLineEditCommand
+{
+
+public:
+ QBeginCommand() {}
+ int terminator() { return 1; }
+ Commands type() { return Begin; };
+};
+
+class QEndCommand : public QtMultiLineEditCommand
+{
+public:
+ QEndCommand() {}
+ int terminator() { return -1; }
+ Commands type() { return End; };
+};
+
+// QtMultiLineEditUndoRedo methods
+class QDelTextCmd : public QtMultiLineEditCommand
+{
+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( QtMultiLineEditCommand* 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( QtMultiLineEditCommand* other)
+ {
+ if ( other->type() == type() ) {
+ QInsTextCmd* o = (QInsTextCmd*) other;
+ if ( mOffset == o->mOffset + int(o->mStr.length()) ) {
+ o->mStr += mStr;
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+};
+
+
+/*
+ \class QtMultiLineEdit qtmultilineedit.h
+
+ \brief The QtMultiLineEdit widget is a simple editor for inputting text.
+
+ \obsolete
+
+ The QtMultiLineEdit 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>
+*/
+
+/*
+ \property QtMultiLineEdit::numLines
+ \brief the number of lines in the multi-line edit
+
+ numLines() returns the number of lines in the editor. The count
+ includes any empty lines at top and bottom, so for an empty editor
+ this method will return 1.
+*/
+/*
+ \property QtMultiLineEdit::atBeginning
+ \brief whether the cursor is at the beginning
+
+ atBeginning() returns TRUE if the cursor is placed at the
+ beginning of the text.
+*/
+/*
+ \property QtMultiLineEdit::atEnd
+ \brief whether the cursor is at the end
+
+ atEnd() returns TRUE if the cursor is placed at the end of the text.
+*/
+/*
+ \property QtMultiLineEdit::maxLineWidth
+ \brief the maximum line width in pixels
+ Returns the width in pixels of the longest text line in this editor.
+*/
+/*
+ \property QtMultiLineEdit::alignment
+ \brief the alignment
+
+ Possible values are \c AlignLeft, \c Align(H)Center and \c
+ AlignRight.
+ \sa Qt::AlignmentFlags
+*/
+/*
+ \property QtMultiLineEdit::edited
+ \brief whether the text had been edited
+
+edited() returns the edited flag of the line edit. If this returns FALSE,
+the contents has not been changed since the construction of the
+QtMultiLineEdit (or the last call to setEdited( FALSE ), if any). If
+it returns TRUE, the contents have been edited, or setEdited( TRUE )
+has been called.
+
+setEdited() sets the edited flag of this line edit to \e e. The
+edited flag is never read by QtMultiLineEdit, but is changed to TRUE
+whenever the user changes its contents.
+
+This is useful e.g. for things that need to provide a default value,
+but cannot find the default at once. Just open the widget without the
+best default and when the default is known, check the edited() return
+value and set the line edit's contents if the user has not started
+editing the line edit. Another example is to detect whether the
+contents need saving.
+
+*/
+/*
+ \property QtMultiLineEdit::echoMode
+ \brief the echo mode
+*/
+/*
+ \property QtMultiLineEdit::maxLength
+ \brief the maximum length of the text
+
+ The currently set text length limit, or -1 if there is
+ no limit (this is the default).
+
+*/
+/*
+ \property QtMultiLineEdit::maxLines
+ \brief the maximum number of lines
+ The currently set line limit, or -1 if there is
+ no limit (the default).
+
+ Note that excess lines are deleted from the \e bottom of the
+ lines. If you want teletype behaviour with lines disappearing
+ from the \e top as the limit is exceed, you probably just want
+ to use removeLine(0) prior to adding an excess line.
+
+*/
+/*
+ \property QtMultiLineEdit::hMargin
+ \brief the horizontal margin
+ The horizontal margin current set. The default is 3.
+*/
+/*
+ \property QtMultiLineEdit::wordWrap
+ \brief the word wrap mode
+
+ By default, wrapping keeps words intact. To allow breaking within
+ words, set the wrap policy to \c Anywhere (see setWrapPolicy() ).
+
+ The default wrap mode is \c NoWrap.
+
+ \sa wordWrap(), setWrapColumnOrWidth(), setWrapPolicy()
+*/
+/*
+ \property QtMultiLineEdit::wrapColumnOrWidth
+ \brief the wrap width in columns or pixels
+ The wrap column or wrap width, depending on the word wrap
+ mode.
+ \sa setWordWrap(), setWrapColumnOrWidth()
+*/
+/*
+ \property QtMultiLineEdit::wrapPolicy
+ \brief the wrap policy mode
+ The default is \c AtWhiteSpace.
+
+*/
+/*
+ \property QtMultiLineEdit::autoUpdate
+ \brief whether auto update is enabled
+
+ autoUpdate() returns TRUE if the view updates itself automatically
+ whenever it is changed in some way.
+
+ If autoUpdate() is TRUE (this is the default) then the editor updates
+ itself automatically whenever it has changed in some way (generally,
+ when text has been inserted or deleted).
+
+ If autoUpdate() is FALSE, the view does NOT repaint itself, or update
+ its internal state variables itself when it is changed. This can be
+ useful to avoid flicker during large changes, and is singularly
+ useless otherwise: Disable auto-update, do the changes, re-enable
+ auto-update, and call repaint().
+
+ \warning Do not leave the view in this state for a long time
+ (i.e. between events ). If, for example, the user interacts with the
+ view when auto-update is off, strange things can happen.
+
+ Setting auto-update to TRUE does not repaint the view, you must call
+ repaint() to do this (preferable repaint(FALSE) to avoid flicker).
+
+ \sa autoUpdate() repaint()
+
+*/
+/*
+ \property QtMultiLineEdit::undoEnabled
+ \brief whether undo is enabled
+*/
+/*
+ \property QtMultiLineEdit::undoDepth
+ \brief the undo depth
+
+ The maximum number of operations that can be stored on the undo stack.
+
+ \sa setUndoDepth()
+*/
+/*
+ \property QtMultiLineEdit::readOnly
+ \brief whether the multi-line edit is read-only
+*/
+/*
+ \property QtMultiLineEdit::overWriteMode
+ \brief the overwrite mode
+*/
+/*
+ \property QtMultiLineEdit::text
+ \brief the multi-line edit's text
+*/
+/*
+ \property QtMultiLineEdit::length
+ \brief the length of the text
+*/
+
+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 QtMultiLineData
+{
+ QtMultiLineData() :
+ isHandlingEvent(FALSE),
+ edited(FALSE),
+ maxLineWidth(0),
+ align(Qt::AlignLeft),
+ maxlines(-1),
+ maxlinelen(-1),
+ maxlen(-1),
+ wordwrap( QtMultiLineEdit::NoWrap ),
+ wrapcol( -1 ),
+ wrappolicy( QtMultiLineEdit::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(QtMultiLineEdit::Normal),
+ val(0),
+ dnd_primed(FALSE),
+ dnd_forcecursor(FALSE),
+ undo( TRUE ),
+ undodepth( 256 )
+ {
+ 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;
+ QtMultiLineEdit::WordWrap wordwrap;
+ int wrapcol;
+ QtMultiLineEdit::WrapPolicy wrappolicy;
+ int lr_marg;
+ int marg_extra;
+ QtMultiLineEdit::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()
+ QPtrList<QtMultiLineEditCommand> undoList;
+ QPtrList<QtMultiLineEditCommand> 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_DRAGANDDROP
+ QTimer *dnd_timer;
+#endif
+};
+
+
+#define CLEAR_UNDO {d->undoList.clear(); emit undoAvailable( FALSE );\
+ d->redoList.clear(); emit redoAvailable( FALSE );}
+
+void QtMultiLineEdit::addUndoCmd(QtMultiLineEditCommand* 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 QtMultiLineEdit::addRedoCmd(QtMultiLineEditCommand* c)
+{
+ if ( d->redoList.isEmpty() )
+ emit redoAvailable(TRUE);
+ d->redoList.append(c);
+}
+
+static const int initialScrollTime = 50; // mark text scroll time
+static 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 != QtMultiLineEdit::NoWrap )
+#define DYNAMIC_WRAP ( d->wordwrap == QtMultiLineEdit::WidgetWidth )
+#define FIXED_WIDTH_WRAP ( d->wordwrap == QtMultiLineEdit::FixedPixelWidth )
+#define FIXED_COLUMN_WRAP ( d->wordwrap == QtMultiLineEdit::FixedColumnWidth )
+#define BREAK_WITHIN_WORDS ( d->wrappolicy == QtMultiLineEdit::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 QtMultiLineEdit 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 QtMultiLineEdit widgets are shown.
+
+ \sa defaultTabStop()
+*/
+
+void QtMultiLineEdit::setDefaultTabStop( int ex )
+{
+ defTabStop = ex;
+}
+
+
+
+/*
+ Returns the distance between tab stops.
+
+ \sa setDefaultTabStop();
+*/
+
+int QtMultiLineEdit::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, QtMultiLineEdit with parent \a parent and
+ called \a name.
+*/
+
+QtMultiLineEdit::QtMultiLineEdit( QWidget *parent , const char *name )
+ :QtTableView( parent, name, WStaticContents | WRepaintNoErase )
+{
+ d = new QtMultiLineData;
+ QFontMetrics fm( font() );
+ setCellHeight( fm.lineSpacing() );
+ setNumCols( 1 );
+
+ contents = new QPtrList<QtMultiLineEditRow>;
+ contents->setAutoDelete( TRUE );
+
+ cursorX = 0; cursorY = 0;
+ curXPos = 0;
+
+ setTableFlags( Tbl_autoVScrollBar|Tbl_autoHScrollBar|
+ Tbl_smoothVScrolling |
+ Tbl_clipCellPainting
+ );
+ setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
+ setBackgroundMode( PaletteBase );
+ 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 QtMultiLineEditRow(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 ) );
+ }
+}
+
+/*
+ \fn int QtMultiLineEdit::lineLength( int line ) const
+ Returns the number of characters at line number \a line.
+*/
+
+/* \fn QString *QtMultiLineEdit::getString( int line ) const
+
+ Returns a pointer to the text at line \a line.
+*/
+
+/* \fn void QtMultiLineEdit::textChanged()
+
+ This signal is emitted when the text is changed by an event or by a
+ slot. Note that the signal is not emitted when you call a non-slot
+ function such as insertLine().
+
+ \sa returnPressed()
+*/
+
+/* \fn void QtMultiLineEdit::returnPressed()
+
+ This signal is emitted when the user presses the return or enter
+ key. It is not emitted if isReadOnly() is TRUE.
+
+ \sa textChanged()
+*/
+
+/*
+ \fn void QtMultiLineEdit::undoAvailable (bool yes)
+
+ This signal is emitted when the availability of undo changes.
+ If \a yes is TRUE, then undo() will work until
+ undoAvailable( FALSE ) is next emitted.
+*/
+
+/*
+ \fn void QtMultiLineEdit::redoAvailable (bool yes)
+
+ This signal is emitted when the availability of redo changes.
+ If \a yes is TRUE, then redo() will work until
+ redoAvailable( FALSE ) is next emitted.
+*/
+
+/*
+ \fn void QtMultiLineEdit::copyAvailable (bool yes)
+
+ This signal is emitted when the availability of cut/copy changes.
+ If \a yes is TRUE, then cut() and copy() will work until
+ copyAvailable( FALSE ) is next emitted.
+*/
+
+
+/*
+ If \a on is FALSE, this multi line edit accepts text input.
+ Scrolling and cursor movements are accepted in any case.
+
+ \sa isReadOnly() QWidget::setEnabled()
+*/
+
+void QtMultiLineEdit::setReadOnly( bool on )
+{
+ if ( readOnly != on ) {
+ readOnly = on;
+#ifndef QT_NO_CURSOR
+ setCursor( on ? arrowCursor : ibeamCursor );
+#endif
+ }
+}
+
+/*
+*/
+int QtMultiLineEdit::maxLineWidth() const
+{
+ return d->maxLineWidth;
+}
+
+/*
+ Destroys the QtMultiLineEdit
+*/
+
+QtMultiLineEdit::~QtMultiLineEdit()
+{
+ delete contents;
+ delete d;
+}
+
+static QPixmap *buffer = 0;
+
+static void cleanupMLBuffer()
+{
+ delete buffer;
+ buffer = 0;
+}
+
+static QPixmap *getCacheBuffer( QSize sz )
+{
+ if ( !buffer ) {
+ qAddPostRoutine( cleanupMLBuffer );
+ buffer = new QPixmap;
+ }
+
+ if ( buffer->width() < sz.width() || buffer->height() < sz.height() )
+ buffer->resize( sz );
+ return buffer;
+}
+
+/*
+ Implements the basic drawing logic. Paints the line at row \a row
+ using painter \a painter. The \a col parameter is ignored.
+*/
+void QtMultiLineEdit::paintCell( QPainter *painter, int row, int )
+{
+ const QColorGroup & g = colorGroup();
+ QFontMetrics fm( painter->font() );
+ QString s = stringShown(row);
+ if ( s.isNull() ) {
+ qWarning( "QtMultiLineEdit::paintCell: (%s) no text at line %d",
+ name( "unnamed" ), row );
+ return;
+ }
+ QRect updateR = cellUpdateRect();
+ QPixmap *buffer = getCacheBuffer( updateR.size() );
+ ASSERT(buffer);
+ buffer->fill ( g.base() );
+
+ QPainter p( buffer );
+ p.setFont( painter->font() );
+ p.translate( -updateR.left(), -updateR.top() );
+
+ p.setTabStops( tabStopDist(fm) );
+
+ int yPos = 0;
+ int markX1, markX2; // in x-coordinate pixels
+ markX1 = markX2 = 0; // avoid gcc warning
+ if ( markIsOn ) {
+ int markBeginX, markBeginY;
+ int markEndX, markEndY;
+ getMarkedRegion( &markBeginY, &markBeginX, &markEndY, &markEndX );
+ if ( row >= markBeginY && row <= markEndY ) {
+ if ( row == markBeginY ) {
+ markX1 = markBeginX;
+ if ( row == markEndY ) // both marks on same row
+ markX2 = markEndX;
+ else
+ markX2 = s.length(); // mark till end of line
+ } else {
+ if ( row == markEndY ) {
+ markX1 = 0;
+ markX2 = markEndX;
+ } else {
+ markX1 = 0; // whole line is marked
+ markX2 = s.length(); // whole line is marked
+ }
+ }
+ }
+ }
+ p.setPen( g.text() );
+ QtMultiLineEditRow* r = contents->at( row );
+ int wcell = cellWidth() - 2*d->lr_marg;// - d->marg_extra;
+ int wrow = r->w;
+ int x = d->lr_marg - p.fontMetrics().leftBearing(s[0]);
+ if ( d->align == Qt::AlignCenter || d->align == Qt::AlignHCenter )
+ x += (wcell - wrow) / 2;
+ else if ( d->align == Qt::AlignRight )
+ x += wcell - wrow;
+ p.drawText( x, yPos, cellWidth()-d->lr_marg-x, cellHeight(),
+ d->align == AlignLeft?ExpandTabs:0, s );
+ if ( !r->newline && BREAK_WITHIN_WORDS )
+ p.drawPixmap( x + wrow - d->lr_marg - d->marg_extra, yPos, d->arrow );
+#if 0
+ if ( r->newline )
+ p.drawLine( d->lr_marg, yPos+cellHeight()-2, cellWidth() - d->lr_marg, yPos+cellHeight()-2);
+#endif
+ if ( markX1 != markX2 ) {
+ int sLength = s.length();
+ int xpos1 = mapToView( markX1, row );
+ int xpos2 = mapToView( markX2, row );
+ int fillxpos1 = xpos1;
+ int fillxpos2 = xpos2;
+ if ( markX1 == 0 )
+ fillxpos1 -= 2;
+ if ( markX2 == sLength )
+ fillxpos2 += 3;
+ p.setClipping( TRUE );
+ p.setClipRect( fillxpos1 - updateR.left(), 0,
+ fillxpos2 - fillxpos1, cellHeight(row) );
+ p.fillRect( fillxpos1, 0, fillxpos2 - fillxpos1, cellHeight(row),
+ g.brush( QColorGroup::Highlight ) );
+ p.setPen( g.highlightedText() );
+ p.drawText( x, yPos, cellWidth()-d->lr_marg-x, cellHeight(),
+ d->align == AlignLeft?ExpandTabs:0, s );
+ p.setClipping( FALSE );
+ }
+
+ if ( row == cursorY && cursorOn && !readOnly ) {
+ int cursorPos = QMIN( (int)s.length(), cursorX );
+ int cXPos = QMAX( mapToView( cursorPos, row ), 0 );
+ int cYPos = 0;
+ if ( hasFocus() || d->dnd_forcecursor ) {
+ p.setPen( g.text() );
+ /* styled?
+ p.drawLine( cXPos - 2, cYPos,
+ cXPos + 2, cYPos );
+ */
+ p.drawLine( cXPos, cYPos,
+ cXPos, cYPos + fm.height() - 2);
+ /* styled?
+ p.drawLine( cXPos - 2, cYPos + fm.height() - 2,
+ cXPos + 2, cYPos + fm.height() - 2);
+ */
+
+#ifndef QT_NO_TRANSFORMATIONS
+ // TODO: set it other times, eg. when scrollbar moves view
+ QWMatrix wm = painter->worldMatrix();
+ setMicroFocusHint( int(wm.dx()+cXPos),
+ int (wm.dy()+cYPos),
+ 1, fm.ascent() );
+#else
+ setMicroFocusHint( cXPos,
+ cYPos,
+ 1, fm.ascent() );
+#endif
+ }
+ }
+ p.end();
+ painter->drawPixmap( updateR.left(), updateR.top(), *buffer,
+ 0, 0, updateR.width(), updateR.height() );
+}
+
+
+/*
+ \overload
+ Returns the width in pixels of the string \a s.
+ NOTE: only appropriate for whole lines.
+*/
+
+int QtMultiLineEdit::textWidth( const QString &s )
+{
+ int w = 0;
+ if ( !s.isNull() ) {
+ w = textWidthWithTabs( QFontMetrics( font() ), s, 0, s.length(),
+ d->align );
+ }
+ return w + 2 * d->lr_marg + d->marg_extra;
+}
+
+
+/*
+ Returns the width in pixels of the text at line \a line.
+*/
+
+int QtMultiLineEdit::textWidth( int line )
+{
+ if ( d->echomode == Password) {
+ QString s = stringShown(line);
+ return textWidth( s );
+ }
+ QtMultiLineEditRow* r = contents->at(line);
+ return r?r->w:0;
+}
+
+/*
+ Starts the cursor blinking.
+*/
+
+void QtMultiLineEdit::focusInEvent( QFocusEvent * )
+{
+ stopAutoScroll();
+ if ( !d->blinkTimer->isActive() )
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+ cursorOn = TRUE;
+ updateCell( cursorY, 0, FALSE );
+}
+
+
+/*\reimp
+*/
+void QtMultiLineEdit::leaveEvent( QEvent * )
+{
+}
+
+
+/*\reimp
+*/
+void QtMultiLineEdit::focusOutEvent( QFocusEvent * )
+{
+ stopAutoScroll();
+ d->blinkTimer->stop();
+ if ( cursorOn ) {
+ cursorOn = FALSE;
+ updateCell( cursorY, 0, FALSE );
+ }
+}
+
+
+/*
+ \reimp
+ Present for binary compatibility only!
+*/
+
+void QtMultiLineEdit::timerEvent( QTimerEvent * )
+{
+ // ############ Remove in 3.0!!!!!!!!
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void QtMultiLineEdit::doDrag()
+{
+ if ( d->dnd_timer ) {
+ d->dnd_timer->stop();
+ }
+ QDragObject *drag_text = new QTextDrag(markedText(), this);
+ if ( readOnly ) {
+ drag_text->dragCopy();
+ } else {
+ if ( drag_text->drag() && QDragObject::target() != this ) {
+ del();
+ if ( textDirty && !d->isHandlingEvent )
+ emit textChanged();
+ }
+ }
+ d->dnd_primed = FALSE;
+}
+#endif
+
+/*
+ If there is marked text, sets \a line1, \a col1, \a line2 and \a col2
+ to the start and end of the marked region and returns TRUE. Returns
+ FALSE if there is no marked text.
+ */
+bool QtMultiLineEdit::getMarkedRegion( int *line1, int *col1,
+ int *line2, int *col2 ) const
+{
+ if ( !markIsOn || !line1 || !line2 || !col1 || !col2 )
+ return FALSE;
+ if ( markAnchorY < markDragY ||
+ markAnchorY == markDragY && markAnchorX < markDragX) {
+ *line1 = markAnchorY;
+ *col1 = markAnchorX;
+ *line2 = markDragY;
+ *col2 = markDragX;
+ if ( *line2 > numLines() - 1 ) {
+ *line2 = numLines() - 1;
+ *col2 = lineLength( *line2 );
+ }
+ } else {
+ *line1 = markDragY;
+ *col1 = markDragX;
+ *line2 = markAnchorY;
+ *col2 = markAnchorX;
+ if ( *line2 > numLines() - 1 ) {
+ *line2 = numLines() - 1;
+ *col2 = lineLength( *line2 );
+ }
+ }
+ return markIsOn;
+}
+
+
+/*
+ Returns TRUE if there is marked text.
+*/
+
+bool QtMultiLineEdit::hasMarkedText() const
+{
+ return markIsOn;
+}
+
+
+/*
+ Returns a copy of the marked text.
+*/
+
+QString QtMultiLineEdit::markedText() const
+{
+ int markBeginX, markBeginY;
+ int markEndX, markEndY;
+ if ( !getMarkedRegion( &markBeginY, &markBeginX, &markEndY, &markEndX ) )
+ return QString();
+ if ( markBeginY == markEndY ) { //just one line
+ QString *s = getString( markBeginY );
+ return s->mid( markBeginX, markEndX - markBeginX );
+ } else { //multiline
+ QString *firstS, *lastS;
+ firstS = getString( markBeginY );
+ lastS = getString( markEndY );
+ int i;
+ QString tmp;
+ if ( firstS )
+ tmp += firstS->mid(markBeginX);
+ if ( contents->at( markBeginY )->newline )
+ tmp += '\n';
+
+ for( i = markBeginY + 1; i < markEndY ; i++ ) {
+ tmp += *getString(i);
+ if ( contents->at( i )->newline )
+ tmp += '\n';
+ }
+
+ if ( lastS ) {
+ tmp += lastS->left(markEndX);
+ } else {
+ tmp.truncate(tmp.length()-1);
+ }
+
+ return tmp;
+ }
+}
+
+
+
+/*
+ Returns the text at line number \a line (possibly the empty string),
+ or a \link QString::operator!() null string\endlink if \a line is invalid.
+*/
+
+QString QtMultiLineEdit::textLine( int line ) const
+{
+ QString *s = getString(line);
+ if ( s ) {
+ if ( s->isNull() )
+ return QString::fromLatin1("");
+ else
+ return *s;
+ } else
+ return QString::null;
+}
+
+
+/*
+ Returns a copy of the whole text. If the multi line edit contains no
+ text, a
+ \link QString::operator!() null string\endlink
+ is returned.
+*/
+
+QString QtMultiLineEdit::text() const
+{
+ QString tmp;
+ for( int i = 0 ; i < (int)contents->count() ; i++ ) {
+ tmp += *getString(i);
+ if ( i+1 < (int)contents->count() && contents->at(i)->newline )
+ tmp += '\n';
+ }
+ return tmp;
+}
+
+
+/*
+ Selects all text without moving the cursor.
+*/
+
+void QtMultiLineEdit::selectAll()
+{
+ markAnchorX = 0;
+ markAnchorY = 0;
+ markDragY = numLines() - 1;
+ markDragX = lineLength( markDragY );
+ turnMark( markDragX != markAnchorX || markDragY != markAnchorY );
+ if ( autoUpdate() )
+ update();
+}
+
+
+
+/*
+ Deselects all text (i.e. removes marking) and leaves the cursor at the
+ current position.
+*/
+
+void QtMultiLineEdit::deselect()
+{
+ turnMark( FALSE );
+}
+
+
+/*
+ Sets the text to \a s, removing old text, if any.
+*/
+
+void QtMultiLineEdit::setText( const QString &s )
+{
+ bool oldUndo = isUndoEnabled();
+ setUndoEnabled( FALSE );
+ bool oldAuto = autoUpdate();
+ setAutoUpdate( FALSE );
+ bool b = signalsBlocked();
+ blockSignals( TRUE );
+ clear();
+ CLEAR_UNDO
+ blockSignals( b );
+ insertLine( s, -1 );
+ emit textChanged();
+ setAutoUpdate(oldAuto);
+ if ( autoUpdate() )
+ update();
+ setUndoEnabled( oldUndo );
+}
+
+
+/*
+ Appends \a s to the text.
+*/
+
+void QtMultiLineEdit::append( const QString &s )
+{
+ bool oldUndo = isUndoEnabled();
+ setUndoEnabled( FALSE );
+ insertLine( s, -1 );
+ setUndoEnabled( oldUndo );
+ emit textChanged();
+}
+
+/* \reimp
+Passes wheel events to the vertical scrollbar.
+*/
+void QtMultiLineEdit::wheelEvent( QWheelEvent *e ){
+ QApplication::sendEvent( verticalScrollBar(), e);
+}
+
+
+/*
+ The key press event handler converts a key press in event \a e to
+ some line editor action.
+
+ Here are the default key bindings when isReadOnly() is FALSE:
+ \list
+ \i <i> Left Arrow </i> Move the cursor one character leftwards
+ \i <i> Right Arrow </i> Move the cursor one character rightwards
+ \i <i> Up Arrow </i> Move the cursor one line upwards
+ \i <i> Down Arrow </i> Move the cursor one line downwards
+ \i <i> Page Up </i> Move the cursor one page upwards
+ \i <i> Page Down </i> Move the cursor one page downwards
+ \i <i> Backspace </i> Delete the character to the left of the cursor
+ \i <i> Home </i> Move the cursor to the beginning of the line
+ \i <i> End </i> Move the cursor to the end of the line
+ \i <i> Delete </i> Delete the character to the right of the cursor
+ \i <i> Shift - Left Arrow </i> Mark text one character leftwards
+ \i <i> Shift - Right Arrow </i> Mark text one character rightwards
+ \i <i> Control-A </i> Move the cursor to the beginning of the line
+ \i <i> Control-B </i> Move the cursor one character leftwards
+ \i <i> Control-C </i> Copy the marked text to the clipboard
+ \i <i> Control-D </i> Delete the character to the right of the cursor
+ \i <i> Control-E </i> Move the cursor to the end of the line
+ \i <i> Control-F </i> Move the cursor one character rightwards
+ \i <i> Control-H </i> Delete the character to the left of the cursor
+ \i <i> Control-K </i> Delete to end of line
+ \i <i> Control-N </i> Move the cursor one line downwards
+ \i <i> Control-P </i> Move the cursor one line upwards
+ \i <i> Control-V </i> Paste the clipboard text into line edit
+ \i <i> Control-X </i> Cut the marked text, copy to clipboard
+ \i <i> Control-Z </i> Undo the last operation
+ \i <i> Control-Y </i> Redo the last operation
+ \i <i> Control - Left Arrow </i> Move the cursor one word leftwards
+ \i <i> Control - Right Arrow </i> Move the cursor one word rightwards
+ \i <i> Control - Up Arrow </i> Move the cursor one word upwards
+ \i <i> Control - Down Arrow </i> Move the cursor one word downwards
+ \i <i> Control - Home Arrow </i> Move the cursor to the beginning of the text
+ \i <i> Control - End Arrow </i> Move the cursor to the end of the text
+ \endlist
+ In addition, the following key bindings are used on Windows:
+ \list
+ \i <i> Shift - Delete </i> Cut the marked text, copy to clipboard
+ \i <i> Shift - Insert </i> Paste the clipboard text into line edit
+ \i <i> Control - Insert </i> Copy the marked text to the clipboard
+ \endlist
+ All other keys with valid ASCII codes insert themselves into the line.
+
+ Here are the default key bindings when isReadOnly() is TRUE:
+ \list
+ \i <i> Left Arrow </i> Scrolls the table rightwards
+ \i <i> Right Arrow </i> Scrolls the table rightwards
+ \i <i> Up Arrow </i> Scrolls the table one line downwards
+ \i <i> Down Arrow </i> Scrolls the table one line upwards
+ \i <i> Page Up </i> Scrolls the table one page downwards
+ \i <i> Page Down </i> Scrolls the table one page upwards
+ \i <i> Control-C </i> Copy the marked text to the clipboard
+ \endlist
+
+*/
+
+void QtMultiLineEdit::keyPressEvent( QKeyEvent *e )
+{
+ textDirty = FALSE;
+ d->isHandlingEvent = TRUE;
+ int unknown = 0;
+ if ( readOnly ) {
+ int pageSize = viewHeight() / cellHeight();
+
+ switch ( e->key() ) {
+ case Key_Left:
+ setXOffset( xOffset() - viewWidth()/10 );
+ break;
+ case Key_Right:
+ setXOffset( xOffset() + viewWidth()/10 );
+ break;
+ case Key_Up:
+ setTopCell( topCell() - 1 );
+ break;
+ case Key_Down:
+ setTopCell( topCell() + 1 );
+ break;
+ case Key_Home:
+ setCursorPosition(0,0, e->state() & ShiftButton );
+ break;
+ case Key_End:
+ setCursorPosition( numLines()-1, lineLength( numLines()-1 ),
+ e->state() & ShiftButton );
+ break;
+ case Key_Next:
+ setTopCell( topCell() + pageSize );
+ break;
+ case Key_Prior:
+ setTopCell( QMAX( topCell() - pageSize, 0 ) );
+ break;
+#ifndef QT_NO_CLIPBOARD
+ case Key_C:
+ if ( echoMode() == Normal && (e->state()&ControlButton) )
+ copy();
+ else
+ unknown++;
+ break;
+ case Key_F16: // Copy key on Sun keyboards
+ if ( echoMode() == Normal )
+ copy();
+ else
+ unknown++;
+ break;
+#endif
+ default:
+ unknown++;
+ }
+ if ( unknown )
+ e->ignore();
+ d->isHandlingEvent = FALSE;
+ return;
+ }
+ if ( e->text().length() &&
+ e->key() != Key_Return &&
+ e->key() != Key_Enter &&
+ e->key() != Key_Delete &&
+ e->key() != Key_Backspace &&
+ (!e->ascii() || e->ascii()>=32)
+ ) {
+ insert( e->text() );
+ //QApplication::sendPostedEvents( this, QEvent::Paint );
+ if ( textDirty )
+ emit textChanged();
+ d->isHandlingEvent = FALSE;
+ return;
+ }
+ if ( e->state() & ControlButton ) {
+ switch ( e->key() ) {
+ case Key_A:
+ home( e->state() & ShiftButton );
+ break;
+ case Key_B:
+ cursorLeft( e->state() & ShiftButton );
+ break;
+#ifndef QT_NO_CLIPBOARD
+ case Key_C:
+ if ( echoMode() == Normal )
+ copy();
+ break;
+#endif
+ case Key_D:
+ del();
+ break;
+ case Key_E:
+ end( e->state() & ShiftButton );
+ break;
+ case Key_Left:
+ cursorWordBackward( e->state() & ShiftButton );
+ break;
+ case Key_Right:
+ cursorWordForward( e->state() & ShiftButton );
+ break;
+ case Key_Up:
+ cursorUp( e->state() & ShiftButton );
+ break;
+ case Key_Down:
+ cursorDown( e->state() & ShiftButton );
+ break;
+ case Key_Home:
+ setCursorPosition(0,0, e->state() & ShiftButton );
+ break;
+ case Key_End:
+ setCursorPosition( numLines()-1, lineLength( numLines()-1 ),
+ e->state() & ShiftButton );
+ break;
+ case Key_F:
+ cursorRight( e->state() & ShiftButton );
+ break;
+ case Key_H:
+ backspace();
+ break;
+ case Key_K:
+ killLine();
+ break;
+ case Key_N:
+ cursorDown( e->state() & ShiftButton );
+ break;
+ case Key_P:
+ cursorUp( e->state() & ShiftButton );
+ break;
+#ifndef QT_NO_CLIPBOARD
+ case Key_V:
+ paste();
+ break;
+ case Key_X:
+ cut();
+ break;
+#endif
+ case Key_Z:
+ undo();
+ break;
+ case Key_Y:
+ redo();
+ break;
+#if defined (_WS_WIN_)
+ case Key_Insert:
+ copy();
+#endif
+ default:
+ unknown++;
+ }
+ } else {
+ switch ( e->key() ) {
+ case Key_Left:
+ cursorLeft( e->state() & ShiftButton );
+ break;
+ case Key_Right:
+ cursorRight( e->state() & ShiftButton );
+ break;
+ case Key_Up:
+ cursorUp( e->state() & ShiftButton );
+ break;
+ case Key_Down:
+ cursorDown( e->state() & ShiftButton );
+ break;
+ case Key_Backspace:
+ backspace();
+ break;
+ case Key_Home:
+ home( e->state() & ShiftButton );
+ break;
+ case Key_End:
+ end( e->state() & ShiftButton );
+ break;
+ case Key_Delete:
+#if defined (_WS_WIN_)
+ if ( e->state() & ShiftButton ) {
+ cut();
+ break;
+ }
+#endif
+ del();
+ break;
+ case Key_Next:
+ pageDown( e->state() & ShiftButton );
+ break;
+ case Key_Prior:
+ pageUp( e->state() & ShiftButton );
+ break;
+ case Key_Enter:
+ case Key_Return:
+ newLine();
+ emit returnPressed();
+ break;
+ case Key_Tab:
+ insert( e->text() );
+ break;
+#if defined (_WS_WIN_)
+ case Key_Insert:
+ if ( e->state() & ShiftButton )
+ paste();
+ else
+ unknown++;
+ break;
+#endif
+ case Key_F14: // Undo key on Sun keyboards
+ undo();
+ break;
+#ifndef QT_NO_CLIPBOARD
+ case Key_F16: // Copy key on Sun keyboards
+ if ( echoMode() == Normal )
+ copy();
+ break;
+ case Key_F18: // Paste key on Sun keyboards
+ paste();
+ break;
+ case Key_F20: // Paste key on Sun keyboards
+ cut();
+ break;
+#endif
+ default:
+ unknown++;
+ }
+ }
+ if ( textDirty )
+ emit textChanged();
+
+ if ( unknown ) // unknown key
+ e->ignore();
+
+ d->isHandlingEvent = FALSE;
+}
+
+
+/*
+ Moves the cursor one page down. If \a mark is TRUE, the text
+ is marked.
+*/
+
+void QtMultiLineEdit::pageDown( bool mark )
+{
+ bool oldAuto = autoUpdate();
+ if ( mark )
+ setAutoUpdate( FALSE );
+
+ if ( partiallyInvisible( cursorY ) )
+ cursorY = topCell();
+ int delta = cursorY - topCell();
+ int pageSize = viewHeight() / cellHeight();
+ int newTopCell = QMIN( topCell() + pageSize, numLines() - 1 - pageSize );
+
+ if ( pageSize >= numLines() ) { // quick fix to handle small texts
+ newTopCell = topCell();
+ }
+ if ( !curXPos )
+ curXPos = mapToView( cursorX, cursorY );
+ int oldY = cursorY;
+
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ if ( newTopCell != topCell() ) {
+ cursorY = newTopCell + delta;
+ cursorX = mapFromView( curXPos, cursorY );
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ setTopCell( newTopCell );
+ } else if ( cursorY != (int)contents->count() - 1) { // just move the cursor
+ cursorY = QMIN( cursorY + pageSize, numLines() - 1);
+ cursorX = mapFromView( curXPos, cursorY );
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ makeVisible();
+ }
+ if ( oldAuto )
+ if ( mark ) {
+ setAutoUpdate( TRUE );
+ update();
+ } else {
+ updateCell( oldY, 0, FALSE );
+ }
+ if ( !mark )
+ turnMark( FALSE );
+}
+
+
+/*
+ Moves the cursor one page up. If \a mark is TRUE, the text
+ is marked.
+*/
+
+void QtMultiLineEdit::pageUp( bool mark )
+{
+ bool oldAuto = autoUpdate();
+ if ( mark )
+ setAutoUpdate( FALSE );
+ if ( partiallyInvisible( cursorY ) )
+ cursorY = topCell();
+ int delta = cursorY - topCell();
+ int pageSize = viewHeight() / cellHeight();
+ bool partial = delta == pageSize && viewHeight() != pageSize * cellHeight();
+ int newTopCell = QMAX( topCell() - pageSize, 0 );
+ if ( pageSize > numLines() ) { // quick fix to handle small texts
+ newTopCell = 0;
+ delta = 0;
+ }
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ if ( !curXPos )
+ curXPos = mapToView( cursorX, cursorY );
+ int oldY = cursorY;
+ if ( newTopCell != topCell() ) {
+ cursorY = QMIN( newTopCell + delta, numLines() - 1 );
+ if ( partial )
+ cursorY--;
+ cursorX = mapFromView( curXPos, cursorY );
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ setTopCell( newTopCell );
+ } else { // just move the cursor
+ cursorY = QMAX( cursorY - pageSize, 0 );
+ cursorX = mapFromView( curXPos, cursorY );
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ }
+ if ( oldAuto )
+ if ( mark ) {
+ setAutoUpdate( TRUE );
+ update();
+ } else {
+ updateCell( oldY, 0, FALSE );
+ }
+ if ( !mark )
+ turnMark( FALSE );
+}
+
+// THE CORE INSERTION FUNCTION
+void QtMultiLineEdit::insertAtAux( const QString &txt, int line, int col, bool mark )
+{
+ dummy = FALSE;
+ d->blinkTimer->stop();
+ cursorOn = TRUE;
+ int oldw = contentsRect().width();
+
+ line = QMAX( QMIN( line, numLines() - 1), 0 );
+ col = QMAX( QMIN( col, lineLength( line )), 0 );
+
+ QString itxt = txt;
+ QtMultiLineEditRow *row = contents->at( line );
+ if ( d->maxlen >= 0 && length() + int(txt.length()) > d->maxlen )
+ itxt.truncate( d->maxlen - length() );
+
+ row->s.insert( uint(col), itxt );
+
+ if ( mark ) {
+ markAnchorX = col;
+ markAnchorY = line;
+ }
+ if ( cursorX == col && cursorY == line ) {
+ cursorX += itxt.length();
+ }
+ QFontMetrics fm( font() );
+ if ( !WORD_WRAP || ( col == 0 && itxt.contains('\n') == int(itxt.length())) )
+ wrapLine( line, 0 );
+ else if ( WORD_WRAP && itxt.find('\n')<0 && itxt.find('\t')<0
+ && (
+ ( DYNAMIC_WRAP && fm.width( itxt ) + row->w < contentsRect().width() - 2*d->lr_marg - d->marg_extra )
+ ||
+ ( FIXED_WIDTH_WRAP && ( d->wrapcol < 0 || fm.width( itxt ) + row->w < d->wrapcol ) )
+ ||
+ ( FIXED_COLUMN_WRAP && ( d->wrapcol < 0 || int(row->s.length()) < d->wrapcol ) )
+ )
+ && ( itxt.find(' ') < 0 || row->s.find(' ') >= 0 && row->s.find(' ') < col ) ){
+ row->w = textWidth( row->s );
+ setWidth( QMAX( maxLineWidth(), row->w) );
+ updateCell( line, 0, FALSE );
+ }
+ else {
+ if ( line > 0 && !contents->at( line-1)->newline )
+ rebreakParagraph( line-1 );
+ else
+ rebreakParagraph( line );
+ }
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+
+ setNumRowsAndTruncate();
+
+ textDirty = TRUE;
+ d->edited = TRUE;
+ if ( autoUpdate() ) {
+ makeVisible();
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+ if ( DYNAMIC_WRAP && oldw != contentsRect().width() ) {
+ setAutoUpdate( FALSE );
+ rebreakAll();
+ setAutoUpdate( TRUE );
+ update();
+ }
+ }
+}
+
+
+/*
+ Inserts \a txt at line number \a line. If \a line is less than zero,
+ or larger than the number of rows, the new text is put at the end.
+ If \a txt contains newline characters, several lines are inserted.
+
+ The cursor position is not changed.
+*/
+
+void QtMultiLineEdit::insertLine( const QString &txt, int line )
+{
+ QString s = txt;
+ int oldXPos = cursorX;
+ int oldYPos = cursorY;
+ if ( line < 0 || line >= int( contents->count() ) ) {
+ if ( !dummy )
+ contents->append( new QtMultiLineEditRow(QString::fromLatin1(""), 0) );
+ insertAt( s, numLines()-1, 0 );
+ } else {
+ s.append('\n');
+ insertAt( s, line, 0 );
+ }
+ cursorX = oldXPos;
+ cursorY = oldYPos;
+}
+
+/*
+ Deletes the line at line number \a line. If \a
+ line is less than zero, or larger than the number of lines,
+ no line is deleted.
+*/
+
+void QtMultiLineEdit::removeLine( int line )
+{
+ CLEAR_UNDO
+ if ( line >= numLines() )
+ return;
+ if ( cursorY >= line && cursorY > 0 )
+ cursorY--;
+ bool updt = autoUpdate() && rowIsVisible( line );
+ QtMultiLineEditRow* r = contents->at( line );
+ ASSERT( r );
+ bool recalc = r->w == maxLineWidth();
+ contents->remove( line );
+ if ( contents->count() == 0 ) {
+ int w = textWidth( QString::fromLatin1("") );
+ contents->append( new QtMultiLineEditRow(QString::fromLatin1(""), w) );
+ setWidth( w );
+ dummy = TRUE;
+ }
+ if ( setNumRowsAndTruncate() )
+ recalc = updt = FALSE;
+ if ( recalc )
+ updateCellWidth();
+ makeVisible();
+ if (updt)
+ update();
+ textDirty = TRUE;
+ d->edited = TRUE;
+}
+
+/*
+ Inserts \a s at the current cursor position.
+*/
+void QtMultiLineEdit::insert( const QString& s )
+{
+ insert( s, FALSE );
+}
+
+/*
+ Inserts \a c at the current cursor position.
+ (this function is provided for backward compatibility -
+ it simply calls insert()).
+*/
+void QtMultiLineEdit::insertChar( QChar c )
+{
+ insert(c);
+}
+
+/*
+ \overload
+ Inserts string \a str at the current cursor position. If \a mark is
+ TRUE the string is marked.
+*/
+
+void QtMultiLineEdit::insert( const QString& str, bool mark )
+{
+ dummy = FALSE;
+ bool wasMarkedText = hasMarkedText();
+ if ( wasMarkedText )
+ addUndoCmd( new QBeginCommand );
+ if ( wasMarkedText )
+ del(); // ## Will flicker
+ QString *s = getString( cursorY );
+ if ( cursorX > (int)s->length() )
+ cursorX = s->length();
+ else if ( overWrite && !wasMarkedText && cursorX < (int)s->length() )
+ del(); // ## Will flicker
+ insertAt(str, cursorY, cursorX, mark );
+ makeVisible();
+
+ if ( wasMarkedText )
+ addUndoCmd( new QEndCommand() );
+}
+
+/*
+ Makes a line break at the current cursor position.
+*/
+
+void QtMultiLineEdit::newLine()
+{
+ insert("\n");
+}
+
+/*
+ Deletes text from the current cursor position to the end of the line.
+*/
+
+void QtMultiLineEdit::killLineAux()
+{
+ deselect(); // -sanders Don't let del() delete marked region
+ QtMultiLineEditRow* r = contents->at( cursorY );
+ if ( cursorX == (int)r->s.length() ) {
+ // if (r->newline) // -sanders Only del newlines!
+ del();
+ return;
+ } else {
+ bool recalc = r->w == maxLineWidth();
+ r->s.remove( cursorX, r->s.length() );
+ r->w = textWidth( r->s );
+ updateCell( cursorY, 0, FALSE );
+ if ( recalc )
+ updateCellWidth();
+ rebreakParagraph( cursorY ); // -sanders
+ textDirty = TRUE;
+ d->edited = TRUE;
+ }
+ curXPos = 0;
+ makeVisible();
+ turnMark( FALSE );
+}
+
+
+/*
+ Moves the cursor one character to the left. If \a mark is TRUE, the text
+ is marked. If \a wrap is TRUE, the cursor moves to the end of the
+ previous line if it is placed at the beginning of the current line.
+
+ \sa cursorRight() cursorUp() cursorDown()
+*/
+
+void QtMultiLineEdit::cursorLeft( bool mark, bool wrap )
+{
+ cursorLeft(mark,!mark,wrap);
+}
+void QtMultiLineEdit::cursorLeft( bool mark, bool clear_mark, bool wrap )
+{
+ if ( cursorX != 0 || cursorY != 0 && wrap ) {
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ d->blinkTimer->stop();
+ int ll = lineLength( cursorY );
+ if ( cursorX > ll )
+ cursorX = ll;
+ cursorOn = TRUE;
+ cursorX--;
+ if ( cursorX < 0 ) {
+ int oldY = cursorY;
+ if ( cursorY > 0 ) {
+ cursorY--;
+ cursorX = lineLength( cursorY );
+ if ( cursorX > 1 && !isEndOfParagraph( cursorY ) )
+ cursorX--;
+ } else {
+ cursorY = 0; //### ?
+ cursorX = 0;
+ }
+ updateCell( oldY, 0, FALSE );
+ }
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+ updateCell( cursorY, 0, FALSE );
+ }
+ curXPos = 0;
+ makeVisible();
+ if ( clear_mark )
+ turnMark( FALSE );
+}
+
+/*
+ Moves the cursor one character to the right. If \a mark is TRUE, the text
+ is marked. If \a wrap is TRUE, the cursor moves to the beginning of the next
+ line if it is placed at the end of the current line.
+ \sa cursorLeft() cursorUp() cursorDown()
+*/
+
+void QtMultiLineEdit::cursorRight( bool mark, bool wrap )
+{
+ cursorRight(mark,!mark,wrap);
+}
+void QtMultiLineEdit::cursorRight( bool mark, bool clear_mark, bool wrap )
+{
+ int strl = lineLength( cursorY );
+ if ( strl > 1 && !isEndOfParagraph( cursorY ) )
+ strl--;
+ if ( cursorX < strl || cursorY < (int)contents->count() - 1 && wrap ) {
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ d->blinkTimer->stop();
+ cursorOn = TRUE;
+ cursorX++;
+ if ( cursorX > strl ) {
+ int oldY = cursorY;
+ if ( cursorY < (int) contents->count() - 1 ) {
+ cursorY++;
+ cursorX = 0;
+ } else {
+ cursorX = lineLength( cursorY );
+ }
+ updateCell( oldY, 0, FALSE );
+ }
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ updateCell( cursorY, 0, FALSE );
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+ }
+ curXPos = 0;
+ makeVisible();
+ if ( clear_mark )
+ turnMark( FALSE );
+}
+
+/*
+ Moves the cursor up one line. If \a mark is TRUE, the text
+ is marked.
+ \sa cursorDown() cursorLeft() cursorRight()
+*/
+
+void QtMultiLineEdit::cursorUp( bool mark )
+{
+ cursorUp(mark,!mark);
+}
+void QtMultiLineEdit::cursorUp( bool mark, bool clear_mark )
+{
+ if ( cursorY != 0 ) {
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ if ( !curXPos )
+ curXPos = mapToView( cursorX, cursorY );
+ int oldY = cursorY;
+ d->blinkTimer->stop();
+ cursorOn = TRUE;
+ cursorY--;
+ if ( cursorY < 0 ) {
+ cursorY = 0;
+ }
+ cursorX = mapFromView( curXPos, cursorY );
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ updateCell( oldY, 0, FALSE );
+ updateCell( cursorY, 0, FALSE );
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+ }
+ makeVisible();
+ if ( clear_mark )
+ turnMark( FALSE );
+}
+
+/*
+ Moves the cursor one line down. If \a mark is TRUE, the text
+ is marked.
+ \sa cursorUp() cursorLeft() cursorRight()
+*/
+
+void QtMultiLineEdit::cursorDown( bool mark )
+{
+ cursorDown(mark,!mark);
+}
+void QtMultiLineEdit::cursorDown( bool mark, bool clear_mark )
+{
+ int lastLin = contents->count() - 1;
+ if ( cursorY != lastLin ) {
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ if ( !curXPos )
+ curXPos = mapToView( cursorX, cursorY );
+ int oldY = cursorY;
+ d->blinkTimer->stop();
+ cursorOn = TRUE;
+ cursorY++;
+ if ( cursorY > lastLin ) {
+ cursorY = lastLin;
+ }
+ cursorX = mapFromView( curXPos, cursorY );
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ updateCell( oldY, 0, FALSE );
+ updateCell( cursorY, 0, FALSE );
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+ }
+ makeVisible();
+ if ( clear_mark )
+ turnMark( FALSE );
+}
+
+/*
+ Turns off marked text
+*/
+void QtMultiLineEdit::turnMark( bool on )
+{
+ if ( on != markIsOn ) {
+ markIsOn = on;
+ if ( echoMode() == Normal )
+ emit copyAvailable( on );
+ update();
+ }
+}
+
+
+
+
+/*
+ Deletes the character on the left side of the text cursor and moves
+ the cursor one position to the left. If a text has been marked by
+ the user (e.g. by clicking and dragging) the cursor is put at the
+ beginning of the marked text and the marked text is removed.
+ \sa del()
+*/
+
+void QtMultiLineEdit::backspace()
+{
+ if ( hasMarkedText() ) {
+ del();
+ } else {
+ if ( !atBeginning() ) {
+ cursorLeft( FALSE );
+ del();
+ }
+ }
+ makeVisible();
+}
+
+void QtMultiLineEdit::delAux()
+{
+ int markBeginX, markBeginY;
+ int markEndX, markEndY;
+ QRect oldContents = contentsRect();
+ if ( getMarkedRegion( &markBeginY, &markBeginX, &markEndY, &markEndX ) ) {
+ turnMark( FALSE );
+ textDirty = TRUE;
+ d->edited = TRUE;
+ if ( markBeginY == markEndY ) { //just one line
+ QtMultiLineEditRow *r = contents->at( markBeginY );
+ ASSERT(r);
+ bool recalc = r->w == maxLineWidth();
+ r->s.remove( markBeginX, markEndX - markBeginX );
+ r->w = textWidth( r->s );
+ cursorX = markBeginX;
+ cursorY = markBeginY;
+
+ if (autoUpdate() )
+ updateCell( cursorY, 0, FALSE );
+ if ( recalc )
+ updateCellWidth();
+ } else { //multiline
+ bool oldAuto = autoUpdate();
+ setAutoUpdate( FALSE );
+ ASSERT( markBeginY >= 0);
+ ASSERT( markEndY < (int)contents->count() );
+
+ QtMultiLineEditRow *firstR, *lastR;
+ firstR = contents->at( markBeginY );
+ lastR = contents->at( markEndY );
+ ASSERT( firstR != lastR );
+ firstR->s.remove( markBeginX, firstR->s.length() - markBeginX );
+ lastR->s.remove( 0, markEndX );
+ firstR->s.append( lastR->s ); // lastS will be removed in loop below
+ firstR->newline = lastR->newline; // Don't forget this -sanders
+ firstR->w = textWidth( firstR->s );
+
+ for( int i = markBeginY + 1 ; i <= markEndY ; i++ )
+ contents->remove( markBeginY + 1 );
+
+ if ( contents->isEmpty() )
+ insertLine( QString::fromLatin1(""), -1 );
+
+ cursorX = markBeginX;
+ cursorY = markBeginY;
+ curXPos = 0;
+
+ setNumRowsAndTruncate();
+ updateCellWidth();
+ setAutoUpdate( oldAuto );
+ if ( autoUpdate() )
+ update();
+ }
+ markAnchorY = markDragY = cursorY;
+ markAnchorX = markDragX = cursorX;
+ } else {
+ if ( !atEnd() ) {
+ textDirty = TRUE;
+ d->edited = TRUE;
+ QtMultiLineEditRow *r = contents->at( cursorY );
+ if ( cursorX == (int) r->s.length() ) { // remove newline
+ QtMultiLineEditRow* other = contents->at( cursorY + 1 );
+ if ( ! r->newline && cursorX )
+ r->s.truncate( r->s.length()-1 );
+
+ bool needBreak = !r->s.isEmpty();
+ r->s += other->s;
+ r->newline = other->newline;
+ contents->remove( cursorY + 1 );
+ if ( needBreak )
+ rebreakParagraph( cursorY, 1 );
+ else
+ wrapLine( cursorY, 1 );
+ } else {
+ bool recalc = r->w == maxLineWidth();
+ r->s.remove( cursorX, 1 );
+ rebreakParagraph( cursorY );
+ if ( recalc )
+ updateCellWidth();
+ }
+ }
+ }
+ if ( DYNAMIC_WRAP && oldContents != contentsRect() ) {
+ if ( oldContents.width() != contentsRect().width() ) {
+ bool oldAuto = autoUpdate();
+ setAutoUpdate( FALSE );
+ rebreakAll();
+ setAutoUpdate( oldAuto );
+ }
+ if ( autoUpdate() )
+ update();
+ }
+ curXPos = 0;
+ makeVisible();
+}
+
+/*
+ Moves the text cursor to the left end of the line. If \a mark is
+ TRUE, text is marked towards the first position. If it is FALSE and
+ the cursor is moved, all marked text is unmarked.
+
+ \sa end()
+*/
+
+void QtMultiLineEdit::home( bool mark )
+{
+ if ( cursorX != 0 ) {
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ d->blinkTimer->stop();
+ cursorX = 0;
+ cursorOn = TRUE;
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ updateCell( cursorY, 0, FALSE );
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+ }
+ curXPos = 0;
+ if ( !mark )
+ turnMark( FALSE );
+ makeVisible();
+}
+
+/*
+ Moves the text cursor to the right end of the line. If \a mark is TRUE
+ text is marked towards the last position. If it is FALSE and the
+ cursor is moved, all marked text is unmarked.
+
+ \sa home()
+*/
+
+void QtMultiLineEdit::end( bool mark )
+{
+ int tlen = lineLength( cursorY );
+ if ( cursorX != tlen ) {
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ d->blinkTimer->stop();
+ cursorX = tlen;
+ cursorOn = TRUE;
+ if ( mark )
+ newMark( cursorX, cursorY, FALSE );
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+ updateCell( cursorY, 0, FALSE );
+ }
+ curXPos = 0;
+ makeVisible();
+ if ( !mark )
+ turnMark( FALSE );
+}
+
+/*\reimp
+*/
+void QtMultiLineEdit::mousePressEvent( QMouseEvent *e )
+{
+ stopAutoScroll();
+ d->dnd_startpos = e->pos();
+
+ if ( e->button() == RightButton ) {
+ QPopupMenu *popup = new QPopupMenu( this );
+ int id[ (int)IdCount ];
+ id[ IdUndo ] = popup->insertItem( tr( "Undo" ) );
+ id[ IdRedo ] = popup->insertItem( tr( "Redo" ) );
+ popup->insertSeparator();
+#ifndef QT_NO_CLIPBOARD
+ id[ IdCut ] = popup->insertItem( tr( "Cut" ) );
+ id[ IdCopy ] = popup->insertItem( tr( "Copy" ) );
+ id[ IdPaste ] = popup->insertItem( tr( "Paste" ) );
+#ifndef QT_NO_MIMECLIPBOARD
+ id[ IdPasteSpecial ] = popup->insertItem( tr( "Paste special..." ) );
+#endif
+#endif
+ id[ IdClear ] = popup->insertItem( tr( "Clear" ) );
+ popup->insertSeparator();
+ id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) );
+ popup->setItemEnabled( id[ IdUndo ],
+ !this->d->undoList.isEmpty() );
+ popup->setItemEnabled( id[ IdRedo ],
+ !this->d->redoList.isEmpty() );
+#ifndef QT_NO_CLIPBOARD
+ popup->setItemEnabled( id[ IdCut ],
+ !isReadOnly() && hasMarkedText() );
+ popup->setItemEnabled( id[ IdCopy ], hasMarkedText() );
+ popup->setItemEnabled( id[ IdPaste ],
+ !isReadOnly() && (bool)QApplication::clipboard()->text().length() );
+#ifndef QT_NO_MIMECLIPBOARD
+ // Any non-plain types?
+ QMimeSource* ms = QApplication::clipboard()->data();
+ bool ps = FALSE;
+ if ( ms ) {
+ if ( !isReadOnly() ) {
+ const char* fmt;
+ for (int i=0; !ps && (fmt=ms->format(i)); i++) {
+ ps = qstrnicmp(fmt,"text/",5)==0
+ && qstrnicmp(fmt+5,"plain",5)!=0;
+ }
+ }
+ }
+ popup->setItemEnabled( id[ IdPasteSpecial ], ps );
+#endif
+#endif
+ popup->setItemEnabled( id[ IdClear ],
+ !isReadOnly() && (bool)text().length() );
+ int allSelected = markIsOn && markAnchorX == 0 && markAnchorY == 0 &&
+ markDragY == numLines() - 1 && markDragX == lineLength( markDragY );
+ popup->setItemEnabled( id[ IdSelectAll ],
+ (bool)text().length() && !allSelected );
+
+ int r = popup->exec( e->globalPos() );
+ delete popup;
+
+ if ( r == id[ IdUndo ] )
+ undo();
+ else if ( r == id[ IdRedo ] )
+ redo();
+#ifndef QT_NO_CLIPBOARD
+ else if ( r == id[ IdCut ] )
+ cut();
+ else if ( r == id[ IdCopy ] )
+ copy();
+ else if ( r == id[ IdPaste ] )
+ paste();
+# ifndef QT_NO_MIMECLIPBOARD
+ else if ( r == id[ IdPasteSpecial ] )
+ pasteSpecial(QCursor::pos());
+# endif
+#endif
+ else if ( r == id[ IdClear ] )
+ clear();
+ else if ( r == id[ IdSelectAll ] )
+ selectAll();
+ return;
+ }
+
+ if ( e->button() != MidButton && e->button() != LeftButton)
+ return;
+
+ int newX, newY;
+ pixelPosToCursorPos( e->pos(), &newX, &newY );
+
+ if ( e->state() & ShiftButton ) {
+ wordMark = FALSE;
+ dragMarking = TRUE;
+ setCursorPosition( newY, newX, TRUE);
+ return;
+ }
+
+#ifndef QT_NO_DRAGANDDROP
+ if (
+ inMark(newX, newY) // Click on highlighted text
+ && echoMode() == Normal // No DnD of passwords, etc.
+ && e->pos().y() < totalHeight() // Click past the end is not dragging
+ )
+ {
+ // The user might be trying to drag
+ d->dnd_primed = TRUE;
+ d->dnd_timer->start( QApplication::startDragTime(), FALSE );
+ } else
+#endif
+ {
+ wordMark = FALSE;
+ dragMarking = TRUE;
+ setCursorPixelPosition(e->pos());
+ }
+}
+
+void QtMultiLineEdit::pixelPosToCursorPos(QPoint p, int* x, int* y) const
+{
+ *y = findRow( p.y() );
+ if ( *y < 0 ) {
+ if ( p.y() < lineWidth() ) {
+ *y = topCell();
+ } else {
+ *y = lastRowVisible();
+ p.setX(cellWidth());
+ }
+ }
+ *y = QMIN( (int)contents->count() - 1, *y );
+ QFontMetrics fm( font() );
+ *x = xPosToCursorPos( stringShown( *y ), fm,
+ p.x() - d->lr_marg + xOffset(),
+ cellWidth() - 2 * d->lr_marg - d->marg_extra,
+ d->align );
+ QtMultiLineEditRow* r = contents->at( *y );
+ if (r && !r->newline && ((unsigned int)*x == r->s.length()) && (*x > 0))
+ --*x;
+}
+
+void QtMultiLineEdit::setCursorPixelPosition(QPoint p, bool clear_mark)
+{
+ int newY;
+ pixelPosToCursorPos( p, &cursorX, &newY );
+ curXPos = 0;
+ if ( clear_mark ) {
+ markAnchorX = cursorX;
+ markAnchorY = newY;
+ bool markWasOn = markIsOn;
+ turnMark( FALSE );
+ if ( markWasOn ) {
+ cursorY = newY;
+ update();
+ d->isHandlingEvent = FALSE;
+ return;
+ }
+ }
+ if ( cursorY != newY ) {
+ int oldY = cursorY;
+ cursorY = newY;
+ updateCell( oldY, 0, FALSE );
+ }
+ updateCell( cursorY, 0, FALSE ); // ###
+}
+
+void QtMultiLineEdit::startAutoScroll()
+{
+ if ( !dragScrolling ) {
+ d->scrollTime = initialScrollTime;
+ d->scrollAccel = initialScrollAccel;
+ d->scrollTimer->start( d->scrollTime, FALSE );
+ dragScrolling = TRUE;
+ }
+}
+
+void QtMultiLineEdit::stopAutoScroll()
+{
+ if ( dragScrolling ) {
+ d->scrollTimer->stop();
+ dragScrolling = FALSE;
+ }
+}
+
+/*\reimp
+*/
+void QtMultiLineEdit::mouseMoveEvent( QMouseEvent *e )
+{
+#ifndef QT_NO_DRAGANDDROP
+ d->dnd_timer->stop();
+ if ( d->dnd_primed &&
+ ( d->dnd_startpos - e->pos() ).manhattanLength() > QApplication::startDragDistance() ) {
+ doDrag();
+ return;
+ }
+#endif
+ if ( !dragMarking )
+ return;
+ if ( rect().contains( e->pos() ) ) {
+ stopAutoScroll();
+ } else if ( !dragScrolling ) {
+ startAutoScroll();
+ }
+
+ int newX, newY;
+ pixelPosToCursorPos(e->pos(), &newX, &newY);
+
+ if ( wordMark ) {
+ extendSelectionWord( newX, newY);
+ }
+
+ if ( markDragX == newX && markDragY == newY )
+ return;
+ int oldY = markDragY;
+ newMark( newX, newY, FALSE );
+ for ( int i = QMIN(oldY,newY); i <= QMAX(oldY,newY); i++ )
+ updateCell( i, 0, FALSE );
+}
+
+void QtMultiLineEdit::extendSelectionWord( int &newX, int&newY)
+{
+ QString s = stringShown( newY );
+ int lim = s.length();
+ if ( newX >= 0 && newX < lim ) {
+ int i = newX;
+ int startclass = charClass(s.at(i));
+ if ( markAnchorY < markDragY ||
+ ( markAnchorY == markDragY && markAnchorX < markDragX ) ) {
+ // going right
+ while ( i < lim && charClass(s.at(i)) == startclass )
+ i++;
+ } else {
+ // going left
+ while ( i >= 0 && charClass(s.at(i)) == startclass )
+ i--;
+ i++;
+ }
+ newX = i;
+ }
+}
+
+
+
+
+/*\reimp
+*/
+void QtMultiLineEdit::mouseReleaseEvent( QMouseEvent *e )
+{
+ stopAutoScroll();
+#ifndef QT_NO_DRAGANDDROP
+ if ( d->dnd_timer->isActive() ) {
+ d->dnd_timer->stop();
+ d->dnd_primed = FALSE;
+ setCursorPixelPosition(e->pos());
+ }
+#endif
+ wordMark = FALSE;
+ dragMarking = FALSE;
+ textDirty = FALSE;
+ d->isHandlingEvent = TRUE;
+ if ( markAnchorY == markDragY && markAnchorX == markDragX )
+ turnMark( FALSE );
+
+#ifndef QT_NO_CLIPBOARD
+#if defined(_WS_X11_)
+ else if ( echoMode() == Normal )
+ copy();
+#endif
+
+ if ( e->button() == MidButton && !readOnly ) {
+#if defined(_WS_X11_)
+ paste(); // Will repaint the cursor line.
+#else
+#ifndef QT_NO_COMPAT
+ if ( style().styleHint(QStyle::SH_GUIStyle) == Qt::MotifStyle )
+ paste();
+#endif
+#endif
+ }
+#endif
+
+ d->isHandlingEvent = FALSE;
+
+ if ( !readOnly && textDirty )
+ emit textChanged();
+}
+
+
+/*\reimp
+*/
+void QtMultiLineEdit::mouseDoubleClickEvent( QMouseEvent *m )
+{
+ if ( m->button() == LeftButton ) {
+ if ( m->state() & ShiftButton ) {
+ int newX = cursorX;
+ int newY = cursorY;
+ extendSelectionWord( newX, newY);
+ newMark( newX, newY, FALSE );
+ } else {
+ markWord( cursorX, cursorY );
+ }
+ dragMarking = TRUE;
+ wordMark = TRUE;
+ updateCell( cursorY, 0, FALSE );
+
+ }
+}
+
+#ifndef QT_NO_DRAGANDDROP
+
+/*
+ \reimp
+*/
+
+void QtMultiLineEdit::dragEnterEvent( QDragEnterEvent * )
+{
+ cursorOn = TRUE;
+ updateCell( cursorY, 0, FALSE );
+}
+
+/*\reimp
+*/
+void QtMultiLineEdit::dragMoveEvent( QDragMoveEvent* event )
+{
+ if ( readOnly ) return;
+ event->accept( QTextDrag::canDecode(event) );
+ d->dnd_forcecursor = TRUE;
+ setCursorPixelPosition(event->pos(), FALSE);
+ d->dnd_forcecursor = FALSE;
+ QRect inside_margin(scroll_margin, scroll_margin,
+ width()-scroll_margin*2, height()-scroll_margin*2);
+ if ( !inside_margin.contains(event->pos()) ) {
+ startAutoScroll();
+ }
+ if ( event->source() == this && event->action() == QDropEvent::Move )
+ event->acceptAction();
+}
+
+/*\reimp
+*/
+void QtMultiLineEdit::dragLeaveEvent( QDragLeaveEvent* )
+{
+ if ( cursorOn ) {
+ cursorOn = FALSE;
+ updateCell( cursorY, 0, FALSE );
+ }
+ stopAutoScroll();
+}
+
+/*\reimp
+*/
+void QtMultiLineEdit::dropEvent( QDropEvent* event )
+{
+ if ( readOnly ) return;
+ QString text;
+ QCString fmt = pickSpecial(event,FALSE,event->pos());
+ if ( QTextDrag::decode(event, text, fmt) ) {
+ int i = -1;
+ while ( ( i = text.find( '\r' ) ) != -1 )
+ text.replace( i,1,"" );
+ if ( event->source() == this && event->action() == QDropEvent::Move ) {
+ event->acceptAction();
+ // Careful not to tread on my own feet
+ int newX, newY;
+ pixelPosToCursorPos( event->pos(), &newX, &newY );
+ if ( afterMark( newX, newY ) ) {
+ // The tricky case
+ int x1, y1, x2, y2;
+ getMarkedRegion( &y1, &x1, &y2, &x2 );
+ if ( newY == y2 ) {
+ newY = y1;
+ newX = x1 + newX - x2;
+ } else {
+ newY -= y2 - y1;
+ }
+ addUndoCmd( new QBeginCommand );
+ del();
+ setCursorPosition(newY, newX);
+ insert(text, TRUE);
+ addUndoCmd( new QEndCommand );
+ } else if ( beforeMark( newX, newY ) ) {
+ // Easy
+ addUndoCmd( new QBeginCommand );
+ del();
+ setCursorPosition(newY, newX);
+ insert(text, TRUE);
+ addUndoCmd( new QEndCommand );
+ } else {
+ // Do nothing.
+ }
+ } else {
+ setCursorPixelPosition(event->pos());
+ insert(text, TRUE);
+ }
+ update();
+ emit textChanged();
+ }
+}
+
+#endif // QT_NO_DRAGANDDROP
+
+
+/*
+ Returns TRUE if line \a line is invisible or partially invisible.
+*/
+
+bool QtMultiLineEdit::partiallyInvisible( int line )
+{
+ int y;
+ if ( !rowYPos( line, &y ) )
+ return TRUE;
+ if ( y < 0 )
+ return TRUE;
+ else if ( y + cellHeight() - 2 > viewHeight() )
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ Scrolls such that the cursor is visible
+*/
+
+void QtMultiLineEdit::makeVisible()
+{
+ if ( !autoUpdate() )
+ return;
+
+ if ( partiallyInvisible( cursorY ) ) {
+ if ( cursorY >= lastRowVisible() )
+ setBottomCell( cursorY );
+ else
+ setTopCell( cursorY );
+ }
+ int xPos = mapToView( cursorX, cursorY );
+ if ( xPos < xOffset() ) {
+ int of = xPos - 10; //###
+ setXOffset( of );
+ } else if ( xPos > xOffset() + viewWidth() ) {
+ int of = xPos - viewWidth() + 10; //###
+ setXOffset( of );
+ }
+}
+
+/*
+ Computes the character position in line \a line which corresponds
+ to pixel \a xPos
+*/
+
+int QtMultiLineEdit::mapFromView( int xPos, int line )
+{
+ QString s = stringShown( line );
+ if ( !s )
+ return 0;
+ QFontMetrics fm( font() );
+ int index = xPosToCursorPos( s, fm,
+ xPos - d->lr_marg,
+ cellWidth() - 2 * d->lr_marg - d->marg_extra,
+ d->align );
+ QtMultiLineEditRow* r = contents->at( line );
+ if (r && !r->newline && ((unsigned int)index == r->s.length()) && (index > 0))
+ --index;
+ return index;
+}
+
+/*
+ Computes the pixel position in line \a line which corresponds to
+ character position \a xIndex
+*/
+
+int QtMultiLineEdit::mapToView( int xIndex, int line )
+{
+ QString s = stringShown( line );
+ xIndex = QMIN( (int)s.length(), xIndex );
+ QFontMetrics fm( font() );
+ int wcell = cellWidth() - 2 * d->lr_marg;// - d->marg_extra;
+ int wrow = contents->at( line )->w;
+ int w = textWidthWithTabs( fm, s, 0, xIndex, d->align ) - 1;
+ if ( d->align == Qt::AlignCenter || d->align == Qt::AlignHCenter )
+ w += (wcell - wrow) / 2;
+ else if ( d->align == Qt::AlignRight )
+ w += wcell - wrow;
+ return d->lr_marg + w;
+}
+
+/*
+ Traverses the list and finds an item with the maximum width, and
+ updates the internal list box structures accordingly.
+*/
+
+void QtMultiLineEdit::updateCellWidth()
+{
+ QtMultiLineEditRow* r = contents->first();
+ int maxW = 0;
+ int w;
+ switch ( d->echomode ) {
+ case Normal:
+ while ( r ) {
+ w = r->w;
+ if ( w > maxW )
+ maxW = w;
+ r = contents->next();
+ }
+ break;
+ case Password: {
+ uint l = 0;
+ while ( r ) {
+ l = QMAX(l, r->s.length() );
+ r = contents->next();
+ }
+ QString t;
+ t.fill(QChar('*'), l);
+ maxW = textWidth(t);
+ }
+ break;
+ case NoEcho:
+ maxW = textWidth(QString::fromLatin1(""));
+ }
+ setWidth( maxW );
+}
+
+
+/*
+ Sets the bottommost visible line to \a line.
+*/
+
+void QtMultiLineEdit::setBottomCell( int line )
+{
+ int rowY = cellHeight() * line;
+ int newYPos = rowY + cellHeight() - viewHeight();
+ setYOffset( QMAX( newYPos, 0 ) );
+}
+
+#ifndef QT_NO_CLIPBOARD
+
+/*
+ Copies text in MIME subtype \a subtype from the clipboard onto the current
+ cursor position.
+ Any marked text is first deleted.
+*/
+void QtMultiLineEdit::pasteSubType(const QCString& subtype)
+{
+ QCString st = subtype;
+ addUndoCmd( new QBeginCommand );
+
+ if ( hasMarkedText() )
+ del();
+ QString t = QApplication::clipboard()->text(st);
+ if ( !t.isEmpty() ) {
+ if ( hasMarkedText() )
+ turnMark( FALSE );
+
+#if defined(_OS_WIN32_)
+ // Need to convert CRLF to NL
+ t.replace( "\r\n", "\n" );
+#endif
+
+ for (int i=0; (uint)i<t.length(); i++) {
+ if ( t[i] < ' ' && t[i] != '\n' && t[i] != '\t' )
+ t[i] = ' ';
+ }
+ insertAt( t, cursorY, cursorX );
+ turnMark( FALSE );
+ curXPos = 0;
+ makeVisible();
+ }
+ if ( textDirty && !d->isHandlingEvent )
+ emit textChanged();
+
+ addUndoCmd( new QEndCommand );
+}
+
+/*
+ Copies plain text from the clipboard onto the current cursor position.
+ Any marked text is first deleted.
+*/
+void QtMultiLineEdit::paste()
+{
+ pasteSubType("plain");
+}
+
+#ifndef QT_NO_MIMECLIPBOARD
+/*
+ Prompts the user for a type from a list of text types available,
+ Then copies text from the clipboard onto the current cursor position.
+ Any marked text is first deleted.
+*/
+void QtMultiLineEdit::pasteSpecial(const QPoint& pt)
+{
+ QCString st = pickSpecial(QApplication::clipboard()->data(),TRUE,pt);
+ if ( !st.isEmpty() )
+ pasteSubType(st);
+}
+#endif
+#ifndef QT_NO_MIME
+QCString QtMultiLineEdit::pickSpecial(QMimeSource* ms, bool always_ask, const QPoint& pt)
+{
+ if ( ms ) {
+ QPopupMenu popup(this);
+ QString fmt;
+ int n=0;
+ QDict<void> done;
+ for (int i=0; !(fmt=ms->format(i)).isNull(); i++) {
+ int semi=fmt.find(";");
+ if ( semi >= 0 )
+ fmt = fmt.left(semi);
+ if ( fmt.left(5) == "text/" ) {
+ fmt = fmt.mid(5);
+ if ( !done.find(fmt) ) {
+ done.insert(fmt,(void*)1);
+ popup.insertItem(fmt,i);
+ n++;
+ }
+ }
+ }
+ if ( n ) {
+ int i = n==1 && !always_ask ? popup.idAt(0) : popup.exec(pt);
+ if ( i >= 0 )
+ return popup.text(i).latin1();
+ }
+ }
+ return QCString();
+}
+#endif // QT_NO_MIME
+#endif // QT_NO_CLIPBOARD
+
+
+/*
+ Removes all text.
+*/
+
+void QtMultiLineEdit::clear()
+{
+ addUndoCmd( new QDelTextCmd( 0, text() ) );
+ setEdited( TRUE );
+ contents->clear();
+ cursorX = cursorY = 0;
+ int w = textWidth( QString::fromLatin1("") );
+ contents->append( new QtMultiLineEditRow(QString::fromLatin1(""), w) );
+ setNumRowsAndTruncate();
+ setWidth( w );
+ dummy = TRUE;
+ turnMark( FALSE );
+ if ( autoUpdate() )
+ update();
+ if ( !d->isHandlingEvent ) //# && not already empty
+ emit textChanged();
+ update();
+}
+
+
+/*\reimp
+*/
+
+void QtMultiLineEdit::setFont( const QFont &font )
+{
+ QWidget::setFont( font );
+ d->clearChartable();
+ QFontMetrics fm( font );
+ setCellHeight( fm.lineSpacing() );
+ for ( QtMultiLineEditRow* r = contents->first(); r; r = contents->next() )
+ r->w = textWidth( r->s );
+ rebreakAll();
+ updateCellWidth();
+}
+
+/*
+ Sets a new marked text limit, does not repaint the widget.
+*/
+
+void QtMultiLineEdit::newMark( int posx, int posy, bool /*copy*/ )
+{
+ if ( markIsOn && markDragX == posx && markDragY == posy &&
+ cursorX == posx && cursorY == posy )
+ return;
+ markDragX = posx;
+ markDragY = posy;
+ cursorX = posx;
+ cursorY = posy;
+ turnMark( markDragX != markAnchorX || markDragY != markAnchorY );
+}
+
+bool QtMultiLineEdit::beforeMark( int posx, int posy ) const
+{
+ int x1, y1, x2, y2;
+ if ( !getMarkedRegion( &y1, &x1, &y2, &x2 ) )
+ return FALSE;
+ return
+ (y1 > posy || y1 == posy && x1 > posx)
+ && (y2 > posy || y2 == posy && x2 > posx);
+}
+
+bool QtMultiLineEdit::afterMark( int posx, int posy ) const
+{
+ int x1, y1, x2, y2;
+ if ( !getMarkedRegion( &y1, &x1, &y2, &x2 ) )
+ return FALSE;
+ return
+ (y1 < posy || y1 == posy && x1 < posx)
+ && (y2 < posy || y2 == posy && x2 < posx);
+}
+
+bool QtMultiLineEdit::inMark( int posx, int posy ) const
+{
+ int x1, y1, x2, y2;
+ if ( !getMarkedRegion( &y1, &x1, &y2, &x2 ) )
+ return FALSE;
+ return
+ (y1 < posy || y1 == posy && x1 <= posx)
+ && (y2 > posy || y2 == posy && x2 >= posx);
+}
+
+/*
+ Marks the word at character position \a posx, \a posy.
+ */
+void QtMultiLineEdit::markWord( int posx, int posy )
+{
+ QString& s = contents->at( posy )->s;
+
+ int i = posx - 1;
+ while ( i >= 0 && s[i].isPrint() && !s[i].isSpace() )
+ i--;
+ i++;
+ markAnchorY = posy;
+ markAnchorX = i;
+
+ while ( s[i].isPrint() && !s[i].isSpace() )
+ i++;
+ markDragX = i;
+ markDragY = posy;
+ turnMark( markDragX != markAnchorX || markDragY != markAnchorY );
+
+#ifndef QT_NO_CLIPBOARD
+#if defined(_WS_X11_)
+ if ( echoMode() == Normal )
+ copy();
+#endif
+#endif
+}
+
+/*
+ This may become a protected virtual member in a future Qt.
+ This implementation is an example of a useful classification
+ that aids selection of common units like filenames and URLs.
+*/
+int QtMultiLineEdit::charClass( QChar ch )
+{
+ if ( !ch.isPrint() || ch.isSpace() ) return 1;
+ else if ( ch.isLetter() || ch=='-' || ch=='+' || ch==':'
+ || ch=='.' || ch=='/' || ch=='\\'
+ || ch=='@' || ch=='$' || ch=='~' ) return 2;
+ else return 3;
+}
+
+#ifndef QT_NO_CLIPBOARD
+/*
+ Copies the marked text to the clipboard. Will copy only
+ if echoMode() is Normal.
+*/
+
+void QtMultiLineEdit::copy() const
+{
+ QString t = markedText();
+ if ( !t.isEmpty() && echoMode() == Normal ) {
+#if defined(_WS_X11_)
+ disconnect( QApplication::clipboard(), SIGNAL(dataChanged()), this, 0);
+#endif
+#if defined(_OS_WIN32_)
+ // Need to convert NL to CRLF
+ t.replace( "\n", "\r\n" );
+#endif
+ QApplication::clipboard()->setText( t );
+#if defined(_WS_X11_)
+ connect( QApplication::clipboard(), SIGNAL(dataChanged()),
+ this, SLOT(clipboardChanged()) );
+#endif
+ }
+}
+
+/* \obsolete
+
+ Backward compatibility.
+*/
+void QtMultiLineEdit::copyText() const
+{
+ copy();
+}
+
+/*
+ Copies the selected text to the clipboard and deletes the selected text.
+*/
+
+void QtMultiLineEdit::cut()
+{
+ if ( hasMarkedText() ) {
+ if ( echoMode() == Normal )
+ copy();
+ del();
+ if ( textDirty && !d->isHandlingEvent )
+ emit textChanged();
+ }
+}
+
+#endif
+
+/*
+ This private slot is activated when this line edit owns the clipboard and
+ some other widget/application takes over the clipboard. (X11 only)
+*/
+
+void QtMultiLineEdit::clipboardChanged()
+{
+#if defined(_WS_X11_)
+ disconnect( QApplication::clipboard(), SIGNAL(dataChanged()),
+ this, SLOT(clipboardChanged()) );
+ turnMark( FALSE );
+ update();
+#endif
+}
+
+
+/*
+ Sets maxLineWidth() and maybe cellWidth() to \a w without updating the entire widget.
+ */
+
+void QtMultiLineEdit::setWidth( int w )
+{
+ if ( w ==d->maxLineWidth )
+ return;
+ bool u = autoUpdate();
+ setAutoUpdate( FALSE );
+ d->maxLineWidth = w;
+ if ( d->align == AlignLeft )
+ setCellWidth( w );
+ else
+ setCellWidth( QMAX( w, contentsRect().width() ) );
+ setAutoUpdate( u );
+ if ( autoUpdate() && d->align != AlignLeft )
+ update();
+}
+
+
+/*
+ Sets the cursor position to character number \a col in line number \a line.
+ The parameters are adjusted to lie within the legal range.
+
+ If \a mark is FALSE, the selection is cleared. otherwise it is extended
+
+ \sa cursorPosition()
+*/
+
+void QtMultiLineEdit::setCursorPosition( int line, int col, bool mark )
+{
+ if ( mark && !hasMarkedText() ) {
+ markAnchorX = cursorX;
+ markAnchorY = cursorY;
+ }
+ int oldY = cursorY;
+ cursorY = QMAX( QMIN( line, numLines() - 1), 0 );
+ cursorX = QMAX( QMIN( col, lineLength( cursorY )), 0 );
+ curXPos = 0;
+ makeVisible();
+ if ( mark ) {
+ newMark( cursorX, cursorY, FALSE );
+ for ( int i = QMIN(oldY,cursorY); i <= QMAX(oldY,cursorY); i++ )
+ updateCell( i, 0, FALSE );
+ } else {
+ updateCell( oldY, 0, FALSE );
+ turnMark( FALSE );
+ }
+}
+
+
+
+/* \obsolete
+
+ Use getCursorPosition() instead.
+*/
+
+void QtMultiLineEdit::cursorPosition( int *line, int *col ) const
+{
+ getCursorPosition(line,col);
+}
+
+
+/*
+ Returns the current line and character
+ position within that line, in the variables pointed to
+ by \a line and \a col respectively.
+
+ \sa setCursorPosition()
+*/
+
+void QtMultiLineEdit::getCursorPosition( int *line, int *col ) const
+{
+ if ( line )
+ *line = cursorY;
+ if ( col )
+ *col = cursorX;
+}
+
+
+/*
+ \sa setAutoUpdate()
+*/
+
+bool QtMultiLineEdit::autoUpdate() const
+{
+ return QtTableView::autoUpdate();
+}
+
+
+/*
+ Sets the auto-update option of multi-line editor to \a enable.
+
+*/
+
+void QtMultiLineEdit::setAutoUpdate( bool enable )
+{
+ QtTableView::setAutoUpdate( enable );
+}
+
+/*
+ Sets the fixed height of the QtMultiLineEdit so that \a lines text lines
+ are visible given the current font.
+
+ \sa setMaxLines(), setFixedHeight()
+ */
+void QtMultiLineEdit::setFixedVisibleLines( int lines )
+{
+ int ls = fontMetrics().lineSpacing();
+ setFixedHeight( frameWidth()*2 + ls*lines );
+ return;
+}
+
+
+
+/*
+ Returns the top center point where the cursor is drawn
+*/
+
+QPoint QtMultiLineEdit::cursorPoint() const
+{
+ QPoint cp( 0, 0 );
+
+ QFontMetrics fm( font() );
+ int col, row;
+ col = row = 0;
+ cursorPosition( &row, &col );
+ QString line = textLine( row );
+ ASSERT( line );
+ cp.setX( d->lr_marg + textWidthWithTabs( fm, line, 0, col, d->align ) - 1 );
+ cp.setY( (row * cellHeight()) + viewRect().y() );
+ return cp;
+}
+
+
+/* \reimp
+*/
+QSizePolicy QtMultiLineEdit::sizePolicy() const
+{
+ //### removeme 3.0
+ return QWidget::sizePolicy();
+}
+
+
+/*\reimp
+*/
+QSize QtMultiLineEdit::sizeHint() const
+{
+ constPolish();
+ int expected_lines;
+ if ( d->maxlines >= 0 && d->maxlines <= 6 ) {
+ expected_lines = d->maxlines;
+ } else {
+ expected_lines = 6;
+ }
+ QFontMetrics fm( font() );
+ int h = fm.lineSpacing()*(expected_lines-1)+fm.height() + frameWidth()*2;
+ int w = fm.width('x')*35;
+
+ int maxh = maximumSize().height();
+ if ( maxh < QWIDGETSIZE_MAX )
+ h = maxh;
+
+ return QSize( w, h ).expandedTo( QApplication::globalStrut() );
+}
+
+
+/*
+ Returns a size sufficient for one character, and scroll bars.
+*/
+
+QSize QtMultiLineEdit::minimumSizeHint() const
+{
+ constPolish();
+ QFontMetrics fm( font() );
+ int h = fm.lineSpacing() + frameWidth()*2;
+ int w = fm.maxWidth();
+ h += frameWidth();
+ w += frameWidth();
+ if ( testTableFlags(Tbl_hScrollBar|Tbl_autoHScrollBar) )
+ w += verticalScrollBar()->sizeHint().width();
+ if ( testTableFlags(Tbl_vScrollBar|Tbl_autoVScrollBar) )
+ h += horizontalScrollBar()->sizeHint().height();
+ return QSize(w,h);
+}
+
+
+
+/*\reimp
+*/
+
+void QtMultiLineEdit::resizeEvent( QResizeEvent *e )
+{
+ int oldw = contentsRect().width();
+ QtTableView::resizeEvent( e );
+ if ( DYNAMIC_WRAP
+ && (e->oldSize().width() != width()
+ || oldw != contentsRect().width() ) ) {
+ bool oldAuto = autoUpdate();
+ setAutoUpdate( FALSE );
+ rebreakAll();
+ if ( oldw != contentsRect().width() )
+ rebreakAll();
+ setAutoUpdate( oldAuto );
+ if ( autoUpdate() )
+ repaint( FALSE );
+ } else if ( d->align != AlignLeft ) {
+ d->maxLineWidth = 0; // trigger update
+ updateCellWidth();
+ }
+ if ( isVisible() )
+ deselect();
+}
+
+/*
+ Sets the alignment to \a flags. Possible values are \c AlignLeft, \c
+ Align(H)Center and \c AlignRight.
+
+ \sa alignment(), Qt::AlignmentFlags
+*/
+void QtMultiLineEdit::setAlignment( int flags )
+{
+ if ( d->align != flags ) {
+ d->align = flags;
+ update();
+ }
+}
+
+/*
+ Returns the alignment.
+
+*/
+int QtMultiLineEdit::alignment() const
+{
+ return d->align;
+}
+
+
+/*
+ Not supported at this time.
+ \a v is the validator to set.
+*/
+void QtMultiLineEdit::setValidator( const QValidator *v )
+{
+ d->val = v;
+ // #### validate text now
+}
+
+/*
+ Not supported at this time.
+*/
+const QValidator * QtMultiLineEdit::validator() const
+{
+ return d->val;
+}
+
+/* \sa edited()
+*/
+void QtMultiLineEdit::setEdited( bool e )
+{
+ d->edited = e;
+}
+
+/* \sa setEdited()
+*/
+bool QtMultiLineEdit::edited() const
+{
+ return d->edited;
+}
+
+/* \enum QtMultiLineEdit::EchoMode
+
+ This enum type describes the ways in which QLineEdit can display its
+ contents. The currently defined values are: \list
+
+ \i Normal - display characters as they are entered. This is
+ the default.
+
+ \i NoEcho - do not display anything.
+
+ \i Password - display asterisks instead of the characters
+ actually entered.
+
+ \endlist
+
+ \sa setEchoMode() echoMode() QLineEdit::EchoMode
+*/
+
+
+/*
+ Sets the echo mode to \a em. The default is \c Normal.
+
+ The display is updated according.
+
+ \sa setEchoMode()
+*/
+void QtMultiLineEdit::setEchoMode( EchoMode em )
+{
+ if ( d->echomode != em ) {
+ d->echomode = em;
+ updateCellWidth();
+ update();
+ }
+}
+
+/*
+ Returns the currently set echo mode.
+
+ \sa setEchoMode()
+*/
+QtMultiLineEdit::EchoMode QtMultiLineEdit::echoMode() const
+{
+ return d->echomode;
+}
+
+
+/*
+ Returns the string shown at line \a row, including
+ processing of the echoMode().
+*/
+
+QString QtMultiLineEdit::stringShown(int row) const
+{
+ QString* s = getString(row);
+ if ( !s ) return QString::null;
+ switch ( d->echomode ) {
+ case Normal:
+ if (!*s) return QString::fromLatin1("");
+ return *s;
+ case Password:
+ {
+ QString r;
+ r.fill(QChar('*'), (int)s->length());
+ if ( !r ) r = QString::fromLatin1("");
+ return r;
+ }
+ case NoEcho:
+ return QString::fromLatin1("");
+ }
+ return QString::fromLatin1("");
+}
+
+/*
+
+ \sa maxLength()
+*/
+void QtMultiLineEdit::setMaxLength(int m)
+{
+ d->maxlen = m;
+}
+
+/*
+ \sa setMaxLength()
+*/
+int QtMultiLineEdit::maxLength() const
+{
+ return d->maxlen;
+}
+
+
+/*
+ Returns the length of the current text.
+
+ \sa setMaxLength()
+ */
+int QtMultiLineEdit::length() const
+{
+ int l = 0;
+ for ( QtMultiLineEditRow* r = contents->first(); r; r = contents->next() ) {
+ l += r->s.length();
+ if ( r->newline )
+ ++l;
+ }
+ return l-1;
+}
+
+
+/*
+ Sets the maximum length of lines to \a m. Use -1 for unlimited
+ (the default). Existing long lines will be truncated.
+
+ \sa maxLineLength()
+*/
+void QtMultiLineEdit::setMaxLineLength(int m)
+{
+ bool trunc = d->maxlinelen < 0 || m < d->maxlinelen;
+ d->maxlinelen = m;
+ if ( trunc ) {
+ QtMultiLineEditRow* r = contents->first();
+ while ( r ) {
+ r->s.truncate( m );
+ r = contents->next();
+ }
+ if ( cursorX > m ) cursorX = m;
+ if ( markAnchorX > m ) markAnchorX = m;
+ if ( markDragX > m ) markDragX = m;
+ update();
+ updateCellWidth();
+ }
+}
+
+/*
+ Returns the currently set line length limit, or -1 if there is
+ no limit (this is the default).
+
+ \sa setMaxLineLength()
+*/
+int QtMultiLineEdit::maxLineLength() const
+{
+ return d->maxlinelen;
+}
+
+/*
+ Sets the maximum number of lines to \a m. Use -1 for unlimited
+ (the default). Existing excess lines will be deleted.
+
+ \sa maxLines(), numLines()
+*/
+void QtMultiLineEdit::setMaxLines(int m)
+{
+ if ( m == 0 ) // bad value
+ m = -1;
+ d->maxlines = m;
+ if ( d->maxlines >= 0 && d->maxlines <= 6 ) {
+ setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
+ } else {
+ setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
+ }
+ if ( setNumRowsAndTruncate() ) {
+ updateCellWidth();
+ update();
+ }
+}
+
+/*
+ \sa setMaxLines()
+*/
+int QtMultiLineEdit::maxLines() const
+{
+ return d->maxlines;
+}
+
+/*
+ Sets the horizontal margin to \a m.
+
+ \sa hMargin()
+*/
+void QtMultiLineEdit::setHMargin(int m)
+{
+ if ( m != d->lr_marg ) {
+ d->lr_marg = m;
+ updateCellWidth();
+ update();
+ }
+}
+
+/*
+
+ \sa setHMargin()
+*/
+int QtMultiLineEdit::hMargin() const
+{
+ return d->lr_marg;
+}
+
+/*
+ Marks the text starting at \a row_from, \a col_from and ending
+ at \a row_to, \a col_to.
+*/
+void QtMultiLineEdit::setSelection( int row_from, int col_from,
+ int row_to, int col_to )
+{
+ setCursorPosition( row_from, col_from, FALSE );
+ setCursorPosition( row_to, col_to, TRUE );
+}
+
+
+/*
+ Moves the cursor one word to the right. If \a mark is TRUE, the text
+ is marked.
+ \sa cursorWordBackward()
+*/
+void QtMultiLineEdit::cursorWordForward( bool mark )
+{
+ int x = cursorX;
+ int y = cursorY;
+
+ if ( x == lineLength( y ) || textLine(y).at(x).isSpace() ) {
+ while ( x < lineLength( y ) && textLine(y).at(x).isSpace() )
+ ++x;
+ if ( x == lineLength( y ) ) {
+ if ( y < (int)contents->count() - 1) {
+ ++y;
+ x = 0;
+ while ( x < lineLength( y ) && textLine(y).at(x).isSpace() )
+ ++x;
+ }
+ }
+ }
+ else {
+ while ( x < lineLength( y ) && !textLine(y).at(x).isSpace() )
+ ++x;
+ int xspace = x;
+ while ( xspace < lineLength( y ) && textLine(y).at(xspace).isSpace() )
+ ++xspace;
+ if ( xspace < lineLength( y ) )
+ x = xspace;
+ }
+ cursorOn = TRUE;
+ int oldY = cursorY;
+ setCursorPosition( y, x, mark );
+ if ( oldY != cursorY )
+ updateCell( oldY, 0, FALSE );
+ updateCell( cursorY, 0, FALSE );
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+}
+
+/*
+ Moves the cursor one word to the left. If \a mark is TRUE, the text
+ is marked.
+ \sa cursorWordForward()
+*/
+void QtMultiLineEdit::cursorWordBackward( bool mark )
+{
+ int x = cursorX;
+ int y = cursorY;
+
+ while ( x > 0 && textLine(y).at(x-1).isSpace() )
+ --x;
+
+ if ( x == 0 ) {
+ if ( y > 0 ) {
+ --y;
+ x = lineLength( y );
+ while ( x > 0 && textLine(y).at(x-1).isSpace() )
+ --x;
+ }
+ }
+ else {
+ while ( x > 0 && !textLine(y).at(x-1).isSpace() )
+ --x;
+ }
+ cursorOn = TRUE;
+ int oldY = cursorY;
+ setCursorPosition( y, x, mark );
+ if ( oldY != cursorY )
+ updateCell( oldY, 0, FALSE );
+ updateCell( cursorY, 0, FALSE );
+ d->blinkTimer->start( QApplication::cursorFlashTime() / 2, FALSE );
+}
+
+#define DO_BREAK {doBreak = TRUE; if ( lastSpace > a ) { \
+i = lastSpace; \
+linew = lastw; \
+} \
+else \
+i = QMAX( a, i-1 );}
+
+void QtMultiLineEdit::wrapLine( int line, int removed )
+{
+ QtMultiLineEditRow* r = contents->at( line );
+ int yPos;
+ (void) rowYPos( line, &yPos );
+ QFontMetrics fm( font() );
+ int i = 0;
+ QString s = r->s;
+ int a = 0;
+ int l = line;
+ int w = 0;
+ int nlines = 0;
+ int lastSpace = -1;
+ bool doBreak = FALSE;
+ int linew = 0;
+ int lastw = 0;
+ int tabDist = -1; // lazy eval
+ while ( i < int(s.length()) ) {
+ doBreak = FALSE;
+ if ( s[i] == '\t' && d->align == Qt::AlignLeft ) {
+ if ( tabDist<0 )
+ tabDist = tabStopDist(fm);
+ linew = ( linew/tabDist + 1 ) * tabDist;
+ } else if ( s[i] != '\n' ) {
+ char c = s[i].latin1();
+ if ( c > 0 ) {
+ if ( !d->chartable[c] )
+ d->chartable[c] = fm.width( s[i] );
+ linew += d->chartable[c];
+ } else {
+ linew += fm.width( s[i] );
+ }
+ }
+ if ( WORD_WRAP &&
+ lastSpace >= a && s[i] != '\n' ) {
+ if ( DYNAMIC_WRAP ) {
+ if (linew >= contentsRect().width() - 2*d->lr_marg - d->marg_extra) {
+ DO_BREAK
+ }
+ } else if ( FIXED_COLUMN_WRAP ) {
+ if ( d->wrapcol >= 0 && i-a >= d->wrapcol ) {
+ DO_BREAK
+ }
+ } else if ( FIXED_WIDTH_WRAP ) {
+ if ( d->wrapcol >= 0 && linew > d->wrapcol - d->marg_extra ) {
+ DO_BREAK
+ }
+ }
+ }
+ if ( s[i] == '\n' || doBreak ) {
+ r->s = s.mid( a, i - a + (doBreak?1:0) );
+ r->w = linew - fm.leftBearing(r->s[0]) + 2 * d->lr_marg + d->marg_extra;
+ if ( r->w > w )
+ w = r->w;
+ if ( cursorY > l )
+ ++cursorY;
+ else if ( cursorY == line && cursorX >=a && cursorX <= i + (doBreak?1:0)) {
+ cursorY = l;
+ cursorX -= a;
+ }
+ if ( markAnchorY > l )
+ ++markAnchorY;
+ else if ( markAnchorY == line && markAnchorX >=a && markAnchorX <= i + (doBreak?1:0)) {
+ markAnchorY = l;
+ markAnchorX -= a;
+ }
+ a = i + 1;
+ lastSpace = a;
+ linew = 0;
+ bool oldnewline = r->newline;
+ r->newline = !doBreak;
+ r = new QtMultiLineEditRow( QString::null, 0, oldnewline );
+ ++nlines;
+ contents->insert( l + 1, r );
+ ++l;
+ }
+ if ( s[i].isSpace() || BREAK_WITHIN_WORDS ) {
+ lastSpace = i;
+ lastw = linew;
+ }
+ if ( lastSpace <= a )
+ lastw = linew;
+
+ ++i;
+ }
+ if ( a < int(s.length()) ){
+ r->s = s.mid( a, i - a );
+ r->w = linew - fm.leftBearing( r->s[0] ) + 2 * d->lr_marg + d->marg_extra;
+ }
+ if ( cursorY == line && cursorX >= a ) {
+ cursorY = l;
+ cursorX -= a;
+ }
+ if ( markAnchorY == line && markAnchorX >= a ) {
+ markAnchorY = l;
+ markAnchorX -= a;
+ }
+ if ( r->w > w )
+ w = r->w;
+
+ setWidth( QMAX( maxLineWidth(), w ) );
+ bool oldAuto = autoUpdate();
+ setAutoUpdate( FALSE );
+ (void)setNumRowsAndTruncate();
+ setAutoUpdate( oldAuto );
+
+ yPos += (nlines+1) * cellHeight();
+ int sh = (nlines-removed) * cellHeight();
+ if ( autoUpdate() ) {
+ if ( sh && yPos >= contentsRect().top() && yPos < contentsRect().bottom() ) {
+ int h = contentsRect().bottom() - yPos + 1;
+ if ( d->maxlines >= 0 ) {
+ int maxy;
+ if ( rowYPos( d->maxlines-1, &maxy ) ) {
+ maxy += cellHeight();
+ if ( maxy < contentsRect().bottom() && maxy > yPos )
+ h = maxy - yPos + 1;
+ }
+ }
+ QWidget::scroll( 0, sh, QRect( contentsRect().left(), yPos,
+ contentsRect().width(),
+ h ) );
+ }
+ for (int ul = 0; ul <= nlines; ++ul )
+ updateCell( line + ul, 0, FALSE );
+ }
+}
+
+void QtMultiLineEdit::rebreakParagraph( int line, int removed )
+{
+ QtMultiLineEditRow* r = contents->at( line );
+ if ( WORD_WRAP ) {
+ QtMultiLineEditRow* other = 0;
+ while (line < int(contents->count())-1 && !r->newline ) {
+ other = contents->at( line + 1 );
+ if ( cursorY > line ) {
+ --cursorY;
+ if ( cursorY == line ) {
+ cursorX += r->s.length();
+ }
+ }
+ if ( markAnchorY > line ) {
+ --markAnchorY;
+ if ( markAnchorY == line ) {
+ markAnchorX += r->s.length();
+ }
+ }
+ r->s.append( other->s );
+ r->newline = other->newline;
+ contents->remove( line + 1 );
+ ++removed;
+ }
+ }
+ wrapLine( line, removed );
+}
+
+void QtMultiLineEdit::rebreakAll()
+{
+ if ( !WORD_WRAP )
+ return;
+ d->maxLineWidth = 0;
+ for (int i = 0; i < int(contents->count()); ++i ) {
+ if ( contents->at( i )->newline &&
+ contents->at( i )->w < contentsRect().width() - 2*d->lr_marg - d->marg_extra ) {
+ setWidth( QMAX( d->maxLineWidth, contents->at( i )->w ) );
+ continue;
+ }
+ rebreakParagraph( i );
+ while ( i < int(contents->count() )
+ && !contents->at( i )->newline )
+ ++i;
+ }
+}
+
+
+/* \enum QtMultiLineEdit::WordWrap
+
+ This enum describes the multiline edit's word wrap mode.
+
+ The following values are valid:
+ \list
+ \i NoWrap - no word wrap at all.
+ \i WidgetWidth - word wrap depending on the current
+ width of the editor widget
+ \i FixedPixelWidth - wrap according to a fix amount
+ of pixels ( see wrapColumnOrWidth() )
+ \i FixedColumnWidth - wrap according to a fix character
+ column. This is useful whenever you need formatted text that
+ can also be displayed gracefully on devices with monospaced
+ fonts, for example a standard VT100 terminal. In that case
+ wrapColumnOrWidth() should typically be set to 80.
+ \endlist
+
+ \sa setWordWrap()
+*/
+
+/*
+ Sets the word wrap mode to \a mode.
+
+ */
+void QtMultiLineEdit::setWordWrap( WordWrap mode )
+{
+ if ( mode == d->wordwrap )
+ return;
+ d->wordwrap = mode;
+
+ if ( BREAK_WITHIN_WORDS ) {
+ d->arrow = QPixmap( (const char **)arrow_xpm );
+ d->marg_extra = 8;
+ if ( DYNAMIC_WRAP )
+ clearTableFlags( Tbl_autoHScrollBar );
+ else
+ setTableFlags( Tbl_autoHScrollBar );
+ } else {
+ d->marg_extra = 0;
+ setTableFlags( Tbl_autoHScrollBar );
+ }
+ if ( !text().isEmpty() )
+ setText( text() );
+}
+
+/*
+ Returns the current word wrap mode.
+
+ \sa setWordWrap()
+ */
+QtMultiLineEdit::WordWrap QtMultiLineEdit::wordWrap() const
+{
+ return d->wordwrap;
+}
+
+/*
+ Sets the wrap column or wrap width to \a value, depending on the
+ word wrap mode.
+
+ \sa setWordWrap()
+ */
+void QtMultiLineEdit::setWrapColumnOrWidth( int value )
+{
+ if ( value == d->wrapcol )
+ return;
+ d->wrapcol = value;
+ if ( wordWrap() != NoWrap )
+ setText( text() );
+}
+
+/*
+ */
+int QtMultiLineEdit::wrapColumnOrWidth() const
+{
+ return d->wrapcol;
+}
+
+
+/* \enum QtMultiLineEdit::WrapPolicy
+
+ Defines where text can be wrapped in word wrap mode.
+
+ The following values are valid:
+ \list
+ \i AtWhiteSpace - break only after whitespace
+ \i Anywhere - break anywhere
+ \endlist
+
+ \sa setWrapPolicy()
+*/
+
+/*
+ Sets the wrap \a policy, i.e. where text can be wrapped in word wrap
+ mode.
+
+ \sa setWordWrap(), wrapPolicy()
+ */
+void QtMultiLineEdit::setWrapPolicy( WrapPolicy policy )
+{
+ if ( d->wrappolicy == policy )
+ return;
+ d->wrappolicy = policy;
+ WordWrap m = d->wordwrap;
+ if ( m != NoWrap ) { // trigger update
+ d->wordwrap = NoWrap;
+ setWordWrap( m );
+ }
+}
+
+/*
+
+ Returns the current word wrap policy.
+
+ \sa setWrapPolicy()
+ */
+QtMultiLineEdit::WrapPolicy QtMultiLineEdit::wrapPolicy() const
+{
+ return d->wrappolicy;
+}
+
+/*
+ Returns wether \a row is the last row in a paragraph.
+
+ This function is only interesting in word wrap mode, otherwise its
+ return value is always TRUE.
+
+ \sa setWordWrap()
+ */
+bool QtMultiLineEdit::isEndOfParagraph( int row ) const
+{
+ return contents->at( row )->newline;
+}
+
+int QtMultiLineEdit::positionToOffsetInternal( int row, int col ) const
+{
+ row = QMAX( QMIN( row, numLines() - 1), 0 ); // Sanity check
+ col = QMAX( QMIN( col, lineLength( row )), 0 ); // Sanity check
+ if ( row == 0 )
+ return QMIN( col, lineLength( 0 ));
+ else {
+ int lastI;
+ lastI = lineLength( row );
+ int i, tmp = 0;
+
+ for( i = 0; i < row ; i++ ) {
+ tmp += lineLength( i );
+ if ( contents->at( i )->newline )
+ ++tmp;
+ }
+
+ tmp += QMIN( lastI, col );
+
+ return tmp;
+ }
+
+}
+
+// if position is <0 = returns row 0, col 0, if position >= amount of text
+// returns pointer to end of text.
+void QtMultiLineEdit::offsetToPositionInternal( int position,
+ int *row, int *col ) const
+{
+ if (position <= 0) {
+ *row = 0;
+ *col = 0;
+ return;
+ }
+ else {
+ int charsLeft = position;
+ int i;
+
+ for( i = 0; contents->at( i ); ++i ) {
+ if (lineLength( i ) < charsLeft)
+ charsLeft -= lineLength( i );
+ else {
+ *row = i;
+ *col = charsLeft;
+ return;
+ }
+ if ( contents->at( i )->newline )
+ --charsLeft;
+ }
+
+ if (contents->at( i - 1) && !contents->at( i - 1 )->newline) {
+ *row = i - 1;
+ *col = lineLength( i - 1 );
+ }
+ else {
+ *row = i;
+ *col = 0;
+ }
+ return;
+ }
+}
+
+
+/*
+ Processes an undo/redo command \a cmd, depending on \a undo.
+ */
+void QtMultiLineEdit::processCmd( QtMultiLineEditCommand* cmd, bool undo)
+{
+ QDelTextCmd* delcmd = (QDelTextCmd*) cmd;
+ bool ins = TRUE;
+ if (cmd->type() == QtMultiLineEditCommand::Delete )
+ ins = undo;
+ else if (cmd->type() == QtMultiLineEditCommand::Insert )
+ ins = !undo;
+ else
+ return;
+
+ if ( ins ) {
+ int row, col;
+ offsetToPositionInternal( delcmd->mOffset, &row, &col );
+ setCursorPosition( row, col, FALSE );
+ insertAt( delcmd->mStr, row, col, FALSE );
+ offsetToPositionInternal( delcmd->mOffset+delcmd->mStr.length(), &row, &col );
+ setCursorPosition( row, col, FALSE );
+ } else { // del
+ int row, col, rowEnd, colEnd;
+ offsetToPositionInternal( delcmd->mOffset, &row, &col );
+ offsetToPositionInternal( delcmd->mOffset + delcmd->mStr.length(), &rowEnd, &colEnd );
+ markAnchorY = row;
+ markAnchorX = col;
+ setCursorPosition( rowEnd, colEnd, FALSE );
+ markDragY = rowEnd;
+ markDragX = colEnd;
+ turnMark( TRUE );
+ del();
+ }
+}
+
+/*
+ Undoes the last text operation.
+ */
+void QtMultiLineEdit::undo()
+{
+ if ( d->undoList.isEmpty() || isReadOnly() )
+ return;
+ textDirty = FALSE;
+ int macroLevel = 0;
+ bool before = d->undo;
+ d->undo = FALSE;
+ do {
+ QtMultiLineEditCommand *command = d->undoList.take();
+ if ( !command )
+ break;
+ processCmd( command, TRUE );
+ macroLevel += command->terminator();
+ if ( d->undoList.isEmpty() )
+ emit undoAvailable( FALSE );
+ addRedoCmd( command );
+ } while (macroLevel != 0);
+ d->undo = before;
+ if ( textDirty )
+ emit textChanged();
+ textDirty = FALSE;
+}
+
+/*
+ Redoes the last text operation.
+ */
+void QtMultiLineEdit::redo()
+{
+ if ( d->redoList.isEmpty() || isReadOnly() )
+ return;
+ textDirty = FALSE;
+ int macroLevel = 0;
+ bool before = d->undo;
+ d->undo = FALSE;
+ do {
+ QtMultiLineEditCommand *command = d->redoList.take();
+ if ( !command )
+ break;
+ processCmd( command, FALSE );
+ macroLevel += command->terminator();
+ if ( d->redoList.isEmpty() )
+ emit redoAvailable( FALSE );
+ if ( d->undoList.isEmpty() )
+ emit undoAvailable(TRUE);
+ d->undoList.append( command );
+ } while (macroLevel != 0);
+ d->undo = before;
+ if ( textDirty )
+ emit textChanged();
+ textDirty = FALSE;
+}
+
+/*
+ Inserts \a s at line number \a line, after character number \a col
+ in the line.
+ If \a s contains newline characters, new lines are inserted.
+ If \a mark is TRUE the inserted text is selected.
+
+ The cursor position is adjusted. If the insertion position is equal to
+ the cursor position, the cursor is placed after the end of the new text.
+
+ */
+
+void QtMultiLineEdit::insertAt( const QString &s, int line, int col, bool mark )
+{
+ if ( d->undo ) {
+ d->undo = FALSE;
+ QString itxt = s;
+ int offset = positionToOffsetInternal( line, col );
+ if ( d->maxlen >= 0 && length() + int(s.length()) > d->maxlen )
+ itxt.truncate( d->maxlen - length() );
+ addUndoCmd( new QInsTextCmd( offset, itxt ) );
+ insertAtAux( s, line, col, mark ); // may perform del op
+ d->undo = TRUE;
+ }
+ else
+ insertAtAux( s, line, col, mark ); // may perform del op
+}
+
+void QtMultiLineEdit::deleteNextChar( int offset, int row, int col )
+{
+ int row2, col2;
+ setCursorPosition( row, col, FALSE );
+ offsetToPositionInternal( offset + 1, &row2, &col2 );
+ setCursorPosition( row2, col2, TRUE );
+
+ QString str = markedText();
+ addUndoCmd( new QDelTextCmd( offset, str ) );
+
+ setCursorPosition( row, col, FALSE );
+}
+
+/*
+ Deletes text from the current cursor position to the end of the line.
+*/
+
+void QtMultiLineEdit::killLine()
+{
+ if ( d->undo ) {
+ d->undo = FALSE;
+ int curY, curX;
+ cursorPosition( &curY, &curX );
+ int offset = positionToOffsetInternal( curY, curX );
+ QtMultiLineEditRow* r = contents->at( curY );
+ deselect();
+
+ addUndoCmd( new QBeginCommand );
+ if (curX == (int)r->s.length()) {
+ if ( ! atEnd() && r->newline )
+ deleteNextChar( offset, curY, curX );
+ }
+ else {
+ QString str = r->s.mid( curX, r->s.length() );
+ addUndoCmd( new QDelTextCmd( offset, str ) );
+ }
+
+ addUndoCmd( new QEndCommand );
+ killLineAux();
+ d->undo = TRUE;
+ }
+ else
+ killLineAux();
+}
+
+/*
+ Deletes the character on the right side of the text cursor. If a
+ text has been marked by the user (e.g. by clicking and dragging) the
+ cursor is put at the beginning of the marked text and the marked
+ text is removed. \sa backspace()
+*/
+
+void QtMultiLineEdit::del()
+{
+ if (d->undo ) {
+ d->undo = FALSE;
+ bool oldAuto = autoUpdate();
+ setAutoUpdate( FALSE );
+ int markBeginX, markBeginY;
+ int markEndX, markEndY;
+
+ if ( getMarkedRegion( &markBeginY, &markBeginX, &markEndY, &markEndX ) ) {
+ addUndoCmd( new QBeginCommand );
+ int offset = positionToOffsetInternal( markBeginY, markBeginX );
+ QString str = markedText();
+ d->undoList.append( new QDelTextCmd( offset, str ) );
+ addUndoCmd( new QEndCommand );
+ }
+ else if ( ! atEnd() ) {
+ int crsorY, crsorX;
+ cursorPosition( &crsorY, &crsorX );
+ int offset = positionToOffsetInternal( crsorY, crsorX );
+ QtMultiLineEditRow* r = contents->at( crsorY );
+ if (r) {
+ if (crsorX != (int)r->s.length())
+ deleteNextChar( offset, crsorY, crsorX );
+ else if (r->newline)
+ deleteNextChar( offset, crsorY, crsorX );
+ // else noop
+ }
+ }
+ setAutoUpdate( oldAuto );
+ delAux();
+ d->undo = TRUE;
+ }
+ else
+ delAux();
+}
+
+/*
+ Sets undo enabled to \a enable.
+
+ \sa isUndoEnabled()
+*/
+void QtMultiLineEdit::setUndoEnabled( bool enable )
+{
+ if ( d->undo == enable )
+ return;
+ d->undo = enable;
+ if ( !enable ) {
+ CLEAR_UNDO
+ }
+}
+
+
+/*
+ Returns whether the multilineedit is currently undo enabled or not.
+
+ \sa setUndoEnabled()
+ */
+bool QtMultiLineEdit::isUndoEnabled() const
+{
+ return d->undo;
+}
+
+
+/*
+ Sets the maximum number of operations that can be stored on the undo
+ stack to \a depth.
+
+ \sa undoDepth()
+ */
+void QtMultiLineEdit::setUndoDepth( int depth )
+{
+ d->undodepth = depth;
+}
+
+
+/*
+ */
+int QtMultiLineEdit::undoDepth() const
+{
+ return d->undodepth;
+}
+
+void QtMultiLineEdit::blinkTimerTimeout()
+{
+ cursorOn = !cursorOn;
+ updateCell( cursorY, 0, FALSE );
+}
+
+void QtMultiLineEdit::scrollTimerTimeout()
+{
+ QPoint p = mapFromGlobal( QCursor::pos() );
+ if ( d->scrollAccel-- <= 0 && d->scrollTime ) {
+ d->scrollAccel = initialScrollAccel;
+ d->scrollTime--;
+ d->scrollTimer->stop();
+ d->scrollTimer->start( d->scrollTime );
+ }
+ int l = QMAX(1,(initialScrollTime-d->scrollTime)/5);
+
+ // auto scrolling is dual-use - for highlighting and DND
+ int margin = d->dnd_primed ? scroll_margin : 0;
+ bool mark = !d->dnd_primed;
+ bool clear_mark = d->dnd_primed ? FALSE : !mark;
+
+ for (int i=0; i<l; i++) {
+ if ( p.y() < margin ) {
+ cursorUp( mark, clear_mark );
+ } else if ( p.y() > height()-margin ) {
+ cursorDown( mark, clear_mark );
+ } else if ( p.x() < margin ) {
+ cursorLeft( mark, clear_mark, FALSE );
+ } else if ( p.x() > width()-margin ) {
+ cursorRight( mark, clear_mark, FALSE );
+ } else {
+ stopAutoScroll();
+ break;
+ }
+ }
+}
+
+void QtMultiLineEdit::dndTimeout()
+{
+#ifndef QT_NO_DRAGANDDROP
+ doDrag();
+#endif
+}
+
+int QtMultiLineEdit::setNumRowsAndTruncate()
+{
+ int n = contents->count();
+ int r = 0;
+ while ( d->maxlines >= 0 && n > d->maxlines ) {
+ // truncate
+ contents->at(n-2)->newline = TRUE;
+ contents->removeLast();
+ if ( markAnchorY == n-1 )
+ markAnchorY--;
+ if ( markDragY == n-1 )
+ markDragY--;
+ if ( cursorY == n-1 ) {
+ cursorY--;
+ cursorX = contents->at(cursorY)->s.length();
+ }
+ n--;
+ r++;
+ }
+ setNumRows( n );
+ return r;
+}
+
+/* \reimp
+*/
+bool QtMultiLineEdit::event( QEvent * e )
+{
+ if ( e->type() == QEvent::AccelOverride && !isReadOnly() ) {
+ QKeyEvent* ke = (QKeyEvent*) e;
+ if ( ke->state() & ControlButton ) {
+ switch ( ke->key() ) {
+ case Key_A:
+ case Key_E:
+#if defined (_WS_WIN_)
+ case Key_Insert:
+#endif
+ case Key_X:
+ case Key_V:
+ case Key_C:
+ case Key_Left:
+ case Key_Right:
+ case Key_Up:
+ case Key_Down:
+ case Key_Home:
+ case Key_End:
+ ke->accept();
+ default:
+ break;
+ }
+ } else {
+ switch ( ke->key() ) {
+ case Key_Delete:
+ case Key_Home:
+ case Key_End:
+ case Key_Backspace:
+ ke->accept();
+ default:
+ break;
+ }
+ }
+ }
+ return QWidget::event( e );
+}
+
+/* \reimp
+*/
+
+bool QtMultiLineEdit::focusNextPrevChild( bool )
+{
+ return FALSE;
+}
+
+#endif
diff --git a/src/attic/qtmultilineedit.h b/src/attic/qtmultilineedit.h
new file mode 100644
index 0000000..7d39f9f
--- /dev/null
+++ b/src/attic/qtmultilineedit.h
@@ -0,0 +1,363 @@
+/**********************************************************************
+**
+** Definition of QtMultiLineEdit widget class
+**
+** Created : 961005
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file contains a class moved out of the Qt GUI Toolkit API. It
+** may be used, distributed and modified without limitation.
+**
+**********************************************************************/
+
+#ifndef QTMULTILINEEDIT_H
+#define QTMULTILINEEDIT_H
+
+#ifndef QT_H
+#include "qttableview.h"
+#include "qstring.h"
+#include "qptrlist.h"
+#endif // QT_H
+
+#ifndef QT_NO_QTMULTILINEEDIT
+
+struct QtMultiLineData;
+class QtMultiLineEditCommand;
+class QValidator;
+
+class QtMultiLineEdit : public QtTableView
+{
+ Q_OBJECT
+ Q_ENUMS( EchoMode WordWrap WrapPolicy )
+ Q_PROPERTY( int numLines READ numLines )
+ Q_PROPERTY( bool atBeginning READ atBeginning )
+ Q_PROPERTY( bool atEnd READ atEnd )
+ Q_PROPERTY( int maxLineWidth READ maxLineWidth )
+ Q_PROPERTY( Alignment alignment READ alignment WRITE setAlignment )
+ Q_PROPERTY( bool edited READ edited WRITE setEdited DESIGNABLE false )
+ Q_PROPERTY( EchoMode echoMode READ echoMode WRITE setEchoMode )
+ Q_PROPERTY( int maxLength READ maxLength WRITE setMaxLength )
+ Q_PROPERTY( int maxLines READ maxLines WRITE setMaxLines )
+ Q_PROPERTY( int hMargin READ hMargin WRITE setHMargin )
+ Q_PROPERTY( WordWrap wordWrap READ wordWrap WRITE setWordWrap )
+ Q_PROPERTY( int wrapColumnOrWidth READ wrapColumnOrWidth WRITE setWrapColumnOrWidth )
+ Q_PROPERTY( WrapPolicy wrapPolicy READ wrapPolicy WRITE setWrapPolicy )
+ Q_PROPERTY( bool autoUpdate READ autoUpdate WRITE setAutoUpdate DESIGNABLE false )
+ Q_PROPERTY( bool undoEnabled READ isUndoEnabled WRITE setUndoEnabled )
+ Q_PROPERTY( int undoDepth READ undoDepth WRITE setUndoDepth )
+ Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly )
+ Q_PROPERTY( bool overWriteMode READ isOverwriteMode WRITE setOverwriteMode )
+ Q_PROPERTY( QString text READ text WRITE setText )
+ Q_PROPERTY( int length READ length )
+
+public:
+ QtMultiLineEdit( QWidget *parent=0, const char *name=0 );
+ ~QtMultiLineEdit();
+
+ QString textLine( int line ) const;
+ int numLines() const;
+
+ QSize sizeHint() const;
+ QSize minimumSizeHint() const;
+ QSizePolicy sizePolicy() const;
+
+ virtual void setFont( const QFont &font );
+
+ virtual void insertLine( const QString &s, int line = -1 );
+ virtual void insertAt( const QString &s, int line, int col, bool mark = FALSE );
+ virtual void removeLine( int line );
+
+ void cursorPosition( int *line, int *col ) const;
+ virtual void setCursorPosition( int line, int col, bool mark = FALSE );
+ void getCursorPosition( int *line, int *col ) const;
+ bool atBeginning() const;
+ bool atEnd() const;
+
+ virtual void setFixedVisibleLines( int lines );
+
+ int maxLineWidth() const;
+
+ void setAlignment( int flags );
+ int alignment() const;
+
+ virtual void setValidator( const QValidator * );
+ const QValidator * validator() const;
+
+ void setEdited( bool );
+ bool edited() const;
+
+ void cursorWordForward( bool mark );
+ void cursorWordBackward( bool mark );
+
+ enum EchoMode { Normal, NoEcho, Password };
+ virtual void setEchoMode( EchoMode );
+ EchoMode echoMode() const;
+
+ void setMaxLength(int);
+ int maxLength() const;
+ virtual void setMaxLineLength(int);
+ int maxLineLength() const;
+ virtual void setMaxLines(int);
+ int maxLines() const;
+ virtual void setHMargin(int);
+ int hMargin() const;
+
+ virtual void setSelection( int row_from, int col_from, int row_to, int col_t );
+
+ enum WordWrap {
+ NoWrap,
+ WidgetWidth,
+ FixedPixelWidth,
+ FixedColumnWidth
+ };
+ void setWordWrap( WordWrap mode );
+ WordWrap wordWrap() const;
+ void setWrapColumnOrWidth( int );
+ int wrapColumnOrWidth() const;
+
+ enum WrapPolicy {
+ AtWhiteSpace,
+ Anywhere
+ };
+ void setWrapPolicy( WrapPolicy policy );
+ WrapPolicy wrapPolicy() const;
+
+ bool autoUpdate() const;
+ virtual void setAutoUpdate( bool );
+
+ void setUndoEnabled( bool );
+ bool isUndoEnabled() const;
+ void setUndoDepth( int );
+ int undoDepth() const;
+
+ bool isReadOnly() const;
+ bool isOverwriteMode() const;
+
+ QString text() const;
+
+ int length() const;
+
+ static void setDefaultTabStop( int ex );
+ static int defaultTabStop();
+public slots:
+ virtual void setText( const QString &);
+ virtual void setReadOnly( bool );
+ virtual void setOverwriteMode( bool );
+
+ void clear();
+ void append( const QString &);
+ void deselect();
+ void selectAll();
+#ifndef QT_NO_CLIPBOARD
+ void paste();
+ void pasteSubType(const QCString& subtype);
+ void copyText() const;
+ void copy() const;
+ void cut();
+#endif
+ void insert( const QString& );
+ void undo();
+ void redo();
+
+signals:
+ void textChanged();
+ void returnPressed();
+ void undoAvailable( bool );
+ void redoAvailable( bool );
+ void copyAvailable( bool );
+
+protected:
+ void paintCell( QPainter *, int row, int col );
+ bool event( QEvent * );
+
+ void mousePressEvent( QMouseEvent * );
+ void mouseMoveEvent( QMouseEvent * );
+ void mouseReleaseEvent( QMouseEvent * );
+ void mouseDoubleClickEvent( QMouseEvent * );
+ void wheelEvent( QWheelEvent * );
+ void keyPressEvent( QKeyEvent * );
+ void focusInEvent( QFocusEvent * );
+ void focusOutEvent( QFocusEvent * );
+ void timerEvent( QTimerEvent * );
+ void leaveEvent( QEvent * );
+ void resizeEvent( QResizeEvent * );
+
+ bool focusNextPrevChild( bool );
+
+#ifndef QT_NO_DRAGANDDROP
+ void dragMoveEvent( QDragMoveEvent* );
+ void dragEnterEvent( QDragEnterEvent * );
+ void dropEvent( QDropEvent* );
+ void dragLeaveEvent( QDragLeaveEvent* );
+#endif
+
+ bool hasMarkedText() const;
+ QString markedText() const;
+ int textWidth( int );
+ int textWidth( const QString &);
+
+ QPoint cursorPoint() const;
+
+protected:
+ virtual void insert( const QString&, bool mark );
+ virtual void newLine();
+ virtual void killLine();
+ virtual void pageUp( bool mark=FALSE );
+ virtual void pageDown( bool mark=FALSE );
+ virtual void cursorLeft( bool mark=FALSE, bool wrap = TRUE );
+ virtual void cursorRight( bool mark=FALSE, bool wrap = TRUE );
+ virtual void cursorUp( bool mark=FALSE );
+ virtual void cursorDown( bool mark=FALSE );
+ virtual void backspace();
+ virtual void del();
+ virtual void home( bool mark=FALSE );
+ virtual void end( bool mark=FALSE );
+
+ bool getMarkedRegion( int *line1, int *col1,
+ int *line2, int *col2 ) const;
+ int lineLength( int row ) const;
+ QString *getString( int row ) const;
+ bool isEndOfParagraph( int row ) const;
+ QString stringShown( int row ) const;
+
+protected:
+ bool cursorOn;
+ void insertChar( QChar );
+
+private slots:
+ void clipboardChanged();
+ void blinkTimerTimeout();
+ void scrollTimerTimeout();
+ void dndTimeout();
+
+private:
+#ifndef QT_NO_MIME
+ QCString pickSpecial(QMimeSource* ms, bool always_ask, const QPoint&);
+#endif
+#ifndef QT_NO_MIMECLIPBOARD
+ void pasteSpecial(const QPoint&);
+#endif
+ struct QtMultiLineEditRow {
+ QtMultiLineEditRow( QString string, int width, bool nl = TRUE )
+ :s(string), w(width), newline( nl )
+ {
+ };
+ QString s;
+ int w;
+ bool newline;
+ };
+ QPtrList<QtMultiLineEditRow> *contents;
+ QtMultiLineData *d;
+
+ bool readOnly;
+ bool dummy;
+ bool markIsOn;
+ bool dragScrolling ;
+ bool dragMarking;
+ bool textDirty;
+ bool wordMark;
+ bool overWrite;
+
+ int cursorX;
+ int cursorY;
+ int markAnchorX;
+ int markAnchorY;
+ int markDragX;
+ int markDragY;
+ int curXPos; // cell coord of cursor
+ int blinkTimer; // #### not used anymore - remove in 3.0
+ int scrollTimer; // #### not used anymore - remove in 3.0
+
+ int mapFromView( int xPos, int row );
+ int mapToView( int xIndex, int row );
+
+ void pixelPosToCursorPos(QPoint p, int* x, int* y) const;
+ void setCursorPixelPosition(QPoint p, bool clear_mark=TRUE);
+
+ void setWidth( int );
+ void updateCellWidth();
+ bool partiallyInvisible( int row );
+ void makeVisible();
+ void setBottomCell( int row );
+
+ void newMark( int posx, int posy, bool copy=TRUE );
+ void markWord( int posx, int posy );
+ void extendSelectionWord( int &newX, int&newY);
+ int charClass( QChar );
+ void turnMark( bool on );
+ bool inMark( int posx, int posy ) const;
+ bool beforeMark( int posx, int posy ) const;
+ bool afterMark( int posx, int posy ) const;
+ int setNumRowsAndTruncate();
+
+#ifndef QT_NO_DRAGANDDROP
+ void doDrag();
+#endif
+ void startAutoScroll();
+ void stopAutoScroll();
+
+ void cursorLeft( bool mark, bool clear_mark, bool wrap );
+ void cursorRight( bool mark, bool clear_mark, bool wrap );
+ void cursorUp( bool mark, bool clear_mark );
+ void cursorDown( bool mark, bool clear_mark );
+
+ void wrapLine( int line, int removed = 0);
+ void rebreakParagraph( int line, int removed = 0 );
+ void rebreakAll();
+ void insertAtAux( const QString &s, int line, int col, bool mark = FALSE );
+ void killLineAux();
+ void delAux();
+ int positionToOffsetInternal( int row, int col ) const;
+ void offsetToPositionInternal( int position, int *row, int *col ) const;
+ void deleteNextChar( int offset, int row, int col );
+
+ void addUndoCmd( QtMultiLineEditCommand* );
+ void addRedoCmd( QtMultiLineEditCommand* );
+ void processCmd( QtMultiLineEditCommand*, bool );
+
+private: // Disabled copy constructor and operator=
+#if defined(Q_DISABLE_COPY)
+ QtMultiLineEdit( const QtMultiLineEdit & );
+ QtMultiLineEdit &operator=( const QtMultiLineEdit & );
+#endif
+};
+
+inline bool QtMultiLineEdit::isReadOnly() const { return readOnly; }
+
+inline bool QtMultiLineEdit::isOverwriteMode() const { return overWrite; }
+
+inline void QtMultiLineEdit::setOverwriteMode( bool on )
+{
+ overWrite = on;
+ }
+
+inline int QtMultiLineEdit::lineLength( int row ) const
+{
+ return contents->at( row )->s.length();
+}
+
+inline bool QtMultiLineEdit::atEnd() const
+{
+ return cursorY == (int)contents->count() - 1
+ && cursorX == lineLength( cursorY ) ;
+}
+
+inline bool QtMultiLineEdit::atBeginning() const
+{
+ return cursorY == 0 && cursorX == 0;
+}
+
+inline QString *QtMultiLineEdit::getString( int row ) const
+{
+ return &(contents->at( row )->s);
+}
+
+inline int QtMultiLineEdit::numLines() const
+{
+ return contents->count();
+}
+
+#endif // QT_NO_QTMULTILINEEDIT
+
+#endif // QTMULTILINEDIT_H
diff --git a/src/attic/qttableview.cpp b/src/attic/qttableview.cpp
new file mode 100644
index 0000000..16fc836
--- /dev/null
+++ b/src/attic/qttableview.cpp
@@ -0,0 +1,2272 @@
+/**********************************************************************
+**
+** Implementation of QtTableView class
+**
+** Created : 941115
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file contains a class moved out of the Qt GUI Toolkit API. It
+** may be used, distributed and modified without limitation.
+**
+**********************************************************************/
+
+#include "qttableview.h"
+#ifndef QT_NO_QTTABLEVIEW
+#include "qscrollbar.h"
+#include "qpainter.h"
+#include "qdrawutil.h"
+#include <limits.h>
+
+enum ScrollBarDirtyFlags {
+ verGeometry = 0x01,
+ verSteps = 0x02,
+ verRange = 0x04,
+ verValue = 0x08,
+ horGeometry = 0x10,
+ horSteps = 0x20,
+ horRange = 0x40,
+ horValue = 0x80,
+ verMask = 0x0F,
+ horMask = 0xF0
+};
+
+
+#define HSBEXT horizontalScrollBar()->sizeHint().height()
+#define VSBEXT verticalScrollBar()->sizeHint().width()
+
+
+class QCornerSquare : public QWidget // internal class
+{
+public:
+ QCornerSquare( QWidget *, const char* = 0 );
+ void paintEvent( QPaintEvent * );
+};
+
+QCornerSquare::QCornerSquare( QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+}
+
+void QCornerSquare::paintEvent( QPaintEvent * )
+{
+}
+
+
+// NOT REVISED
+/*
+ \class QtTableView qttableview.h
+ \brief The QtTableView class provides an abstract base for tables.
+
+ \obsolete
+
+ A table view consists of a number of abstract cells organized in rows
+ and columns, and a visible part called a view. The cells are identified
+ with a row index and a column index. The top-left cell is in row 0,
+ column 0.
+
+ The behavior of the widget can be finely tuned using
+ setTableFlags(); a typical subclass will consist of little more than a
+ call to setTableFlags(), some table content manipulation and an
+ implementation of paintCell(). Subclasses that need cells with
+ variable width or height must reimplement cellHeight() and/or
+ cellWidth(). Use updateTableSize() to tell QtTableView when the
+ width or height has changed.
+
+ When you read this documentation, it is important to understand the
+ distinctions among the four pixel coordinate systems involved.
+
+ \list 1
+ \i The \e cell coordinates. (0,0) is the top-left corner of a cell.
+ Cell coordinates are used by functions such as paintCell().
+
+ \i The \e table coordinates. (0,0) is the top-left corner of the cell at
+ row 0 and column 0. These coordinates are absolute; that is, they are
+ independent of what part of the table is visible at the moment. They are
+ used by functions such as setXOffset() or maxYOffset().
+
+ \i The \e widget coordinates. (0,0) is the top-left corner of the widget,
+ \e including the frame. They are used by functions such as repaint().
+
+ \i The \e view coordinates. (0,0) is the top-left corner of the view, \e
+ excluding the frame. This is the least-used coordinate system; it is used by
+ functions such as viewWidth(). \endlist
+
+ It is rather unfortunate that we have to use four different
+ coordinate systems, but there was no alternative to provide a flexible and
+ powerful base class.
+
+ Note: The row,column indices are always given in that order,
+ i.e., first the vertical (row), then the horizontal (column). This is
+ the opposite order of all pixel operations, which take first the
+ horizontal (x) and then the vertical (y).
+
+ <img src=qtablevw-m.png> <img src=qtablevw-w.png>
+
+ \warning the functions setNumRows(), setNumCols(), setCellHeight(),
+ setCellWidth(), setTableFlags() and clearTableFlags() may cause
+ virtual functions such as cellWidth() and cellHeight() to be called,
+ even if autoUpdate() is FALSE. This may cause errors if relevant
+ state variables are not initialized.
+
+ \warning Experience has shown that use of this widget tends to cause
+ more bugs than expected and our analysis indicates that the widget's
+ very flexibility is the problem. If QScrollView or QListBox can
+ easily be made to do the job you need, we recommend subclassing
+ those widgets rather than QtTableView. In addition, QScrollView makes
+ it easy to have child widgets inside tables, which QtTableView
+ doesn't support at all.
+
+ \sa QScrollView
+ \link guibooks.html#fowler GUI Design Handbook: Table\endlink
+*/
+
+
+/*
+ Constructs a table view. The \a parent, \a name and \f arguments
+ are passed to the QFrame constructor.
+
+ The \link setTableFlags() table flags\endlink are all cleared (set to 0).
+ Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll
+ bars and \c Tbl_clipCellPainting to get safe clipping.
+
+ The \link setCellHeight() cell height\endlink and \link setCellWidth()
+ cell width\endlink are set to 0.
+
+ Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed;
+ see QFrame::setFrameStyle().
+
+ Note that the \a f argument is \e not \link setTableFlags() table
+ flags \endlink but rather \link QWidget::QWidget() widget
+ flags. \endlink
+
+*/
+
+QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f )
+ : QFrame( parent, name, f )
+{
+ nRows = nCols = 0; // zero rows/cols
+ xCellOffs = yCellOffs = 0; // zero offset
+ xCellDelta = yCellDelta = 0; // zero cell offset
+ xOffs = yOffs = 0; // zero total pixel offset
+ cellH = cellW = 0; // user defined cell size
+ tFlags = 0;
+ vScrollBar = hScrollBar = 0; // no scroll bars
+ cornerSquare = 0;
+ sbDirty = 0;
+ eraseInPaint = FALSE;
+ verSliding = FALSE;
+ verSnappingOff = FALSE;
+ horSliding = FALSE;
+ horSnappingOff = FALSE;
+ coveringCornerSquare = FALSE;
+ inSbUpdate = FALSE;
+}
+
+/*
+ Destroys the table view.
+*/
+
+QtTableView::~QtTableView()
+{
+ delete vScrollBar;
+ delete hScrollBar;
+ delete cornerSquare;
+}
+
+
+/*
+ \internal
+ Reimplements QWidget::setBackgroundColor() for binary compatibility.
+ \sa setPalette()
+*/
+
+void QtTableView::setBackgroundColor( const QColor &c )
+{
+ QWidget::setBackgroundColor( c );
+}
+
+/*\reimp
+*/
+
+void QtTableView::setPalette( const QPalette &p )
+{
+ QWidget::setPalette( p );
+}
+
+/*\reimp
+*/
+
+void QtTableView::show()
+{
+ showOrHideScrollBars();
+ QWidget::show();
+}
+
+
+/*
+ \overload void QtTableView::repaint( bool erase )
+ Repaints the entire view.
+*/
+
+/*
+ Repaints the table view directly by calling paintEvent() directly
+ unless updates are disabled.
+
+ Erases the view area \a (x,y,w,h) if \a erase is TRUE. Parameters \a
+ (x,y) are in \e widget coordinates.
+
+ If \a w is negative, it is replaced with <code>width() - x</code>.
+ If \a h is negative, it is replaced with <code>height() - y</code>.
+
+ Doing a repaint() usually is faster than doing an update(), but
+ calling update() many times in a row will generate a single paint
+ event.
+
+ At present, QtTableView is the only widget that reimplements \link
+ QWidget::repaint() repaint()\endlink. It does this because by
+ clearing and then repainting one cell at at time, it can make the
+ screen flicker less than it would otherwise. */
+
+void QtTableView::repaint( int x, int y, int w, int h, bool erase )
+{
+ if ( !isVisible() || testWState(WState_BlockUpdates) )
+ return;
+ if ( w < 0 )
+ w = width() - x;
+ if ( h < 0 )
+ h = height() - y;
+ QRect r( x, y, w, h );
+ if ( r.isEmpty() )
+ return; // nothing to do
+ QPaintEvent e( r );
+ if ( erase && backgroundMode() != NoBackground )
+ eraseInPaint = TRUE; // erase when painting
+ paintEvent( &e );
+ eraseInPaint = FALSE;
+}
+
+/*
+ \overload void QtTableView::repaint( const QRect &r, bool erase )
+ Replaints rectangle \a r. If \a erase is TRUE draws the background
+ using the palette's background.
+*/
+
+
+/*
+ \fn int QtTableView::numRows() const
+ Returns the number of rows in the table.
+ \sa numCols(), setNumRows()
+*/
+
+/*
+ Sets the number of rows of the table to \a rows (must be non-negative).
+ Does not change topCell().
+
+ The table repaints itself automatically if autoUpdate() is set.
+
+ \sa numCols(), setNumCols(), numRows()
+*/
+
+void QtTableView::setNumRows( int rows )
+{
+ if ( rows < 0 ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "QtTableView::setNumRows: (%s) Negative argument %d.",
+ name( "unnamed" ), rows );
+#endif
+ return;
+ }
+ if ( nRows == rows )
+ return;
+
+ if ( autoUpdate() && isVisible() ) {
+ int oldLastVisible = lastRowVisible();
+ int oldTopCell = topCell();
+ nRows = rows;
+ if ( autoUpdate() && isVisible() &&
+ ( oldLastVisible != lastRowVisible() || oldTopCell != topCell() ) )
+ repaint( oldTopCell != topCell() );
+ } else {
+ // Be more careful - if destructing, bad things might happen.
+ nRows = rows;
+ }
+ updateScrollBars( verRange );
+ updateFrameSize();
+}
+
+/*
+ \fn int QtTableView::numCols() const
+ Returns the number of columns in the table.
+ \sa numRows(), setNumCols()
+*/
+
+/*
+ Sets the number of columns of the table to \a cols (must be non-negative).
+ Does not change leftCell().
+
+ The table repaints itself automatically if autoUpdate() is set.
+
+ \sa numCols(), numRows(), setNumRows()
+*/
+
+void QtTableView::setNumCols( int cols )
+{
+ if ( cols < 0 ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "QtTableView::setNumCols: (%s) Negative argument %d.",
+ name( "unnamed" ), cols );
+#endif
+ return;
+ }
+ if ( nCols == cols )
+ return;
+ int oldCols = nCols;
+ nCols = cols;
+ if ( autoUpdate() && isVisible() ) {
+ int maxCol = lastColVisible();
+ if ( maxCol >= oldCols || maxCol >= nCols )
+ repaint();
+ }
+ updateScrollBars( horRange );
+ updateFrameSize();
+}
+
+
+/*
+ \fn int QtTableView::topCell() const
+ Returns the index of the first row in the table that is visible in
+ the view. The index of the first row is 0.
+ \sa leftCell(), setTopCell()
+*/
+
+/*
+ Scrolls the table so that \a row becomes the top row.
+ The index of the very first row is 0.
+ \sa setYOffset(), setTopLeftCell(), setLeftCell()
+*/
+
+void QtTableView::setTopCell( int row )
+{
+ setTopLeftCell( row, -1 );
+ return;
+}
+
+/*
+ \fn int QtTableView::leftCell() const
+ Returns the index of the first column in the table that is visible in
+ the view. The index of the very leftmost column is 0.
+ \sa topCell(), setLeftCell()
+*/
+
+/*
+ Scrolls the table so that \a col becomes the leftmost
+ column. The index of the leftmost column is 0.
+ \sa setXOffset(), setTopLeftCell(), setTopCell()
+*/
+
+void QtTableView::setLeftCell( int col )
+{
+ setTopLeftCell( -1, col );
+ return;
+}
+
+/*
+ Scrolls the table so that the cell at row \a row and colum \a
+ col becomes the top-left cell in the view. The cell at the extreme
+ top left of the table is at position (0,0).
+ \sa setLeftCell(), setTopCell(), setOffset()
+*/
+
+void QtTableView::setTopLeftCell( int row, int col )
+{
+ int newX = xOffs;
+ int newY = yOffs;
+
+ if ( col >= 0 ) {
+ if ( cellW ) {
+ newX = col*cellW;
+ if ( newX > maxXOffset() )
+ newX = maxXOffset();
+ } else {
+ newX = 0;
+ while ( col )
+ newX += cellWidth( --col ); // optimize using current! ###
+ }
+ }
+ if ( row >= 0 ) {
+ if ( cellH ) {
+ newY = row*cellH;
+ if ( newY > maxYOffset() )
+ newY = maxYOffset();
+ } else {
+ newY = 0;
+ while ( row )
+ newY += cellHeight( --row ); // optimize using current! ###
+ }
+ }
+ setOffset( newX, newY );
+}
+
+
+/*
+ \fn int QtTableView::xOffset() const
+
+ Returns the x coordinate in \e table coordinates of the pixel that is
+ currently on the left edge of the view.
+
+ \sa setXOffset(), yOffset(), leftCell() */
+
+/*
+ Scrolls the table so that \a x becomes the leftmost pixel in the view.
+ The \a x parameter is in \e table coordinates.
+
+ The interaction with \link setTableFlags() Tbl_snapToHGrid
+ \endlink is tricky.
+
+ \sa xOffset(), setYOffset(), setOffset(), setLeftCell()
+*/
+
+void QtTableView::setXOffset( int x )
+{
+ setOffset( x, yOffset() );
+}
+
+/*
+ \fn int QtTableView::yOffset() const
+
+ Returns the y coordinate in \e table coordinates of the pixel that is
+ currently on the top edge of the view.
+
+ \sa setYOffset(), xOffset(), topCell()
+*/
+
+
+/*
+ Scrolls the table so that \a y becomes the top pixel in the view.
+ The \a y parameter is in \e table coordinates.
+
+ The interaction with \link setTableFlags() Tbl_snapToVGrid
+ \endlink is tricky.
+
+ \sa yOffset(), setXOffset(), setOffset(), setTopCell()
+*/
+
+void QtTableView::setYOffset( int y )
+{
+ setOffset( xOffset(), y );
+}
+
+/*
+ Scrolls the table so that \a (x,y) becomes the top-left pixel
+ in the view. Parameters \a (x,y) are in \e table coordinates.
+
+ The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink
+ is tricky. If \a updateScrBars is TRUE, the scroll bars are
+ updated.
+
+ \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell()
+*/
+
+void QtTableView::setOffset( int x, int y, bool updateScrBars )
+{
+ if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) &&
+ (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) &&
+ (x == xOffs && y == yOffs) )
+ return;
+
+ if ( x < 0 )
+ x = 0;
+ if ( y < 0 )
+ y = 0;
+
+ if ( cellW ) {
+ if ( x > maxXOffset() )
+ x = maxXOffset();
+ xCellOffs = x / cellW;
+ if ( !testTableFlags(Tbl_snapToHGrid) ) {
+ xCellDelta = (short)(x % cellW);
+ } else {
+ x = xCellOffs*cellW;
+ xCellDelta = 0;
+ }
+ } else {
+ int xn=0, xcd=0, col = 0;
+ while ( col < nCols-1 && x >= xn+(xcd=cellWidth(col)) ) {
+ xn += xcd;
+ col++;
+ }
+ xCellOffs = col;
+ if ( testTableFlags(Tbl_snapToHGrid) ) {
+ xCellDelta = 0;
+ x = xn;
+ } else {
+ xCellDelta = (short)(x-xn);
+ }
+ }
+ if ( cellH ) {
+ if ( y > maxYOffset() )
+ y = maxYOffset();
+ yCellOffs = y / cellH;
+ if ( !testTableFlags(Tbl_snapToVGrid) ) {
+ yCellDelta = (short)(y % cellH);
+ } else {
+ y = yCellOffs*cellH;
+ yCellDelta = 0;
+ }
+ } else {
+ int yn=0, yrd=0, row=0;
+ while ( row < nRows-1 && y >= yn+(yrd=cellHeight(row)) ) {
+ yn += yrd;
+ row++;
+ }
+ yCellOffs = row;
+ if ( testTableFlags(Tbl_snapToVGrid) ) {
+ yCellDelta = 0;
+ y = yn;
+ } else {
+ yCellDelta = (short)(y-yn);
+ }
+ }
+ int dx = (x - xOffs);
+ int dy = (y - yOffs);
+ xOffs = x;
+ yOffs = y;
+ if ( autoUpdate() && isVisible() )
+ scroll( dx, dy );
+ if ( updateScrBars )
+ updateScrollBars( verValue | horValue );
+}
+
+
+/*
+ \overload int QtTableView::cellWidth() const
+
+ Returns the column width in pixels. Returns 0 if the columns have
+ variable widths.
+
+ \sa setCellWidth(), cellHeight()
+*/
+
+/*
+ Returns the width of column \a col in pixels.
+
+ This function is virtual and must be reimplemented by subclasses that
+ have variable cell widths. Note that if the total table width
+ changes, updateTableSize() must be called.
+
+ \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize()
+*/
+
+int QtTableView::cellWidth( int )
+{
+ return cellW;
+}
+
+
+/*
+ Sets the width in pixels of the table cells to \a cellWidth.
+
+ Setting it to 0 means that the column width is variable. When
+ set to 0 (this is the default) QtTableView calls the virtual function
+ cellWidth() to get the width.
+
+ \sa cellWidth(), setCellHeight(), totalWidth(), numCols()
+*/
+
+void QtTableView::setCellWidth( int cellWidth )
+{
+ if ( cellW == cellWidth )
+ return;
+#if defined(QT_CHECK_RANGE)
+ if ( cellWidth < 0 || cellWidth > SHRT_MAX ) {
+ qWarning( "QtTableView::setCellWidth: (%s) Argument out of range (%d)",
+ name( "unnamed" ), cellWidth );
+ return;
+ }
+#endif
+ cellW = (short)cellWidth;
+
+ updateScrollBars( horSteps | horRange );
+ if ( autoUpdate() && isVisible() )
+ repaint();
+
+}
+
+/*
+ \overload int QtTableView::cellHeight() const
+
+ Returns the row height, in pixels. Returns 0 if the rows have
+ variable heights.
+
+ \sa setCellHeight(), cellWidth()
+*/
+
+
+/*
+ Returns the height of row \a row in pixels.
+
+ This function is virtual and must be reimplemented by subclasses that
+ have variable cell heights. Note that if the total table height
+ changes, updateTableSize() must be called.
+
+ \sa setCellHeight(), cellWidth(), totalHeight()
+*/
+
+int QtTableView::cellHeight( int )
+{
+ return cellH;
+}
+
+/*
+ Sets the height in pixels of the table cells to \a cellHeight.
+
+ Setting it to 0 means that the row height is variable. When set
+ to 0 (this is the default), QtTableView calls the virtual function
+ cellHeight() to get the height.
+
+ \sa cellHeight(), setCellWidth(), totalHeight(), numRows()
+*/
+
+void QtTableView::setCellHeight( int cellHeight )
+{
+ if ( cellH == cellHeight )
+ return;
+#if defined(QT_CHECK_RANGE)
+ if ( cellHeight < 0 || cellHeight > SHRT_MAX ) {
+ qWarning( "QtTableView::setCellHeight: (%s) Argument out of range (%d)",
+ name( "unnamed" ), cellHeight );
+ return;
+ }
+#endif
+ cellH = (short)cellHeight;
+ if ( autoUpdate() && isVisible() )
+ repaint();
+ updateScrollBars( verSteps | verRange );
+}
+
+
+/*
+ Returns the total width of the table in pixels.
+
+ This function is virtual and should be reimplemented by subclasses that
+ have variable cell widths and a non-trivial cellWidth() function, or a
+ large number of columns in the table.
+
+ The default implementation may be slow for very wide tables.
+
+ \sa cellWidth(), totalHeight() */
+
+int QtTableView::totalWidth()
+{
+ if ( cellW ) {
+ return cellW*nCols;
+ } else {
+ int tw = 0;
+ for( int i = 0 ; i < nCols ; i++ )
+ tw += cellWidth( i );
+ return tw;
+ }
+}
+
+/*
+ Returns the total height of the table in pixels.
+
+ This function is virtual and should be reimplemented by subclasses that
+ have variable cell heights and a non-trivial cellHeight() function, or a
+ large number of rows in the table.
+
+ The default implementation may be slow for very tall tables.
+
+ \sa cellHeight(), totalWidth()
+*/
+
+int QtTableView::totalHeight()
+{
+ if ( cellH ) {
+ return cellH*nRows;
+ } else {
+ int th = 0;
+ for( int i = 0 ; i < nRows ; i++ )
+ th += cellHeight( i );
+ return th;
+ }
+}
+
+
+/*
+ \fn uint QtTableView::tableFlags() const
+
+ Returns the union of the table flags that are currently set.
+
+ \sa setTableFlags(), clearTableFlags(), testTableFlags()
+*/
+
+/*
+ \fn bool QtTableView::testTableFlags( uint f ) const
+
+ Returns TRUE if any of the table flags in \a f are currently set,
+ otherwise FALSE.
+
+ \sa setTableFlags(), clearTableFlags(), tableFlags()
+*/
+
+/*
+ Sets the table flags to \a f.
+
+ If a flag setting changes the appearance of the table, the table is
+ repainted if - and only if - autoUpdate() is TRUE.
+
+ The table flags are mostly single bits, though there are some multibit
+ flags for convenience. Here is a complete list:
+
+ <dl compact>
+ <dt> Tbl_vScrollBar <dd> - The table has a vertical scroll bar.
+ <dt> Tbl_hScrollBar <dd> - The table has a horizontal scroll bar.
+ <dt> Tbl_autoVScrollBar <dd> - The table has a vertical scroll bar if
+ - and only if - the table is taller than the view.
+ <dt> Tbl_autoHScrollBar <dd> The table has a horizontal scroll bar if
+ - and only if - the table is wider than the view.
+ <dt> Tbl_autoScrollBars <dd> - The union of the previous two flags.
+ <dt> Tbl_clipCellPainting <dd> - The table uses QPainter::setClipRect() to
+ make sure that paintCell() will not draw outside the cell
+ boundaries.
+ <dt> Tbl_cutCellsV <dd> - The table will never show part of a
+ cell at the bottom of the table; if there is not space for all of
+ a cell, the space is left blank.
+ <dt> Tbl_cutCellsH <dd> - The table will never show part of a
+ cell at the right side of the table; if there is not space for all of
+ a cell, the space is left blank.
+ <dt> Tbl_cutCells <dd> - The union of the previous two flags.
+ <dt> Tbl_scrollLastHCell <dd> - When the user scrolls horizontally,
+ let him/her scroll the last cell left until it is at the left
+ edge of the view. If this flag is not set, the user can only scroll
+ to the point where the last cell is completely visible.
+ <dt> Tbl_scrollLastVCell <dd> - When the user scrolls vertically, let
+ him/her scroll the last cell up until it is at the top edge of
+ the view. If this flag is not set, the user can only scroll to the
+ point where the last cell is completely visible.
+ <dt> Tbl_scrollLastCell <dd> - The union of the previous two flags.
+ <dt> Tbl_smoothHScrolling <dd> - The table scrolls as smoothly as
+ possible when the user scrolls horizontally. When this flag is not
+ set, scrolling is done one cell at a time.
+ <dt> Tbl_smoothVScrolling <dd> - The table scrolls as smoothly as
+ possible when scrolling vertically. When this flag is not set,
+ scrolling is done one cell at a time.
+ <dt> Tbl_smoothScrolling <dd> - The union of the previous two flags.
+ <dt> Tbl_snapToHGrid <dd> - Except when the user is actually scrolling,
+ the leftmost column shown snaps to the leftmost edge of the view.
+ <dt> Tbl_snapToVGrid <dd> - Except when the user is actually
+ scrolling, the top row snaps to the top edge of the view.
+ <dt> Tbl_snapToGrid <dd> - The union of the previous two flags.
+ </dl>
+
+ You can specify more than one flag at a time using bitwise OR.
+
+ Example:
+ \code
+ setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars );
+ \endcode
+
+ \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and
+ Tbl_cutCellsV) may cause painting problems when scrollbars are
+ enabled. Do not combine cutCells and scrollbars.
+
+
+ \sa clearTableFlags(), testTableFlags(), tableFlags()
+*/
+
+void QtTableView::setTableFlags( uint f )
+{
+ f = (f ^ tFlags) & f; // clear flags already set
+ tFlags |= f;
+
+ bool updateOn = autoUpdate();
+ setAutoUpdate( FALSE );
+
+ uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
+
+ if ( f & Tbl_vScrollBar ) {
+ setVerScrollBar( TRUE );
+ }
+ if ( f & Tbl_hScrollBar ) {
+ setHorScrollBar( TRUE );
+ }
+ if ( f & Tbl_autoVScrollBar ) {
+ updateScrollBars( verRange );
+ }
+ if ( f & Tbl_autoHScrollBar ) {
+ updateScrollBars( horRange );
+ }
+ if ( f & Tbl_scrollLastHCell ) {
+ updateScrollBars( horRange );
+ }
+ if ( f & Tbl_scrollLastVCell ) {
+ updateScrollBars( verRange );
+ }
+ if ( f & Tbl_snapToHGrid ) {
+ updateScrollBars( horRange );
+ }
+ if ( f & Tbl_snapToVGrid ) {
+ updateScrollBars( verRange );
+ }
+ if ( f & Tbl_snapToGrid ) { // Note: checks for 2 flags
+ if ( (f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || //have to scroll?
+ (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0 ) {
+ snapToGrid( (f & Tbl_snapToHGrid) != 0, // do snapping
+ (f & Tbl_snapToVGrid) != 0 );
+ repaintMask |= Tbl_snapToGrid; // repaint table
+ }
+ }
+
+ if ( updateOn ) {
+ setAutoUpdate( TRUE );
+ updateScrollBars();
+ if ( isVisible() && (f & repaintMask) )
+ repaint();
+ }
+
+}
+
+/*
+ Clears the \link setTableFlags() table flags\endlink that are set
+ in \a f.
+
+ Example (clears a single flag):
+ \code
+ clearTableFlags( Tbl_snapToGrid );
+ \endcode
+
+ The default argument clears all flags.
+
+ \sa setTableFlags(), testTableFlags(), tableFlags()
+*/
+
+void QtTableView::clearTableFlags( uint f )
+{
+ f = (f ^ ~tFlags) & f; // clear flags that are already 0
+ tFlags &= ~f;
+
+ bool updateOn = autoUpdate();
+ setAutoUpdate( FALSE );
+
+ uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH;
+
+ if ( f & Tbl_vScrollBar ) {
+ setVerScrollBar( FALSE );
+ }
+ if ( f & Tbl_hScrollBar ) {
+ setHorScrollBar( FALSE );
+ }
+ if ( f & Tbl_scrollLastHCell ) {
+ int maxX = maxXOffset();
+ if ( xOffs > maxX ) {
+ setOffset( maxX, yOffs );
+ repaintMask |= Tbl_scrollLastHCell;
+ }
+ updateScrollBars( horRange );
+ }
+ if ( f & Tbl_scrollLastVCell ) {
+ int maxY = maxYOffset();
+ if ( yOffs > maxY ) {
+ setOffset( xOffs, maxY );
+ repaintMask |= Tbl_scrollLastVCell;
+ }
+ updateScrollBars( verRange );
+ }
+ if ( f & Tbl_smoothScrolling ) { // Note: checks for 2 flags
+ if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 ||//must scroll?
+ (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0 ) {
+ snapToGrid( (f & Tbl_smoothHScrolling) != 0, // do snapping
+ (f & Tbl_smoothVScrolling) != 0 );
+ repaintMask |= Tbl_smoothScrolling; // repaint table
+ }
+ }
+ if ( f & Tbl_snapToHGrid ) {
+ updateScrollBars( horRange );
+ }
+ if ( f & Tbl_snapToVGrid ) {
+ updateScrollBars( verRange );
+ }
+ if ( updateOn ) {
+ setAutoUpdate( TRUE );
+ updateScrollBars(); // returns immediately if nothing to do
+ if ( isVisible() && (f & repaintMask) )
+ repaint();
+ }
+
+}
+
+
+/*
+ \fn bool QtTableView::autoUpdate() const
+
+ Returns TRUE if the view updates itself automatically whenever it
+ is changed in some way.
+
+ \sa setAutoUpdate()
+*/
+
+/*
+ Sets the auto-update option of the table view to \a enable.
+
+ If \a enable is TRUE (this is the default), the view updates itself
+ automatically whenever it has changed in some way (for example, when a
+ \link setTableFlags() flag\endlink is changed).
+
+ If \a enable is FALSE, the view does NOT repaint itself or update
+ its internal state variables when it is changed. This can be
+ useful to avoid flicker during large changes and is singularly
+ useless otherwise. Disable auto-update, do the changes, re-enable
+ auto-update and call repaint().
+
+ \warning Do not leave the view in this state for a long time
+ (i.e., between events). If, for example, the user interacts with the
+ view when auto-update is off, strange things can happen.
+
+ Setting auto-update to TRUE does not repaint the view; you must call
+ repaint() to do this.
+
+ \sa autoUpdate(), repaint()
+*/
+
+void QtTableView::setAutoUpdate( bool enable )
+{
+ if ( isUpdatesEnabled() == enable )
+ return;
+ setUpdatesEnabled( enable );
+ if ( enable ) {
+ showOrHideScrollBars();
+ updateScrollBars();
+ }
+}
+
+
+/*
+ Repaints the cell at row \a row, column \a col if it is inside the view.
+
+ If \a erase is TRUE, the relevant part of the view is cleared to the
+ background color/pixmap before the contents are repainted.
+
+ \sa isVisible()
+*/
+
+void QtTableView::updateCell( int row, int col, bool erase )
+{
+ int xPos, yPos;
+ if ( !colXPos( col, &xPos ) )
+ return;
+ if ( !rowYPos( row, &yPos ) )
+ return;
+ QRect uR = QRect( xPos, yPos,
+ cellW ? cellW : cellWidth(col),
+ cellH ? cellH : cellHeight(row) );
+ repaint( uR.intersect(viewRect()), erase );
+}
+
+
+/*
+ \fn QRect QtTableView::cellUpdateRect() const
+
+ This function should be called only from the paintCell() function in
+ subclasses. It returns the portion of a cell that actually needs to be
+ updated in \e cell coordinates. This is useful only for non-trivial
+ paintCell().
+
+*/
+
+/*
+ Returns the rectangle that is the actual table, excluding any
+ frame, in \e widget coordinates.
+*/
+
+QRect QtTableView::viewRect() const
+{
+ return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() );
+}
+
+
+/*
+ Returns the index of the last (bottom) row in the view.
+ The index of the first row is 0.
+
+ If no rows are visible it returns -1. This can happen if the
+ view is too small for the first row and Tbl_cutCellsV is set.
+
+ \sa lastColVisible()
+*/
+
+int QtTableView::lastRowVisible() const
+{
+ int cellMaxY;
+ int row = findRawRow( maxViewY(), &cellMaxY );
+ if ( row == -1 || row >= nRows ) { // maxViewY() past end?
+ row = nRows - 1; // yes: return last row
+ } else {
+ if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) {
+ if ( row == yCellOffs ) // cut by right margin?
+ return -1; // yes, nothing in the view
+ else
+ row = row - 1; // cut by margin, one back
+ }
+ }
+ return row;
+}
+
+/*
+ Returns the index of the last (right) column in the view.
+ The index of the first column is 0.
+
+ If no columns are visible it returns -1. This can happen if the
+ view is too narrow for the first column and Tbl_cutCellsH is set.
+
+ \sa lastRowVisible()
+*/
+
+int QtTableView::lastColVisible() const
+{
+ int cellMaxX;
+ int col = findRawCol( maxViewX(), &cellMaxX );
+ if ( col == -1 || col >= nCols ) { // maxViewX() past end?
+ col = nCols - 1; // yes: return last col
+ } else {
+ if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) {
+ if ( col == xCellOffs ) // cut by bottom margin?
+ return -1; // yes, nothing in the view
+ else
+ col = col - 1; // cell by margin, one back
+ }
+ }
+ return col;
+}
+
+/*
+ Returns TRUE if \a row is at least partially visible.
+ \sa colIsVisible()
+*/
+
+bool QtTableView::rowIsVisible( int row ) const
+{
+ return rowYPos( row, 0 );
+}
+
+/*
+ Returns TRUE if \a col is at least partially visible.
+ \sa rowIsVisible()
+*/
+
+bool QtTableView::colIsVisible( int col ) const
+{
+ return colXPos( col, 0 );
+}
+
+
+/*
+ \internal
+ Called when both scroll bars are active at the same time. Covers the
+ bottom left corner between the two scroll bars with an empty widget.
+*/
+
+void QtTableView::coverCornerSquare( bool enable )
+{
+ coveringCornerSquare = enable;
+ if ( !cornerSquare && enable ) {
+ cornerSquare = new QCornerSquare( this );
+ Q_CHECK_PTR( cornerSquare );
+ cornerSquare->setGeometry( maxViewX() + frameWidth() + 1,
+ maxViewY() + frameWidth() + 1,
+ VSBEXT,
+ HSBEXT);
+ }
+ if ( autoUpdate() && cornerSquare ) {
+ if ( enable )
+ cornerSquare->show();
+ else
+ cornerSquare->hide();
+ }
+}
+
+
+/*
+ \internal
+ Scroll the view to a position such that:
+
+ If \a horizontal is TRUE, the leftmost column shown fits snugly
+ with the left edge of the view.
+
+ If \a vertical is TRUE, the top row shown fits snugly with the top
+ of the view.
+
+ You can achieve the same effect automatically by setting any of the
+ \link setTableFlags() Tbl_snapTo*Grid \endlink table flags.
+*/
+
+void QtTableView::snapToGrid( bool horizontal, bool vertical )
+{
+ int newXCell = -1;
+ int newYCell = -1;
+ if ( horizontal && xCellDelta != 0 ) {
+ int w = cellW ? cellW : cellWidth( xCellOffs );
+ if ( xCellDelta >= w/2 )
+ newXCell = xCellOffs + 1;
+ else
+ newXCell = xCellOffs;
+ }
+ if ( vertical && yCellDelta != 0 ) {
+ int h = cellH ? cellH : cellHeight( yCellOffs );
+ if ( yCellDelta >= h/2 )
+ newYCell = yCellOffs + 1;
+ else
+ newYCell = yCellOffs;
+ }
+ setTopLeftCell( newYCell, newXCell ); //row,column
+}
+
+/*
+ \internal
+ This internal slot is connected to the horizontal scroll bar's
+ QScrollBar::valueChanged() signal.
+
+ Moves the table horizontally to offset \a val without updating the
+ scroll bar.
+*/
+
+void QtTableView::horSbValue( int val )
+{
+ if ( horSliding ) {
+ horSliding = FALSE;
+ if ( horSnappingOff ) {
+ horSnappingOff = FALSE;
+ tFlags |= Tbl_snapToHGrid;
+ }
+ }
+ setOffset( val, yOffs, FALSE );
+}
+
+/*
+ \internal
+ This internal slot is connected to the horizontal scroll bar's
+ QScrollBar::sliderMoved() signal.
+
+ Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set.
+*/
+
+void QtTableView::horSbSliding( int val )
+{
+ if ( testTableFlags(Tbl_snapToHGrid) &&
+ testTableFlags(Tbl_smoothHScrolling) ) {
+ tFlags &= ~Tbl_snapToHGrid; // turn off snapping while sliding
+ setOffset( val, yOffs, FALSE );
+ tFlags |= Tbl_snapToHGrid; // turn on snapping again
+ } else {
+ setOffset( val, yOffs, FALSE );
+ }
+}
+
+/*
+ \internal
+ This internal slot is connected to the horizontal scroll bar's
+ QScrollBar::sliderReleased() signal.
+*/
+
+void QtTableView::horSbSlidingDone( )
+{
+ if ( testTableFlags(Tbl_snapToHGrid) &&
+ testTableFlags(Tbl_smoothHScrolling) )
+ snapToGrid( TRUE, FALSE );
+}
+
+/*
+ \internal
+ This internal slot is connected to the vertical scroll bar's
+ QScrollBar::valueChanged() signal.
+
+ Moves the table vertically to offset \a val without updating the
+ scroll bar.
+*/
+
+void QtTableView::verSbValue( int val )
+{
+ if ( verSliding ) {
+ verSliding = FALSE;
+ if ( verSnappingOff ) {
+ verSnappingOff = FALSE;
+ tFlags |= Tbl_snapToVGrid;
+ }
+ }
+ setOffset( xOffs, val, FALSE );
+}
+
+/*
+ \internal
+ This internal slot is connected to the vertical scroll bar's
+ QScrollBar::sliderMoved() signal.
+
+ Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set.
+*/
+
+void QtTableView::verSbSliding( int val )
+{
+ if ( testTableFlags(Tbl_snapToVGrid) &&
+ testTableFlags(Tbl_smoothVScrolling) ) {
+ tFlags &= ~Tbl_snapToVGrid; // turn off snapping while sliding
+ setOffset( xOffs, val, FALSE );
+ tFlags |= Tbl_snapToVGrid; // turn on snapping again
+ } else {
+ setOffset( xOffs, val, FALSE );
+ }
+}
+
+/*
+ \internal
+ This internal slot is connected to the vertical scroll bar's
+ QScrollBar::sliderReleased() signal.
+*/
+
+void QtTableView::verSbSlidingDone( )
+{
+ if ( testTableFlags(Tbl_snapToVGrid) &&
+ testTableFlags(Tbl_smoothVScrolling) )
+ snapToGrid( FALSE, TRUE );
+}
+
+
+/*
+ This virtual function is called before painting of table cells
+ is started. It can be reimplemented by subclasses that want to
+ to set up the painter in a special way and that do not want to
+ do so for each cell.
+*/
+
+void QtTableView::setupPainter( QPainter * )
+{
+}
+
+/*
+ \fn void QtTableView::paintCell( QPainter *p, int row, int col )
+
+ This pure virtual function is called to paint the single cell at \a
+ (row,col) using \a p, which is open when paintCell() is called and
+ must remain open.
+
+ The coordinate system is \link QPainter::translate() translated \endlink
+ so that the origin is at the top-left corner of the cell to be
+ painted, i.e. \e cell coordinates. Do not scale or shear the coordinate
+ system (or if you do, restore the transformation matrix before you
+ return).
+
+ The painter is not clipped by default and for maximum efficiency. For safety,
+ call setTableFlags(Tbl_clipCellPainting) to enable clipping.
+
+ \sa paintEvent(), setTableFlags() */
+
+
+/*
+ Handles paint events, \a e, for the table view.
+
+ Calls paintCell() for the cells that needs to be repainted.
+*/
+
+void QtTableView::paintEvent( QPaintEvent *e )
+{
+ QRect updateR = e->rect(); // update rectangle
+ if ( sbDirty ) {
+ bool e = eraseInPaint;
+ updateScrollBars();
+ eraseInPaint = e;
+ }
+
+ QPainter paint( this );
+
+ if ( !contentsRect().contains( updateR, TRUE ) ) {// update frame ?
+ drawFrame( &paint );
+ if ( updateR.left() < frameWidth() ) //###
+ updateR.setLeft( frameWidth() );
+ if ( updateR.top() < frameWidth() )
+ updateR.setTop( frameWidth() );
+ }
+
+ int maxWX = maxViewX();
+ int maxWY = maxViewY();
+ if ( updateR.right() > maxWX )
+ updateR.setRight( maxWX );
+ if ( updateR.bottom() > maxWY )
+ updateR.setBottom( maxWY );
+
+ setupPainter( &paint ); // prepare for painting table
+
+ int firstRow = findRow( updateR.y() );
+ int firstCol = findCol( updateR.x() );
+ int xStart, yStart;
+ if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) {
+ paint.eraseRect( updateR ); // erase area outside cells but in view
+ return;
+ }
+ int maxX = updateR.right();
+ int maxY = updateR.bottom();
+ int row = firstRow;
+ int col;
+ int yPos = yStart;
+ int xPos = maxX+1; // in case the while() is empty
+ int nextX;
+ int nextY;
+ QRect winR = viewRect();
+ QRect cellR;
+ QRect cellUR;
+#ifndef QT_NO_TRANSFORMATIONS
+ QWMatrix matrix;
+#endif
+
+ while ( yPos <= maxY && row < nRows ) {
+ nextY = yPos + (cellH ? cellH : cellHeight( row ));
+ if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) )
+ break;
+ col = firstCol;
+ xPos = xStart;
+ while ( xPos <= maxX && col < nCols ) {
+ nextX = xPos + (cellW ? cellW : cellWidth( col ));
+ if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) )
+ break;
+
+ cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col),
+ cellH ? cellH : cellHeight(row) );
+ cellUR = cellR.intersect( updateR );
+ if ( cellUR.isValid() ) {
+ cellUpdateR = cellUR;
+ cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates
+ if ( eraseInPaint )
+ paint.eraseRect( cellUR );
+
+#ifndef QT_NO_TRANSFORMATIONS
+ matrix.translate( xPos, yPos );
+ paint.setWorldMatrix( matrix );
+ if ( testTableFlags(Tbl_clipCellPainting) ||
+ frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
+ paint.setClipRect( cellUR );
+ paintCell( &paint, row, col );
+ paint.setClipping( FALSE );
+ } else {
+ paintCell( &paint, row, col );
+ }
+ matrix.reset();
+ paint.setWorldMatrix( matrix );
+#else
+ paint.translate( xPos, yPos );
+ if ( testTableFlags(Tbl_clipCellPainting) ||
+ frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt
+ paint.setClipRect( cellUR );
+ paintCell( &paint, row, col );
+ paint.setClipping( FALSE );
+ } else {
+ paintCell( &paint, row, col );
+ }
+ paint.translate( -xPos, -yPos );
+#endif
+ }
+ col++;
+ xPos = nextX;
+ }
+ row++;
+ yPos = nextY;
+ }
+
+ // while painting we have to erase any areas in the view that
+ // are not covered by cells but are covered by the paint event
+ // rectangle these must be erased. We know that xPos is the last
+ // x pixel updated + 1 and that yPos is the last y pixel updated + 1.
+
+ // Note that this needs to be done regardless whether we do
+ // eraseInPaint or not. Reason: a subclass may implement
+ // flicker-freeness and encourage the use of repaint(FALSE).
+ // The subclass, however, cannot draw all pixels, just those
+ // inside the cells. So QtTableView is reponsible for all pixels
+ // outside the cells.
+
+ QRect viewR = viewRect();
+ const QColorGroup g = colorGroup();
+
+ if ( xPos <= maxX ) {
+ QRect r = viewR;
+ r.setLeft( xPos );
+ r.setBottom( yPos<maxY?yPos:maxY );
+ if ( inherits( "QMultiLineEdit" ) )
+ paint.fillRect( r.intersect( updateR ), g.base() );
+ else
+ paint.eraseRect( r.intersect( updateR ) );
+ }
+ if ( yPos <= maxY ) {
+ QRect r = viewR;
+ r.setTop( yPos );
+ if ( inherits( "QMultiLineEdit" ) )
+ paint.fillRect( r.intersect( updateR ), g.base() );
+ else
+ paint.eraseRect( r.intersect( updateR ) );
+ }
+}
+
+/*\reimp
+*/
+void QtTableView::resizeEvent( QResizeEvent * )
+{
+ updateScrollBars( horValue | verValue | horSteps | horGeometry | horRange |
+ verSteps | verGeometry | verRange );
+ showOrHideScrollBars();
+ updateFrameSize();
+ int maxX = QMIN( xOffs, maxXOffset() ); // ### can be slow
+ int maxY = QMIN( yOffs, maxYOffset() );
+ setOffset( maxX, maxY );
+}
+
+
+/*
+ Redraws all visible cells in the table view.
+*/
+
+void QtTableView::updateView()
+{
+ repaint( viewRect() );
+}
+
+/*
+ Returns a pointer to the vertical scroll bar mainly so you can
+ connect() to its signals. Note that the scroll bar works in pixel
+ values; use findRow() to translate to cell numbers.
+*/
+
+QScrollBar *QtTableView::verticalScrollBar() const
+{
+ QtTableView *that = (QtTableView*)this; // semantic const
+ if ( !vScrollBar ) {
+ QScrollBar *sb = new QScrollBar( QScrollBar::Vertical, that );
+#ifndef QT_NO_CURSOR
+ sb->setCursor( arrowCursor );
+#endif
+ sb->resize( sb->sizeHint() ); // height is irrelevant
+ Q_CHECK_PTR(sb);
+ sb->setTracking( FALSE );
+ sb->setFocusPolicy( NoFocus );
+ connect( sb, SIGNAL(valueChanged(int)),
+ SLOT(verSbValue(int)));
+ connect( sb, SIGNAL(sliderMoved(int)),
+ SLOT(verSbSliding(int)));
+ connect( sb, SIGNAL(sliderReleased()),
+ SLOT(verSbSlidingDone()));
+ sb->hide();
+ that->vScrollBar = sb;
+ return sb;
+ }
+ return vScrollBar;
+}
+
+/*
+ Returns a pointer to the horizontal scroll bar mainly so you can
+ connect() to its signals. Note that the scroll bar works in pixel
+ values; use findCol() to translate to cell numbers.
+*/
+
+QScrollBar *QtTableView::horizontalScrollBar() const
+{
+ QtTableView *that = (QtTableView*)this; // semantic const
+ if ( !hScrollBar ) {
+ QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that );
+#ifndef QT_NO_CURSOR
+ sb->setCursor( arrowCursor );
+#endif
+ sb->resize( sb->sizeHint() ); // width is irrelevant
+ sb->setFocusPolicy( NoFocus );
+ Q_CHECK_PTR(sb);
+ sb->setTracking( FALSE );
+ connect( sb, SIGNAL(valueChanged(int)),
+ SLOT(horSbValue(int)));
+ connect( sb, SIGNAL(sliderMoved(int)),
+ SLOT(horSbSliding(int)));
+ connect( sb, SIGNAL(sliderReleased()),
+ SLOT(horSbSlidingDone()));
+ sb->hide();
+ that->hScrollBar = sb;
+ return sb;
+ }
+ return hScrollBar;
+}
+
+/*
+ Enables or disables the horizontal scroll bar, as required by
+ setAutoUpdate() and the \link setTableFlags() table flags\endlink.
+*/
+
+void QtTableView::setHorScrollBar( bool on, bool update )
+{
+ if ( on ) {
+ tFlags |= Tbl_hScrollBar;
+ horizontalScrollBar(); // created
+ if ( update )
+ updateScrollBars( horMask | verMask );
+ else
+ sbDirty = sbDirty | (horMask | verMask);
+ if ( testTableFlags( Tbl_vScrollBar ) )
+ coverCornerSquare( TRUE );
+ if ( autoUpdate() )
+ sbDirty = sbDirty | horMask;
+ } else {
+ tFlags &= ~Tbl_hScrollBar;
+ if ( !hScrollBar )
+ return;
+ coverCornerSquare( FALSE );
+ bool hideScrollBar = autoUpdate() && hScrollBar->isVisible();
+ if ( hideScrollBar )
+ hScrollBar->hide();
+ if ( update )
+ updateScrollBars( verMask );
+ else
+ sbDirty = sbDirty | verMask;
+ if ( hideScrollBar && isVisible() )
+ repaint( hScrollBar->x(), hScrollBar->y(),
+ width() - hScrollBar->x(), hScrollBar->height() );
+ }
+ if ( update )
+ updateFrameSize();
+}
+
+
+/*
+ Enables or disables the vertical scroll bar, as required by
+ setAutoUpdate() and the \link setTableFlags() table flags\endlink.
+*/
+
+void QtTableView::setVerScrollBar( bool on, bool update )
+{
+ if ( on ) {
+ tFlags |= Tbl_vScrollBar;
+ verticalScrollBar(); // created
+ if ( update )
+ updateScrollBars( verMask | horMask );
+ else
+ sbDirty = sbDirty | (horMask | verMask);
+ if ( testTableFlags( Tbl_hScrollBar ) )
+ coverCornerSquare( TRUE );
+ if ( autoUpdate() )
+ sbDirty = sbDirty | verMask;
+ } else {
+ tFlags &= ~Tbl_vScrollBar;
+ if ( !vScrollBar )
+ return;
+ coverCornerSquare( FALSE );
+ bool hideScrollBar = autoUpdate() && vScrollBar->isVisible();
+ if ( hideScrollBar )
+ vScrollBar->hide();
+ if ( update )
+ updateScrollBars( horMask );
+ else
+ sbDirty = sbDirty | horMask;
+ if ( hideScrollBar && isVisible() )
+ repaint( vScrollBar->x(), vScrollBar->y(),
+ vScrollBar->width(), height() - vScrollBar->y() );
+ }
+ if ( update )
+ updateFrameSize();
+}
+
+
+
+
+int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY,
+ bool goOutsideView ) const
+{
+ int r = -1;
+ if ( nRows == 0 )
+ return r;
+ if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) {
+ if ( yPos < minViewY() ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "QtTableView::findRawRow: (%s) internal error: "
+ "yPos < minViewY() && goOutsideView "
+ "not supported. (%d,%d)",
+ name( "unnamed" ), yPos, yOffs );
+#endif
+ return -1;
+ }
+ if ( cellH ) { // uniform cell height
+ r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top
+ if ( cellMaxY )
+ *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1;
+ if ( cellMinY )
+ *cellMinY = r*cellH + minViewY() - yCellDelta;
+ r += yCellOffs; // absolute cell index
+ } else { // variable cell height
+ QtTableView *tw = (QtTableView *)this;
+ r = yCellOffs;
+ int h = minViewY() - yCellDelta; //##arnt3
+ int oldH = h;
+ Q_ASSERT( r < nRows );
+ while ( r < nRows ) {
+ oldH = h;
+ h += tw->cellHeight( r ); // Start of next cell
+ if ( yPos < h )
+ break;
+ r++;
+ }
+ if ( cellMaxY )
+ *cellMaxY = h - 1;
+ if ( cellMinY )
+ *cellMinY = oldH;
+ }
+ }
+ return r;
+
+}
+
+
+int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX ,
+ bool goOutsideView ) const
+{
+ int c = -1;
+ if ( nCols == 0 )
+ return c;
+ if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) {
+ if ( xPos < minViewX() ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "QtTableView::findRawCol: (%s) internal error: "
+ "xPos < minViewX() && goOutsideView "
+ "not supported. (%d,%d)",
+ name( "unnamed" ), xPos, xOffs );
+#endif
+ return -1;
+ }
+ if ( cellW ) { // uniform cell width
+ c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left
+ if ( cellMaxX )
+ *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1;
+ if ( cellMinX )
+ *cellMinX = c*cellW + minViewX() - xCellDelta;
+ c += xCellOffs; // absolute cell index
+ } else { // variable cell width
+ QtTableView *tw = (QtTableView *)this;
+ c = xCellOffs;
+ int w = minViewX() - xCellDelta; //##arnt3
+ int oldW = w;
+ Q_ASSERT( c < nCols );
+ while ( c < nCols ) {
+ oldW = w;
+ w += tw->cellWidth( c ); // Start of next cell
+ if ( xPos < w )
+ break;
+ c++;
+ }
+ if ( cellMaxX )
+ *cellMaxX = w - 1;
+ if ( cellMinX )
+ *cellMinX = oldW;
+ }
+ }
+ return c;
+}
+
+
+/*
+ Returns the index of the row at position \a yPos, where \a yPos is in
+ \e widget coordinates. Returns -1 if \a yPos is outside the valid
+ range.
+
+ \sa findCol(), rowYPos()
+*/
+
+int QtTableView::findRow( int yPos ) const
+{
+ int cellMaxY;
+ int row = findRawRow( yPos, &cellMaxY );
+ if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() )
+ row = - 1; // cell cut by bottom margin
+ if ( row >= nRows )
+ row = -1;
+ return row;
+}
+
+
+/*
+ Returns the index of the column at position \a xPos, where \a xPos is
+ in \e widget coordinates. Returns -1 if \a xPos is outside the valid
+ range.
+
+ \sa findRow(), colXPos()
+*/
+
+int QtTableView::findCol( int xPos ) const
+{
+ int cellMaxX;
+ int col = findRawCol( xPos, &cellMaxX );
+ if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() )
+ col = - 1; // cell cut by right margin
+ if ( col >= nCols )
+ col = -1;
+ return col;
+}
+
+
+/*
+ Computes the position in the widget of row \a row.
+
+ Returns TRUE and stores the result in \a *yPos (in \e widget
+ coordinates) if the row is visible. Returns FALSE and does not modify
+ \a *yPos if \a row is invisible or invalid.
+
+ \sa colXPos(), findRow()
+*/
+
+bool QtTableView::rowYPos( int row, int *yPos ) const
+{
+ int y;
+ if ( row >= yCellOffs ) {
+ if ( cellH ) {
+ int lastVisible = lastRowVisible();
+ if ( row > lastVisible || lastVisible == -1 )
+ return FALSE;
+ y = (row - yCellOffs)*cellH + minViewY() - yCellDelta;
+ } else {
+ //##arnt3
+ y = minViewY() - yCellDelta; // y of leftmost cell in view
+ int r = yCellOffs;
+ QtTableView *tw = (QtTableView *)this;
+ int maxY = maxViewY();
+ while ( r < row && y <= maxY )
+ y += tw->cellHeight( r++ );
+ if ( y > maxY )
+ return FALSE;
+
+ }
+ } else {
+ return FALSE;
+ }
+ if ( yPos )
+ *yPos = y;
+ return TRUE;
+}
+
+
+/*
+ Computes the position in the widget of column \a col.
+
+ Returns TRUE and stores the result in \a *xPos (in \e widget
+ coordinates) if the column is visible. Returns FALSE and does not
+ modify \a *xPos if \a col is invisible or invalid.
+
+ \sa rowYPos(), findCol()
+*/
+
+bool QtTableView::colXPos( int col, int *xPos ) const
+{
+ int x;
+ if ( col >= xCellOffs ) {
+ if ( cellW ) {
+ int lastVisible = lastColVisible();
+ if ( col > lastVisible || lastVisible == -1 )
+ return FALSE;
+ x = (col - xCellOffs)*cellW + minViewX() - xCellDelta;
+ } else {
+ //##arnt3
+ x = minViewX() - xCellDelta; // x of uppermost cell in view
+ int c = xCellOffs;
+ QtTableView *tw = (QtTableView *)this;
+ int maxX = maxViewX();
+ while ( c < col && x <= maxX )
+ x += tw->cellWidth( c++ );
+ if ( x > maxX )
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ if ( xPos )
+ *xPos = x;
+ return TRUE;
+}
+
+
+/*
+ Moves the visible area of the table right by \a xPixels and
+ down by \a yPixels pixels. Both may be negative.
+
+ \warning You might find that QScrollView offers a higher-level of
+ functionality than using QtTableView and this function.
+
+ This function is \e not the same as QWidget::scroll(); in particular,
+ the signs of \a xPixels and \a yPixels have the reverse semantics.
+
+ \sa setXOffset(), setYOffset(), setOffset(), setTopCell(),
+ setLeftCell()
+*/
+
+void QtTableView::scroll( int xPixels, int yPixels )
+{
+ QWidget::scroll( -xPixels, -yPixels, contentsRect() );
+}
+
+
+/*
+ Returns the leftmost pixel of the table view in \e view
+ coordinates. This excludes the frame and any header.
+
+ \sa maxViewY(), viewWidth(), contentsRect()
+*/
+
+int QtTableView::minViewX() const
+{
+ return frameWidth();
+}
+
+
+/*
+ Returns the top pixel of the table view in \e view
+ coordinates. This excludes the frame and any header.
+
+ \sa maxViewX(), viewHeight(), contentsRect()
+*/
+
+int QtTableView::minViewY() const
+{
+ return frameWidth();
+}
+
+
+/*
+ Returns the rightmost pixel of the table view in \e view
+ coordinates. This excludes the frame and any scroll bar, but
+ includes blank pixels to the right of the visible table data.
+
+ \sa maxViewY(), viewWidth(), contentsRect()
+*/
+
+int QtTableView::maxViewX() const
+{
+ return width() - 1 - frameWidth()
+ - (tFlags & Tbl_vScrollBar ? VSBEXT
+ : 0);
+}
+
+
+/*
+ Returns the bottom pixel of the table view in \e view
+ coordinates. This excludes the frame and any scroll bar, but
+ includes blank pixels below the visible table data.
+
+ \sa maxViewX(), viewHeight(), contentsRect()
+*/
+
+int QtTableView::maxViewY() const
+{
+ return height() - 1 - frameWidth()
+ - (tFlags & Tbl_hScrollBar ? HSBEXT
+ : 0);
+}
+
+
+/*
+ Returns the width of the table view, as such, in \e view
+ coordinates. This does not include any header, scroll bar or frame,
+ but it does include background pixels to the right of the table data.
+
+ \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect()
+*/
+
+int QtTableView::viewWidth() const
+{
+ return maxViewX() - minViewX() + 1;
+}
+
+
+/*
+ Returns the height of the table view, as such, in \e view
+ coordinates. This does not include any header, scroll bar or frame,
+ but it does include background pixels below the table data.
+
+ \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect()
+*/
+
+int QtTableView::viewHeight() const
+{
+ return maxViewY() - minViewY() + 1;
+}
+
+
+void QtTableView::doAutoScrollBars()
+{
+ int viewW = width() - frameWidth() - minViewX();
+ int viewH = height() - frameWidth() - minViewY();
+ bool vScrollOn = testTableFlags(Tbl_vScrollBar);
+ bool hScrollOn = testTableFlags(Tbl_hScrollBar);
+ int w = 0;
+ int h = 0;
+ int i;
+
+ if ( testTableFlags(Tbl_autoHScrollBar) ) {
+ if ( cellW ) {
+ w = cellW*nCols;
+ } else {
+ i = 0;
+ while ( i < nCols && w <= viewW )
+ w += cellWidth( i++ );
+ }
+ if ( w > viewW )
+ hScrollOn = TRUE;
+ else
+ hScrollOn = FALSE;
+ }
+
+ if ( testTableFlags(Tbl_autoVScrollBar) ) {
+ if ( cellH ) {
+ h = cellH*nRows;
+ } else {
+ i = 0;
+ while ( i < nRows && h <= viewH )
+ h += cellHeight( i++ );
+ }
+
+ if ( h > viewH )
+ vScrollOn = TRUE;
+ else
+ vScrollOn = FALSE;
+ }
+
+ if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn )
+ if ( w > viewW - VSBEXT )
+ hScrollOn = TRUE;
+
+ if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn )
+ if ( h > viewH - HSBEXT )
+ vScrollOn = TRUE;
+
+ setHorScrollBar( hScrollOn, FALSE );
+ setVerScrollBar( vScrollOn, FALSE );
+ updateFrameSize();
+}
+
+
+/*
+ \fn void QtTableView::updateScrollBars()
+
+ Updates the scroll bars' contents and presence to match the table's
+ state. Generally, you should not need to call this.
+
+ \sa setTableFlags()
+*/
+
+/*
+ Updates the scroll bars' contents and presence to match the table's
+ state \c or \a f.
+
+ \sa setTableFlags()
+*/
+
+void QtTableView::updateScrollBars( uint f )
+{
+ sbDirty = sbDirty | f;
+ if ( inSbUpdate )
+ return;
+ inSbUpdate = TRUE;
+
+ if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) ||
+ testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) )
+ // if range change and auto
+ doAutoScrollBars(); // turn scroll bars on/off if needed
+
+ if ( !autoUpdate() ) {
+ inSbUpdate = FALSE;
+ return;
+ }
+ if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) &&
+ !testTableFlags( Tbl_vScrollBar ) ) {
+ setYOffset( 0 );
+ }
+ if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) &&
+ !testTableFlags( Tbl_hScrollBar ) ) {
+ setXOffset( 0 );
+ }
+ if ( !isVisible() ) {
+ inSbUpdate = FALSE;
+ return;
+ }
+
+ if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) {
+ if ( sbDirty & horGeometry )
+ hScrollBar->setGeometry( 0,height() - HSBEXT,
+ viewWidth() + frameWidth()*2,
+ HSBEXT);
+
+ if ( sbDirty & horSteps ) {
+ if ( cellW )
+ hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() );
+ else
+ hScrollBar->setSteps( 16, viewWidth() );
+ }
+
+ if ( sbDirty & horRange )
+ hScrollBar->setRange( 0, maxXOffset() );
+
+ if ( sbDirty & horValue )
+ hScrollBar->setValue( xOffs );
+
+ // show scrollbar only when it has a sane geometry
+ if ( !hScrollBar->isVisible() )
+ hScrollBar->show();
+ }
+
+ if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) {
+ if ( sbDirty & verGeometry )
+ vScrollBar->setGeometry( width() - VSBEXT, 0,
+ VSBEXT,
+ viewHeight() + frameWidth()*2 );
+
+ if ( sbDirty & verSteps ) {
+ if ( cellH )
+ vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() );
+ else
+ vScrollBar->setSteps( 16, viewHeight() ); // fttb! ###
+ }
+
+ if ( sbDirty & verRange )
+ vScrollBar->setRange( 0, maxYOffset() );
+
+ if ( sbDirty & verValue )
+ vScrollBar->setValue( yOffs );
+
+ // show scrollbar only when it has a sane geometry
+ if ( !vScrollBar->isVisible() )
+ vScrollBar->show();
+ }
+ if ( coveringCornerSquare &&
+ ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) )
+ cornerSquare->move( maxViewX() + frameWidth() + 1,
+ maxViewY() + frameWidth() + 1 );
+
+ sbDirty = 0;
+ inSbUpdate = FALSE;
+}
+
+
+void QtTableView::updateFrameSize()
+{
+ int rw = width() - ( testTableFlags(Tbl_vScrollBar) ?
+ VSBEXT : 0 );
+ int rh = height() - ( testTableFlags(Tbl_hScrollBar) ?
+ HSBEXT : 0 );
+ if ( rw < 0 )
+ rw = 0;
+ if ( rh < 0 )
+ rh = 0;
+
+ if ( autoUpdate() ) {
+ int fh = frameRect().height();
+ int fw = frameRect().width();
+ setFrameRect( QRect(0,0,rw,rh) );
+
+ if ( rw != fw )
+ update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh );
+ if ( rh != fh )
+ update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 );
+ }
+}
+
+
+/*
+ Returns the maximum horizontal offset within the table of the
+ view's left edge in \e table coordinates.
+
+ This is used mainly to set the horizontal scroll bar's range.
+
+ \sa maxColOffset(), maxYOffset(), totalWidth()
+*/
+
+int QtTableView::maxXOffset()
+{
+ int tw = totalWidth();
+ int maxOffs;
+ if ( testTableFlags(Tbl_scrollLastHCell) ) {
+ if ( nCols != 1)
+ maxOffs = tw - ( cellW ? cellW : cellWidth( nCols - 1 ) );
+ else
+ maxOffs = tw - viewWidth();
+ } else {
+ if ( testTableFlags(Tbl_snapToHGrid) ) {
+ if ( cellW ) {
+ maxOffs = tw - (viewWidth()/cellW)*cellW;
+ } else {
+ int goal = tw - viewWidth();
+ int pos = tw;
+ int nextCol = nCols - 1;
+ int nextCellWidth = cellWidth( nextCol );
+ while( nextCol > 0 && pos > goal + nextCellWidth ) {
+ pos -= nextCellWidth;
+ nextCellWidth = cellWidth( --nextCol );
+ }
+ if ( goal + nextCellWidth == pos )
+ maxOffs = goal;
+ else if ( goal < pos )
+ maxOffs = pos;
+ else
+ maxOffs = 0;
+ }
+ } else {
+ maxOffs = tw - viewWidth();
+ }
+ }
+ return maxOffs > 0 ? maxOffs : 0;
+}
+
+
+/*
+ Returns the maximum vertical offset within the table of the
+ view's top edge in \e table coordinates.
+
+ This is used mainly to set the vertical scroll bar's range.
+
+ \sa maxRowOffset(), maxXOffset(), totalHeight()
+*/
+
+int QtTableView::maxYOffset()
+{
+ int th = totalHeight();
+ int maxOffs;
+ if ( testTableFlags(Tbl_scrollLastVCell) ) {
+ if ( nRows != 1)
+ maxOffs = th - ( cellH ? cellH : cellHeight( nRows - 1 ) );
+ else
+ maxOffs = th - viewHeight();
+ } else {
+ if ( testTableFlags(Tbl_snapToVGrid) ) {
+ if ( cellH ) {
+ maxOffs = th - (viewHeight()/cellH)*cellH;
+ } else {
+ int goal = th - viewHeight();
+ int pos = th;
+ int nextRow = nRows - 1;
+ int nextCellHeight = cellHeight( nextRow );
+ while( nextRow > 0 && pos > goal + nextCellHeight ) {
+ pos -= nextCellHeight;
+ nextCellHeight = cellHeight( --nextRow );
+ }
+ if ( goal + nextCellHeight == pos )
+ maxOffs = goal;
+ else if ( goal < pos )
+ maxOffs = pos;
+ else
+ maxOffs = 0;
+ }
+ } else {
+ maxOffs = th - viewHeight();
+ }
+ }
+ return maxOffs > 0 ? maxOffs : 0;
+}
+
+
+/*
+ Returns the index of the last column, which may be at the left edge
+ of the view.
+
+ Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag,
+ this may or may not be the last column.
+
+ \sa maxXOffset(), maxRowOffset()
+*/
+
+int QtTableView::maxColOffset()
+{
+ int mx = maxXOffset();
+ if ( cellW )
+ return mx/cellW;
+ else {
+ int xcd=0, col=0;
+ while ( col < nCols && mx > (xcd=cellWidth(col)) ) {
+ mx -= xcd;
+ col++;
+ }
+ return col;
+ }
+}
+
+
+/*
+ Returns the index of the last row, which may be at the top edge of
+ the view.
+
+ Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag,
+ this may or may not be the last row.
+
+ \sa maxYOffset(), maxColOffset()
+*/
+
+int QtTableView::maxRowOffset()
+{
+ int my = maxYOffset();
+ if ( cellH )
+ return my/cellH;
+ else {
+ int ycd=0, row=0;
+ while ( row < nRows && my > (ycd=cellHeight(row)) ) {
+ my -= ycd;
+ row++;
+ }
+ return row;
+ }
+}
+
+
+void QtTableView::showOrHideScrollBars()
+{
+ if ( !autoUpdate() )
+ return;
+ if ( vScrollBar ) {
+ if ( testTableFlags(Tbl_vScrollBar) ) {
+ if ( !vScrollBar->isVisible() )
+ sbDirty = sbDirty | verMask;
+ } else {
+ if ( vScrollBar->isVisible() )
+ vScrollBar->hide();
+ }
+ }
+ if ( hScrollBar ) {
+ if ( testTableFlags(Tbl_hScrollBar) ) {
+ if ( !hScrollBar->isVisible() )
+ sbDirty = sbDirty | horMask;
+ } else {
+ if ( hScrollBar->isVisible() )
+ hScrollBar->hide();
+ }
+ }
+ if ( cornerSquare ) {
+ if ( testTableFlags(Tbl_hScrollBar) &&
+ testTableFlags(Tbl_vScrollBar) ) {
+ if ( !cornerSquare->isVisible() )
+ cornerSquare->show();
+ } else {
+ if ( cornerSquare->isVisible() )
+ cornerSquare->hide();
+ }
+ }
+}
+
+
+/*
+ Updates the scroll bars and internal state.
+
+ Call this function when the table view's total size is changed;
+ typically because the result of cellHeight() or cellWidth() have changed.
+
+ This function does not repaint the widget.
+*/
+
+void QtTableView::updateTableSize()
+{
+ bool updateOn = autoUpdate();
+ setAutoUpdate( FALSE );
+ int xofs = xOffset();
+ xOffs++; //so that setOffset will not return immediately
+ setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly
+ setAutoUpdate(updateOn);
+
+ updateScrollBars( horSteps | horRange |
+ verSteps | verRange );
+ showOrHideScrollBars();
+}
+
+
+#endif
diff --git a/src/attic/qttableview.h b/src/attic/qttableview.h
new file mode 100644
index 0000000..a5dab15
--- /dev/null
+++ b/src/attic/qttableview.h
@@ -0,0 +1,250 @@
+/**********************************************************************
+**
+** Definition of QtTableView class
+**
+** Created : 941115
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file contains a class moved out of the Qt GUI Toolkit API. It
+** may be used, distributed and modified without limitation.
+**
+**********************************************************************/
+
+#ifndef QTTABLEVIEW_H
+#define QTTABLEVIEW_H
+
+#ifndef QT_H
+#include "qframe.h"
+#endif // QT_H
+
+#ifndef QT_NO_QTTABLEVIEW
+
+class QScrollBar;
+class QCornerSquare;
+
+
+class QtTableView : public QFrame
+{
+ Q_OBJECT
+public:
+ virtual void setBackgroundColor( const QColor & );
+ virtual void setPalette( const QPalette & );
+ void show();
+
+ void repaint( bool erase=TRUE );
+ void repaint( int x, int y, int w, int h, bool erase=TRUE );
+ void repaint( const QRect &, bool erase=TRUE );
+
+protected:
+ QtTableView( QWidget *parent=0, const char *name=0, WFlags f=0 );
+ ~QtTableView();
+
+ int numRows() const;
+ virtual void setNumRows( int );
+ int numCols() const;
+ virtual void setNumCols( int );
+
+ int topCell() const;
+ virtual void setTopCell( int row );
+ int leftCell() const;
+ virtual void setLeftCell( int col );
+ virtual void setTopLeftCell( int row, int col );
+
+ int xOffset() const;
+ virtual void setXOffset( int );
+ int yOffset() const;
+ virtual void setYOffset( int );
+ virtual void setOffset( int x, int y, bool updateScrBars = TRUE );
+
+ virtual int cellWidth( int col );
+ virtual int cellHeight( int row );
+ int cellWidth() const;
+ int cellHeight() const;
+ virtual void setCellWidth( int );
+ virtual void setCellHeight( int );
+
+ virtual int totalWidth();
+ virtual int totalHeight();
+
+ uint tableFlags() const;
+ bool testTableFlags( uint f ) const;
+ virtual void setTableFlags( uint f );
+ void clearTableFlags( uint f = ~0 );
+
+ bool autoUpdate() const;
+ virtual void setAutoUpdate( bool );
+
+ void updateCell( int row, int column, bool erase=TRUE );
+
+ QRect cellUpdateRect() const;
+ QRect viewRect() const;
+
+ int lastRowVisible() const;
+ int lastColVisible() const;
+
+ bool rowIsVisible( int row ) const;
+ bool colIsVisible( int col ) const;
+
+ QScrollBar *verticalScrollBar() const;
+ QScrollBar *horizontalScrollBar() const;
+
+private slots:
+ void horSbValue( int );
+ void horSbSliding( int );
+ void horSbSlidingDone();
+ void verSbValue( int );
+ void verSbSliding( int );
+ void verSbSlidingDone();
+
+protected:
+ virtual void paintCell( QPainter *, int row, int col ) = 0;
+ virtual void setupPainter( QPainter * );
+
+ void paintEvent( QPaintEvent * );
+ void resizeEvent( QResizeEvent * );
+
+ int findRow( int yPos ) const;
+ int findCol( int xPos ) const;
+
+ bool rowYPos( int row, int *yPos ) const;
+ bool colXPos( int col, int *xPos ) const;
+
+ int maxXOffset();
+ int maxYOffset();
+ int maxColOffset();
+ int maxRowOffset();
+
+ int minViewX() const;
+ int minViewY() const;
+ int maxViewX() const;
+ int maxViewY() const;
+ int viewWidth() const;
+ int viewHeight() const;
+
+ void scroll( int xPixels, int yPixels );
+ void updateScrollBars();
+ void updateTableSize();
+
+private:
+ void coverCornerSquare( bool );
+ void snapToGrid( bool horizontal, bool vertical );
+ virtual void setHorScrollBar( bool on, bool update = TRUE );
+ virtual void setVerScrollBar( bool on, bool update = TRUE );
+ void updateView();
+ int findRawRow( int yPos, int *cellMaxY, int *cellMinY = 0,
+ bool goOutsideView = FALSE ) const;
+ int findRawCol( int xPos, int *cellMaxX, int *cellMinX = 0,
+ bool goOutsideView = FALSE ) const;
+ int maxColsVisible() const;
+
+ void updateScrollBars( uint );
+ void updateFrameSize();
+
+ void doAutoScrollBars();
+ void showOrHideScrollBars();
+
+ int nRows;
+ int nCols;
+ int xOffs, yOffs;
+ int xCellOffs, yCellOffs;
+ short xCellDelta, yCellDelta;
+ short cellH, cellW;
+
+ uint eraseInPaint : 1;
+ uint verSliding : 1;
+ uint verSnappingOff : 1;
+ uint horSliding : 1;
+ uint horSnappingOff : 1;
+ uint coveringCornerSquare : 1;
+ uint sbDirty : 8;
+ uint inSbUpdate : 1;
+
+ uint tFlags;
+ QRect cellUpdateR;
+
+ QScrollBar *vScrollBar;
+ QScrollBar *hScrollBar;
+ QCornerSquare *cornerSquare;
+
+private: // Disabled copy constructor and operator=
+#if defined(Q_DISABLE_COPY)
+ QtTableView( const QtTableView & );
+ QtTableView &operator=( const QtTableView & );
+#endif
+};
+
+
+const uint Tbl_vScrollBar = 0x00000001;
+const uint Tbl_hScrollBar = 0x00000002;
+const uint Tbl_autoVScrollBar = 0x00000004;
+const uint Tbl_autoHScrollBar = 0x00000008;
+const uint Tbl_autoScrollBars = 0x0000000C;
+
+const uint Tbl_clipCellPainting = 0x00000100;
+const uint Tbl_cutCellsV = 0x00000200;
+const uint Tbl_cutCellsH = 0x00000400;
+const uint Tbl_cutCells = 0x00000600;
+
+const uint Tbl_scrollLastHCell = 0x00000800;
+const uint Tbl_scrollLastVCell = 0x00001000;
+const uint Tbl_scrollLastCell = 0x00001800;
+
+const uint Tbl_smoothHScrolling = 0x00002000;
+const uint Tbl_smoothVScrolling = 0x00004000;
+const uint Tbl_smoothScrolling = 0x00006000;
+
+const uint Tbl_snapToHGrid = 0x00008000;
+const uint Tbl_snapToVGrid = 0x00010000;
+const uint Tbl_snapToGrid = 0x00018000;
+
+
+inline int QtTableView::numRows() const
+{ return nRows; }
+
+inline int QtTableView::numCols() const
+{ return nCols; }
+
+inline int QtTableView::topCell() const
+{ return yCellOffs; }
+
+inline int QtTableView::leftCell() const
+{ return xCellOffs; }
+
+inline int QtTableView::xOffset() const
+{ return xOffs; }
+
+inline int QtTableView::yOffset() const
+{ return yOffs; }
+
+inline int QtTableView::cellHeight() const
+{ return cellH; }
+
+inline int QtTableView::cellWidth() const
+{ return cellW; }
+
+inline uint QtTableView::tableFlags() const
+{ return tFlags; }
+
+inline bool QtTableView::testTableFlags( uint f ) const
+{ return (tFlags & f) != 0; }
+
+inline QRect QtTableView::cellUpdateRect() const
+{ return cellUpdateR; }
+
+inline bool QtTableView::autoUpdate() const
+{ return isUpdatesEnabled(); }
+
+inline void QtTableView::repaint( bool erase )
+{ repaint( 0, 0, width(), height(), erase ); }
+
+inline void QtTableView::repaint( const QRect &r, bool erase )
+{ repaint( r.x(), r.y(), r.width(), r.height(), erase ); }
+
+inline void QtTableView::updateScrollBars()
+{ updateScrollBars( 0 ); }
+
+
+#endif // QT_NO_QTTABLEVIEW
+
+#endif // QTTABLEVIEW_H