| 1 | /****************************************************************************
 | 
|---|
| 2 | **
 | 
|---|
| 3 | ** Implementation of QTable widget class
 | 
|---|
| 4 | **
 | 
|---|
| 5 | ** Created : 000607
 | 
|---|
| 6 | **
 | 
|---|
| 7 | ** Copyright (C) 1992-2002 Trolltech AS.  All rights reserved.
 | 
|---|
| 8 | **
 | 
|---|
| 9 | ** This file is part of the table module of the Qt GUI Toolkit.
 | 
|---|
| 10 | **
 | 
|---|
| 11 | ** This file may be distributed under the terms of the Q Public License
 | 
|---|
| 12 | ** as defined by Trolltech AS of Norway and appearing in the file
 | 
|---|
| 13 | ** LICENSE.QPL included in the packaging of this file.
 | 
|---|
| 14 | **
 | 
|---|
| 15 | ** This file may be distributed and/or modified under the terms of the
 | 
|---|
| 16 | ** GNU General Public License version 2 as published by the Free Software
 | 
|---|
| 17 | ** Foundation and appearing in the file LICENSE.GPL included in the
 | 
|---|
| 18 | ** packaging of this file.
 | 
|---|
| 19 | **
 | 
|---|
| 20 | ** Licensees holding valid Qt Enterprise Edition licenses may use this
 | 
|---|
| 21 | ** file in accordance with the Qt Commercial License Agreement provided
 | 
|---|
| 22 | ** with the Software.
 | 
|---|
| 23 | **
 | 
|---|
| 24 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 | 
|---|
| 25 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 | 
|---|
| 26 | **
 | 
|---|
| 27 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 | 
|---|
| 28 | **   information about Qt Commercial License Agreements.
 | 
|---|
| 29 | ** See http://www.trolltech.com/qpl/ for QPL licensing information.
 | 
|---|
| 30 | ** See http://www.trolltech.com/gpl/ for GPL licensing information.
 | 
|---|
| 31 | **
 | 
|---|
| 32 | ** Contact info@trolltech.com if any conditions of this licensing are
 | 
|---|
| 33 | ** not clear to you.
 | 
|---|
| 34 | **
 | 
|---|
| 35 | **********************************************************************/
 | 
|---|
| 36 | 
 | 
|---|
| 37 | #include "qglobal.h"
 | 
|---|
| 38 | #if defined(Q_CC_BOR)
 | 
|---|
| 39 | // needed for qsort() because of a std namespace problem on Borland
 | 
|---|
| 40 | #include "qplatformdefs.h"
 | 
|---|
| 41 | #endif
 | 
|---|
| 42 | 
 | 
|---|
| 43 | #include "qtable.h"
 | 
|---|
| 44 | 
 | 
|---|
| 45 | #ifndef QT_NO_TABLE
 | 
|---|
| 46 | 
 | 
|---|
| 47 | #include <qpainter.h>
 | 
|---|
| 48 | #include <qlineedit.h>
 | 
|---|
| 49 | #include <qcursor.h>
 | 
|---|
| 50 | #include <qapplication.h>
 | 
|---|
| 51 | #include <qtimer.h>
 | 
|---|
| 52 | #include <qobjectlist.h>
 | 
|---|
| 53 | #include <qiconset.h>
 | 
|---|
| 54 | #include <qcombobox.h>
 | 
|---|
| 55 | #include <qcheckbox.h>
 | 
|---|
| 56 | #include <qdragobject.h>
 | 
|---|
| 57 | #include <qevent.h>
 | 
|---|
| 58 | #include <qlistbox.h>
 | 
|---|
| 59 | #include <qstyle.h>
 | 
|---|
| 60 | #include <qdatatable.h>
 | 
|---|
| 61 | #include <qvalidator.h>
 | 
|---|
| 62 | 
 | 
|---|
| 63 | #include <stdlib.h>
 | 
|---|
| 64 | #include <limits.h>
 | 
|---|
| 65 | 
 | 
|---|
| 66 | static bool qt_update_cell_widget = TRUE;
 | 
|---|
| 67 | static bool qt_table_clipper_enabled = TRUE;
 | 
|---|
| 68 | #ifndef QT_INTERNAL_TABLE
 | 
|---|
| 69 | Q_EXPORT
 | 
|---|
| 70 | #endif
 | 
|---|
| 71 | void qt_set_table_clipper_enabled( bool enabled )
 | 
|---|
| 72 | {
 | 
|---|
| 73 |     qt_table_clipper_enabled = enabled;
 | 
|---|
| 74 | }
 | 
|---|
| 75 | 
 | 
|---|
| 76 | class QM_EXPORT_TABLE QTableHeader : public QHeader
 | 
|---|
| 77 | {
 | 
|---|
| 78 |     friend class QTable;
 | 
|---|
| 79 |     Q_OBJECT
 | 
|---|
| 80 | 
 | 
|---|
| 81 | public:
 | 
|---|
| 82 |     enum SectionState {
 | 
|---|
| 83 |         Normal,
 | 
|---|
| 84 |         Bold,
 | 
|---|
| 85 |         Selected
 | 
|---|
| 86 |     };
 | 
|---|
| 87 | 
 | 
|---|
| 88 |     QTableHeader( int, QTable *t, QWidget* parent=0, const char* name=0 );
 | 
|---|
| 89 |     ~QTableHeader() {};
 | 
|---|
| 90 |     void addLabel( const QString &s, int size );
 | 
|---|
| 91 |     void setLabel( int section, const QString & s, int size = -1 );
 | 
|---|
| 92 |     void setLabel( int section, const QIconSet & iconset, const QString & s,
 | 
|---|
| 93 |                    int size = -1 );
 | 
|---|
| 94 | 
 | 
|---|
| 95 |     void setLabels(const QStringList & labels);
 | 
|---|
| 96 | 
 | 
|---|
| 97 |     void removeLabel( int section );
 | 
|---|
| 98 | 
 | 
|---|
| 99 |     void setSectionState( int s, SectionState state );
 | 
|---|
| 100 |     void setSectionStateToAll( SectionState state );
 | 
|---|
| 101 |     SectionState sectionState( int s ) const;
 | 
|---|
| 102 | 
 | 
|---|
| 103 |     int sectionSize( int section ) const;
 | 
|---|
| 104 |     int sectionPos( int section ) const;
 | 
|---|
| 105 |     int sectionAt( int section ) const;
 | 
|---|
| 106 | 
 | 
|---|
| 107 |     void setSectionStretchable( int s, bool b );
 | 
|---|
| 108 |     bool isSectionStretchable( int s ) const;
 | 
|---|
| 109 | 
 | 
|---|
| 110 |     void updateCache();
 | 
|---|
| 111 | 
 | 
|---|
| 112 | signals:
 | 
|---|
| 113 |     void sectionSizeChanged( int s );
 | 
|---|
| 114 | 
 | 
|---|
| 115 | protected:
 | 
|---|
| 116 |     void paintEvent( QPaintEvent *e );
 | 
|---|
| 117 |     void paintSection( QPainter *p, int index, const QRect& fr );
 | 
|---|
| 118 |     void mousePressEvent( QMouseEvent *e );
 | 
|---|
| 119 |     void mouseMoveEvent( QMouseEvent *e );
 | 
|---|
| 120 |     void mouseReleaseEvent( QMouseEvent *e );
 | 
|---|
| 121 |     void mouseDoubleClickEvent( QMouseEvent *e );
 | 
|---|
| 122 |     void resizeEvent( QResizeEvent *e );
 | 
|---|
| 123 | 
 | 
|---|
| 124 | private slots:
 | 
|---|
| 125 |     void doAutoScroll();
 | 
|---|
| 126 |     void sectionWidthChanged( int col, int os, int ns );
 | 
|---|
| 127 |     void indexChanged( int sec, int oldIdx, int newIdx );
 | 
|---|
| 128 |     void updateStretches();
 | 
|---|
| 129 |     void updateWidgetStretches();
 | 
|---|
| 130 | 
 | 
|---|
| 131 | private:
 | 
|---|
| 132 |     void updateSelections();
 | 
|---|
| 133 |     void saveStates();
 | 
|---|
| 134 |     void setCaching( bool b );
 | 
|---|
| 135 |     void swapSections( int oldIdx, int newIdx, bool swapTable = TRUE );
 | 
|---|
| 136 |     bool doSelection( QMouseEvent *e );
 | 
|---|
| 137 |     void sectionLabelChanged( int section );
 | 
|---|
| 138 |     void resizeArrays( int n );
 | 
|---|
| 139 | 
 | 
|---|
| 140 | private:
 | 
|---|
| 141 |     QMemArray<int> states, oldStates;
 | 
|---|
| 142 |     QMemArray<bool> stretchable;
 | 
|---|
| 143 |     QMemArray<int> sectionSizes, sectionPoses;
 | 
|---|
| 144 |     bool mousePressed;
 | 
|---|
| 145 |     int pressPos, startPos, endPos;
 | 
|---|
| 146 |     QTable *table;
 | 
|---|
| 147 |     QTimer *autoScrollTimer;
 | 
|---|
| 148 |     QWidget *line1, *line2;
 | 
|---|
| 149 |     bool caching;
 | 
|---|
| 150 |     int resizedSection;
 | 
|---|
| 151 |     bool isResizing;
 | 
|---|
| 152 |     int numStretches;
 | 
|---|
| 153 |     QTimer *stretchTimer, *widgetStretchTimer;
 | 
|---|
| 154 |     QTableHeaderPrivate *d;
 | 
|---|
| 155 | 
 | 
|---|
| 156 | };
 | 
|---|
| 157 | 
 | 
|---|
| 158 | #ifdef _WS_QWS_
 | 
|---|
| 159 | # define NO_LINE_WIDGET
 | 
|---|
| 160 | #endif
 | 
|---|
| 161 | 
 | 
|---|
| 162 | 
 | 
|---|
| 163 | 
 | 
|---|
| 164 | struct QTablePrivate
 | 
|---|
| 165 | {
 | 
|---|
| 166 |     QTablePrivate() : hasRowSpan( FALSE ), hasColSpan( FALSE ),
 | 
|---|
| 167 |                       inMenuMode( FALSE ), redirectMouseEvent( FALSE )
 | 
|---|
| 168 |     {
 | 
|---|
| 169 |         hiddenRows.setAutoDelete( TRUE );
 | 
|---|
| 170 |         hiddenCols.setAutoDelete( TRUE );
 | 
|---|
| 171 |     }
 | 
|---|
| 172 |     uint hasRowSpan : 1;
 | 
|---|
| 173 |     uint hasColSpan : 1;
 | 
|---|
| 174 |     uint inMenuMode : 1;
 | 
|---|
| 175 |     uint redirectMouseEvent : 1;
 | 
|---|
| 176 |     QIntDict<int> hiddenRows, hiddenCols;
 | 
|---|
| 177 |     QTimer *geomTimer;
 | 
|---|
| 178 |     int lastVisRow;
 | 
|---|
| 179 |     int lastVisCol;
 | 
|---|
| 180 | };
 | 
|---|
| 181 | 
 | 
|---|
| 182 | struct QTableHeaderPrivate
 | 
|---|
| 183 | {
 | 
|---|
| 184 | #ifdef NO_LINE_WIDGET
 | 
|---|
| 185 |     int oldLinePos;
 | 
|---|
| 186 | #endif
 | 
|---|
| 187 | };
 | 
|---|
| 188 | 
 | 
|---|
| 189 | static bool isRowSelection( QTable::SelectionMode selMode )
 | 
|---|
| 190 | {
 | 
|---|
| 191 |     return selMode == QTable::SingleRow || selMode == QTable::MultiRow;
 | 
|---|
| 192 | }
 | 
|---|
| 193 | 
 | 
|---|
| 194 | /*!
 | 
|---|
| 195 |     \class QTableSelection
 | 
|---|
| 196 |     \brief The QTableSelection class provides access to a selected area in a
 | 
|---|
| 197 |     QTable.
 | 
|---|
| 198 | \if defined(commercial)
 | 
|---|
| 199 |     It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
 | 
|---|
| 200 | \endif
 | 
|---|
| 201 | 
 | 
|---|
| 202 |     \ingroup advanced
 | 
|---|
| 203 |     \module table
 | 
|---|
| 204 | 
 | 
|---|
| 205 |     The selection is a rectangular set of cells in a QTable. One of
 | 
|---|
| 206 |     the rectangle's cells is called the anchor cell; this is the cell
 | 
|---|
| 207 |     that was selected first. The init() function sets the anchor and
 | 
|---|
| 208 |     the selection rectangle to exactly this cell; the expandTo()
 | 
|---|
| 209 |     function expands the selection rectangle to include additional
 | 
|---|
| 210 |     cells.
 | 
|---|
| 211 | 
 | 
|---|
| 212 |     There are various access functions to find out about the area:
 | 
|---|
| 213 |     anchorRow() and anchorCol() return the anchor's position;
 | 
|---|
| 214 |     leftCol(), rightCol(), topRow() and bottomRow() return the
 | 
|---|
| 215 |     rectangle's four edges. All four are part of the selection.
 | 
|---|
| 216 | 
 | 
|---|
| 217 |     A newly created QTableSelection is inactive -- isActive() returns
 | 
|---|
| 218 |     FALSE. You must use init() and expandTo() to activate it.
 | 
|---|
| 219 | 
 | 
|---|
| 220 |     \sa QTable QTable::addSelection() QTable::selection()
 | 
|---|
| 221 |     QTable::selectCells() QTable::selectRow() QTable::selectColumn()
 | 
|---|
| 222 | */
 | 
|---|
| 223 | 
 | 
|---|
| 224 | /*!
 | 
|---|
| 225 |     Creates an inactive selection. Use init() and expandTo() to
 | 
|---|
| 226 |     activate it.
 | 
|---|
| 227 | */
 | 
|---|
| 228 | 
 | 
|---|
| 229 | QTableSelection::QTableSelection()
 | 
|---|
| 230 |     : active( FALSE ), inited( FALSE ), tRow( -1 ), lCol( -1 ),
 | 
|---|
| 231 |       bRow( -1 ), rCol( -1 ), aRow( -1 ), aCol( -1 )
 | 
|---|
| 232 | {
 | 
|---|
| 233 | }
 | 
|---|
| 234 | 
 | 
|---|
| 235 | /*!
 | 
|---|
| 236 |     Creates an active selection, starting at \a start_row and \a
 | 
|---|
| 237 |     start_col, ending at \a end_row and \a end_col.
 | 
|---|
| 238 | */
 | 
|---|
| 239 | 
 | 
|---|
| 240 | QTableSelection::QTableSelection( int start_row, int start_col, int end_row, int end_col )
 | 
|---|
| 241 |     : active( FALSE ), inited( FALSE ), tRow( -1 ), lCol( -1 ),
 | 
|---|
| 242 |       bRow( -1 ), rCol( -1 ), aRow( -1 ), aCol( -1 )
 | 
|---|
| 243 | {
 | 
|---|
| 244 |     init( start_row, start_col );
 | 
|---|
| 245 |     expandTo( end_row, end_col );
 | 
|---|
| 246 | }
 | 
|---|
| 247 | 
 | 
|---|
| 248 | /*!
 | 
|---|
| 249 |     Sets the selection anchor to cell \a row, \a col and the selection
 | 
|---|
| 250 |     to only contain this cell. The selection is not active until
 | 
|---|
| 251 |     expandTo() is called.
 | 
|---|
| 252 | 
 | 
|---|
| 253 |     To extend the selection to include additional cells, call
 | 
|---|
| 254 |     expandTo().
 | 
|---|
| 255 | 
 | 
|---|
| 256 |     \sa isActive()
 | 
|---|
| 257 | */
 | 
|---|
| 258 | 
 | 
|---|
| 259 | void QTableSelection::init( int row, int col )
 | 
|---|
| 260 | {
 | 
|---|
| 261 |     aCol = lCol = rCol = col;
 | 
|---|
| 262 |     aRow = tRow = bRow = row;
 | 
|---|
| 263 |     active = FALSE;
 | 
|---|
| 264 |     inited = TRUE;
 | 
|---|
| 265 | }
 | 
|---|
| 266 | 
 | 
|---|
| 267 | /*!
 | 
|---|
| 268 |     Expands the selection to include cell \a row, \a col. The new
 | 
|---|
| 269 |     selection rectangle is the bounding rectangle of \a row, \a col
 | 
|---|
| 270 |     and the previous selection rectangle. After calling this function
 | 
|---|
| 271 |     the selection is active.
 | 
|---|
| 272 | 
 | 
|---|
| 273 |     If you haven't called init(), this function does nothing.
 | 
|---|
| 274 | 
 | 
|---|
| 275 |     \sa init() isActive()
 | 
|---|
| 276 | */
 | 
|---|
| 277 | 
 | 
|---|
| 278 | void QTableSelection::expandTo( int row, int col )
 | 
|---|
| 279 | {
 | 
|---|
| 280 |     if ( !inited )
 | 
|---|
| 281 |         return;
 | 
|---|
| 282 |     active = TRUE;
 | 
|---|
| 283 | 
 | 
|---|
| 284 |     if ( row < aRow ) {
 | 
|---|
| 285 |         tRow = row;
 | 
|---|
| 286 |         bRow = aRow;
 | 
|---|
| 287 |     } else {
 | 
|---|
| 288 |         tRow = aRow;
 | 
|---|
| 289 |         bRow = row;
 | 
|---|
| 290 |     }
 | 
|---|
| 291 | 
 | 
|---|
| 292 |     if ( col < aCol ) {
 | 
|---|
| 293 |         lCol = col;
 | 
|---|
| 294 |         rCol = aCol;
 | 
|---|
| 295 |     } else {
 | 
|---|
| 296 |         lCol = aCol;
 | 
|---|
| 297 |         rCol = col;
 | 
|---|
| 298 |     }
 | 
|---|
| 299 | }
 | 
|---|
| 300 | 
 | 
|---|
| 301 | /*!
 | 
|---|
| 302 |     Returns TRUE if \a s includes the same cells as the selection;
 | 
|---|
| 303 |     otherwise returns FALSE.
 | 
|---|
| 304 | */
 | 
|---|
| 305 | 
 | 
|---|
| 306 | bool QTableSelection::operator==( const QTableSelection &s ) const
 | 
|---|
| 307 | {
 | 
|---|
| 308 |     return ( s.active == active &&
 | 
|---|
| 309 |              s.tRow == tRow && s.bRow == bRow &&
 | 
|---|
| 310 |              s.lCol == lCol && s.rCol == rCol );
 | 
|---|
| 311 | }
 | 
|---|
| 312 | 
 | 
|---|
| 313 | /*!
 | 
|---|
| 314 |     \fn bool QTableSelection::operator!=( const QTableSelection &s ) const
 | 
|---|
| 315 | 
 | 
|---|
| 316 |     Returns TRUE if \a s does not include the same cells as the
 | 
|---|
| 317 |     selection; otherwise returns FALSE.
 | 
|---|
| 318 | */
 | 
|---|
| 319 | 
 | 
|---|
| 320 | 
 | 
|---|
| 321 | /*!
 | 
|---|
| 322 |     \fn int QTableSelection::topRow() const
 | 
|---|
| 323 | 
 | 
|---|
| 324 |     Returns the top row of the selection.
 | 
|---|
| 325 | 
 | 
|---|
| 326 |     \sa bottomRow() leftCol() rightCol()
 | 
|---|
| 327 | */
 | 
|---|
| 328 | 
 | 
|---|
| 329 | /*!
 | 
|---|
| 330 |     \fn int QTableSelection::bottomRow() const
 | 
|---|
| 331 | 
 | 
|---|
| 332 |     Returns the bottom row of the selection.
 | 
|---|
| 333 | 
 | 
|---|
| 334 |     \sa topRow() leftCol() rightCol()
 | 
|---|
| 335 | */
 | 
|---|
| 336 | 
 | 
|---|
| 337 | /*!
 | 
|---|
| 338 |     \fn int QTableSelection::leftCol() const
 | 
|---|
| 339 | 
 | 
|---|
| 340 |     Returns the left column of the selection.
 | 
|---|
| 341 | 
 | 
|---|
| 342 |     \sa topRow() bottomRow() rightCol()
 | 
|---|
| 343 | */
 | 
|---|
| 344 | 
 | 
|---|
| 345 | /*!
 | 
|---|
| 346 |     \fn int QTableSelection::rightCol() const
 | 
|---|
| 347 | 
 | 
|---|
| 348 |     Returns the right column of the selection.
 | 
|---|
| 349 | 
 | 
|---|
| 350 |     \sa topRow() bottomRow() leftCol()
 | 
|---|
| 351 | */
 | 
|---|
| 352 | 
 | 
|---|
| 353 | /*!
 | 
|---|
| 354 |     \fn int QTableSelection::anchorRow() const
 | 
|---|
| 355 | 
 | 
|---|
| 356 |     Returns the anchor row of the selection.
 | 
|---|
| 357 | 
 | 
|---|
| 358 |     \sa anchorCol() expandTo()
 | 
|---|
| 359 | */
 | 
|---|
| 360 | 
 | 
|---|
| 361 | /*!
 | 
|---|
| 362 |     \fn int QTableSelection::anchorCol() const
 | 
|---|
| 363 | 
 | 
|---|
| 364 |     Returns the anchor column of the selection.
 | 
|---|
| 365 | 
 | 
|---|
| 366 |     \sa anchorRow() expandTo()
 | 
|---|
| 367 | */
 | 
|---|
| 368 | 
 | 
|---|
| 369 | /*!
 | 
|---|
| 370 |     \fn int QTableSelection::numRows() const
 | 
|---|
| 371 | 
 | 
|---|
| 372 |     Returns the number of rows in the selection.
 | 
|---|
| 373 | 
 | 
|---|
| 374 |     \sa numCols()
 | 
|---|
| 375 | */
 | 
|---|
| 376 | int QTableSelection::numRows() const
 | 
|---|
| 377 | {
 | 
|---|
| 378 |     return ( tRow < 0 ) ? 0 : bRow - tRow + 1;
 | 
|---|
| 379 | }
 | 
|---|
| 380 | 
 | 
|---|
| 381 | /*!
 | 
|---|
| 382 |     Returns the number of columns in the selection.
 | 
|---|
| 383 | 
 | 
|---|
| 384 |     \sa numRows()
 | 
|---|
| 385 | */
 | 
|---|
| 386 | int QTableSelection::numCols() const
 | 
|---|
| 387 | {
 | 
|---|
| 388 |     return ( lCol < 0 ) ? 0 : rCol - lCol + 1;
 | 
|---|
| 389 | }
 | 
|---|
| 390 | 
 | 
|---|
| 391 | /*!
 | 
|---|
| 392 |     \fn bool QTableSelection::isActive() const
 | 
|---|
| 393 | 
 | 
|---|
| 394 |     Returns whether the selection is active or not. A selection is
 | 
|---|
| 395 |     active after init() \e and expandTo() have been called.
 | 
|---|
| 396 | */
 | 
|---|
| 397 | 
 | 
|---|
| 398 | /*!
 | 
|---|
| 399 |     \fn bool QTableSelection::isEmpty() const
 | 
|---|
| 400 | 
 | 
|---|
| 401 |     Returns whether the selection is empty or not.
 | 
|---|
| 402 | 
 | 
|---|
| 403 |     \sa numRows(), numCols()
 | 
|---|
| 404 | */
 | 
|---|
| 405 | 
 | 
|---|
| 406 | /*!
 | 
|---|
| 407 |     \class QTableItem
 | 
|---|
| 408 |     \brief The QTableItem class provides the cell content for QTable cells.
 | 
|---|
| 409 | \if defined(commercial)
 | 
|---|
| 410 |     It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
 | 
|---|
| 411 | \endif
 | 
|---|
| 412 | 
 | 
|---|
| 413 |     \ingroup advanced
 | 
|---|
| 414 |     \module table
 | 
|---|
| 415 | 
 | 
|---|
| 416 |     For many applications QTableItems are ideal for presenting and
 | 
|---|
| 417 |     editing the contents of QTable cells. In situations where you need
 | 
|---|
| 418 |     to create very large tables you may prefer an alternative approach
 | 
|---|
| 419 |     to using QTableItems: see the notes on large tables.
 | 
|---|
| 420 | 
 | 
|---|
| 421 |     A QTableItem contains a cell's data, by default, a string and a
 | 
|---|
| 422 |     pixmap. The table item also holds the cell's display size and how
 | 
|---|
| 423 |     the data should be aligned. The table item specifies the cell's
 | 
|---|
| 424 |     \l EditType and the editor used for in-place editing (by default a
 | 
|---|
| 425 |     QLineEdit). If you want checkboxes use \l{QCheckTableItem}, and if
 | 
|---|
| 426 |     you want comboboxes use \l{QComboTableItem}. The \l EditType (set
 | 
|---|
| 427 |     in the constructor) determines whether the cell's contents may be
 | 
|---|
| 428 |     edited; setReplaceable() sets whether the cell's contents may be
 | 
|---|
| 429 |     replaced by another cell's contents.
 | 
|---|
| 430 | 
 | 
|---|
| 431 |     If a pixmap is specified it is displayed to the left of any text.
 | 
|---|
| 432 |     You can change the text or pixmap with setText() and setPixmap()
 | 
|---|
| 433 |     respectively. For text you can use setWordWrap().
 | 
|---|
| 434 | 
 | 
|---|
| 435 |     Reimplement createEditor() and setContentFromEditor() if you want
 | 
|---|
| 436 |     to use your own widget instead of a QLineEdit for editing cell
 | 
|---|
| 437 |     contents. Reimplement paint() if you want to display custom
 | 
|---|
| 438 |     content. If you want a checkbox table item use QCheckTableItem,
 | 
|---|
| 439 |     and if you want a combo table item use \l{QComboTableItem}.
 | 
|---|
| 440 | 
 | 
|---|
| 441 |     When sorting table items the key() function is used; by default
 | 
|---|
| 442 |     this returns the table item's text(). Reimplement key() to
 | 
|---|
| 443 |     customize how your table items will sort.
 | 
|---|
| 444 | 
 | 
|---|
| 445 |     Table items are inserted into a table using QTable::setItem(). If
 | 
|---|
| 446 |     you insert an item into a cell that already contains a table item
 | 
|---|
| 447 |     the original item will be deleted.
 | 
|---|
| 448 | 
 | 
|---|
| 449 |     Example:
 | 
|---|
| 450 |     \code
 | 
|---|
| 451 |     for ( int row = 0; row < table->numRows(); row++ ) {
 | 
|---|
| 452 |         for ( int col = 0; col < table->numCols(); col++ ) {
 | 
|---|
| 453 |             table->setItem( row, col,
 | 
|---|
| 454 |                 new QTableItem( table, QTableItem::WhenCurrent, QString::number( row * col ) ) );
 | 
|---|
| 455 |         }
 | 
|---|
| 456 |     }
 | 
|---|
| 457 |     \endcode
 | 
|---|
| 458 | 
 | 
|---|
| 459 |     You can move a table item from one cell to another, in the same or
 | 
|---|
| 460 |     a different table, using QTable::takeItem() and QTable::setItem()
 | 
|---|
| 461 |     but see also QTable::swapCells().
 | 
|---|
| 462 | 
 | 
|---|
| 463 |     Table items can be deleted with delete in the standard way; the
 | 
|---|
| 464 |     table and cell will be updated accordingly.
 | 
|---|
| 465 | 
 | 
|---|
| 466 |     Note, that if you have a table item that is not currently in a table
 | 
|---|
| 467 |     then anything you do to that item other than insert it into a table
 | 
|---|
| 468 |     will result in undefined behaviour.
 | 
|---|
| 469 | 
 | 
|---|
| 470 |     \img qtableitems.png Table Items
 | 
|---|
| 471 | 
 | 
|---|
| 472 |     \sa QCheckTableItem QComboTableItem
 | 
|---|
| 473 | 
 | 
|---|
| 474 | */
 | 
|---|
| 475 | 
 | 
|---|
| 476 | /*!
 | 
|---|
| 477 |     \fn QTable *QTableItem::table() const
 | 
|---|
| 478 | 
 | 
|---|
| 479 |     Returns the QTable the table item belongs to.
 | 
|---|
| 480 | 
 | 
|---|
| 481 |     \sa QTable::setItem() QTableItem()
 | 
|---|
| 482 | */
 | 
|---|
| 483 | 
 | 
|---|
| 484 | /*!
 | 
|---|
| 485 |     \enum QTableItem::EditType
 | 
|---|
| 486 | 
 | 
|---|
| 487 |     \target wheneditable
 | 
|---|
| 488 |     This enum is used to define whether a cell is editable or
 | 
|---|
| 489 |     read-only (in conjunction with other settings), and how the cell
 | 
|---|
| 490 |     should be displayed.
 | 
|---|
| 491 | 
 | 
|---|
| 492 |     \value Always
 | 
|---|
| 493 |     The cell always \e looks editable.
 | 
|---|
| 494 | 
 | 
|---|
| 495 |     Using this EditType ensures that the editor created with
 | 
|---|
| 496 |     createEditor() (by default a QLineEdit) is always visible. This
 | 
|---|
| 497 |     has implications for the alignment of the content: the default
 | 
|---|
| 498 |     editor aligns everything (even numbers) to the left whilst
 | 
|---|
| 499 |     numerical values in the cell are by default aligned to the right.
 | 
|---|
| 500 | 
 | 
|---|
| 501 |     If a cell with the edit type \c Always looks misaligned you could
 | 
|---|
| 502 |     reimplement createEditor() for these items.
 | 
|---|
| 503 | 
 | 
|---|
| 504 |     \value WhenCurrent
 | 
|---|
| 505 |     The cell \e looks editable only when it has keyboard focus (see
 | 
|---|
| 506 |     QTable::setCurrentCell()).
 | 
|---|
| 507 | 
 | 
|---|
| 508 |     \value OnTyping
 | 
|---|
| 509 |     The cell \e looks editable only when the user types in it or
 | 
|---|
| 510 |     double-clicks it. It resembles the \c WhenCurrent functionality
 | 
|---|
| 511 |     but is, perhaps, nicer.
 | 
|---|
| 512 | 
 | 
|---|
| 513 |     The \c OnTyping edit type is the default when QTableItem objects
 | 
|---|
| 514 |     are created by the convenience functions QTable::setText() and
 | 
|---|
| 515 |     QTable::setPixmap().
 | 
|---|
| 516 | 
 | 
|---|
| 517 |     \value Never  The cell is not editable.
 | 
|---|
| 518 | 
 | 
|---|
| 519 |     The cell is actually editable only if QTable::isRowReadOnly() is
 | 
|---|
| 520 |     FALSE for its row, QTable::isColumnReadOnly() is FALSE for its
 | 
|---|
| 521 |     column, and QTable::isReadOnly() is FALSE.
 | 
|---|
| 522 | 
 | 
|---|
| 523 |     QComboTableItems have an isEditable() property. This property is
 | 
|---|
| 524 |     used to indicate whether the user may enter their own text or are
 | 
|---|
| 525 |     restricted to choosing one of the choices in the list.
 | 
|---|
| 526 |     QComboTableItems may be interacted with only if they are editable
 | 
|---|
| 527 |     in accordance with their EditType as described above.
 | 
|---|
| 528 | 
 | 
|---|
| 529 | */
 | 
|---|
| 530 | 
 | 
|---|
| 531 | /*!
 | 
|---|
| 532 |     Creates a table item that is a child of table \a table with no
 | 
|---|
| 533 |     text. The item has the \l EditType \a et.
 | 
|---|
| 534 | 
 | 
|---|
| 535 |     The table item will use a QLineEdit for its editor, will not
 | 
|---|
| 536 |     word-wrap and will occupy a single cell. Insert the table item
 | 
|---|
| 537 |     into a table with QTable::setItem().
 | 
|---|
| 538 | 
 | 
|---|
| 539 |     The table takes ownership of the table item, so a table item
 | 
|---|
| 540 |     should not be inserted into more than one table at a time.
 | 
|---|
| 541 | */
 | 
|---|
| 542 | 
 | 
|---|
| 543 | QTableItem::QTableItem( QTable *table, EditType et )
 | 
|---|
| 544 |     : txt(), pix(), t( table ), edType( et ), wordwrap( FALSE ),
 | 
|---|
| 545 |       tcha( TRUE ), rw( -1 ), cl( -1 ), rowspan( 1 ), colspan( 1 )
 | 
|---|
| 546 | {
 | 
|---|
| 547 |     enabled = TRUE;
 | 
|---|
| 548 | }
 | 
|---|
| 549 | 
 | 
|---|
| 550 | /*!
 | 
|---|
| 551 |     Creates a table item that is a child of table \a table with text
 | 
|---|
| 552 |     \a text. The item has the \l EditType \a et.
 | 
|---|
| 553 | 
 | 
|---|
| 554 |     The table item will use a QLineEdit for its editor, will not
 | 
|---|
| 555 |     word-wrap and will occupy a single cell. Insert the table item
 | 
|---|
| 556 |     into a table with QTable::setItem().
 | 
|---|
| 557 | 
 | 
|---|
| 558 |     The table takes ownership of the table item, so a table item
 | 
|---|
| 559 |     should not be inserted into more than one table at a time.
 | 
|---|
| 560 | */
 | 
|---|
| 561 | 
 | 
|---|
| 562 | QTableItem::QTableItem( QTable *table, EditType et, const QString &text )
 | 
|---|
| 563 |     : txt( text ), pix(), t( table ), edType( et ), wordwrap( FALSE ),
 | 
|---|
| 564 |       tcha( TRUE ), rw( -1 ), cl( -1 ), rowspan( 1 ), colspan( 1 )
 | 
|---|
| 565 | {
 | 
|---|
| 566 |     enabled = TRUE;
 | 
|---|
| 567 | }
 | 
|---|
| 568 | 
 | 
|---|
| 569 | /*!
 | 
|---|
| 570 |     Creates a table item that is a child of table \a table with text
 | 
|---|
| 571 |     \a text and pixmap \a p. The item has the \l EditType \a et.
 | 
|---|
| 572 | 
 | 
|---|
| 573 |     The table item will display the pixmap to the left of the text. It
 | 
|---|
| 574 |     will use a QLineEdit for editing the text, will not word-wrap and
 | 
|---|
| 575 |     will occupy a single cell. Insert the table item into a table with
 | 
|---|
| 576 |     QTable::setItem().
 | 
|---|
| 577 | 
 | 
|---|
| 578 |     The table takes ownership of the table item, so a table item
 | 
|---|
| 579 |     should not be inserted in more than one table at a time.
 | 
|---|
| 580 | */
 | 
|---|
| 581 | 
 | 
|---|
| 582 | QTableItem::QTableItem( QTable *table, EditType et,
 | 
|---|
| 583 |                         const QString &text, const QPixmap &p )
 | 
|---|
| 584 |     : txt( text ), pix( p ), t( table ), edType( et ), wordwrap( FALSE ),
 | 
|---|
| 585 |       tcha( TRUE ), rw( -1 ), cl( -1 ), rowspan( 1 ), colspan( 1 )
 | 
|---|
| 586 | {
 | 
|---|
| 587 |     enabled = TRUE;
 | 
|---|
| 588 | }
 | 
|---|
| 589 | 
 | 
|---|
| 590 | /*!
 | 
|---|
| 591 |     The destructor deletes this item and frees all allocated
 | 
|---|
| 592 |     resources.
 | 
|---|
| 593 | 
 | 
|---|
| 594 |     If the table item is in a table (i.e. was inserted with
 | 
|---|
| 595 |     setItem()), it will be removed from the table and the cell it
 | 
|---|
| 596 |     occupied.
 | 
|---|
| 597 | */
 | 
|---|
| 598 | 
 | 
|---|
| 599 | QTableItem::~QTableItem()
 | 
|---|
| 600 | {
 | 
|---|
| 601 |     if ( table() )
 | 
|---|
| 602 |         table()->takeItem( this );
 | 
|---|
| 603 | }
 | 
|---|
| 604 | 
 | 
|---|
| 605 | int QTableItem::RTTI = 0;
 | 
|---|
| 606 | 
 | 
|---|
| 607 | /*!
 | 
|---|
| 608 |     Returns the Run Time Type Identification value for this table item
 | 
|---|
| 609 |     which for QTableItems is 0.
 | 
|---|
| 610 | 
 | 
|---|
| 611 |     When you create subclasses based on QTableItem make sure that each
 | 
|---|
| 612 |     subclass returns a unique rtti() value. It is advisable to use
 | 
|---|
| 613 |     values greater than 1000, preferably large random numbers, to
 | 
|---|
| 614 |     allow for extensions to this class.
 | 
|---|
| 615 | 
 | 
|---|
| 616 |     \sa QCheckTableItem::rtti() QComboTableItem::rtti()
 | 
|---|
| 617 | */
 | 
|---|
| 618 | 
 | 
|---|
| 619 | int QTableItem::rtti() const
 | 
|---|
| 620 | {
 | 
|---|
| 621 |     return RTTI;
 | 
|---|
| 622 | }
 | 
|---|
| 623 | 
 | 
|---|
| 624 | /*!
 | 
|---|
| 625 |     Returns the table item's pixmap or a null pixmap if no pixmap has
 | 
|---|
| 626 |     been set.
 | 
|---|
| 627 | 
 | 
|---|
| 628 |     \sa setPixmap() text()
 | 
|---|
| 629 | */
 | 
|---|
| 630 | 
 | 
|---|
| 631 | QPixmap QTableItem::pixmap() const
 | 
|---|
| 632 | {
 | 
|---|
| 633 |     return pix;
 | 
|---|
| 634 | }
 | 
|---|
| 635 | 
 | 
|---|
| 636 | 
 | 
|---|
| 637 | /*!
 | 
|---|
| 638 |     Returns the text of the table item or QString::null if there is no
 | 
|---|
| 639 |     text.
 | 
|---|
| 640 | 
 | 
|---|
| 641 |     To ensure that the current value of the editor is returned,
 | 
|---|
| 642 |     setContentFromEditor() is called:
 | 
|---|
| 643 |     \list 1
 | 
|---|
| 644 |     \i if the editMode() is \c Always, or
 | 
|---|
| 645 |     \i if editMode() is \e not \c Always but the editor of the cell is
 | 
|---|
| 646 |     active and the editor is not a QLineEdit.
 | 
|---|
| 647 |     \endlist
 | 
|---|
| 648 | 
 | 
|---|
| 649 |     This means that text() returns the original text value of the item
 | 
|---|
| 650 |     if the editor is a line edit, until the user commits an edit (e.g.
 | 
|---|
| 651 |     by pressing Enter or Tab) in which case the new text is returned.
 | 
|---|
| 652 |     For other editors (e.g. a combobox) setContentFromEditor() is
 | 
|---|
| 653 |     always called so the currently display value is the one returned.
 | 
|---|
| 654 | 
 | 
|---|
| 655 |     \sa setText() pixmap()
 | 
|---|
| 656 | */
 | 
|---|
| 657 | 
 | 
|---|
| 658 | QString QTableItem::text() const
 | 
|---|
| 659 | {
 | 
|---|
| 660 |     QWidget *w = table()->cellWidget( rw, cl );
 | 
|---|
| 661 |     if ( w && ( edType == Always ||
 | 
|---|
| 662 |                 rtti() == QComboTableItem::RTTI ||
 | 
|---|
| 663 |                 rtti() == QCheckTableItem::RTTI ) )
 | 
|---|
| 664 |         ( (QTableItem*)this )->setContentFromEditor( w );
 | 
|---|
| 665 |     return txt;
 | 
|---|
| 666 | }
 | 
|---|
| 667 | 
 | 
|---|
| 668 | /*!
 | 
|---|
| 669 |     Sets pixmap \a p to be this item's pixmap.
 | 
|---|
| 670 | 
 | 
|---|
| 671 |     Note that setPixmap() does not update the cell the table item
 | 
|---|
| 672 |     belongs to. Use QTable::updateCell() to repaint the cell's
 | 
|---|
| 673 |     contents.
 | 
|---|
| 674 | 
 | 
|---|
| 675 |     For \l{QComboTableItem}s and \l{QCheckTableItem}s this function
 | 
|---|
| 676 |     has no visible effect.
 | 
|---|
| 677 | 
 | 
|---|
| 678 |     \sa QTable::setPixmap() pixmap() setText()
 | 
|---|
| 679 | */
 | 
|---|
| 680 | 
 | 
|---|
| 681 | void QTableItem::setPixmap( const QPixmap &p )
 | 
|---|
| 682 | {
 | 
|---|
| 683 |     pix = p;
 | 
|---|
| 684 | }
 | 
|---|
| 685 | 
 | 
|---|
| 686 | /*!
 | 
|---|
| 687 |     Changes the table item's text to \a str.
 | 
|---|
| 688 | 
 | 
|---|
| 689 |     Note that setText() does not update the cell the table item
 | 
|---|
| 690 |     belongs to. Use QTable::updateCell() to repaint the cell's
 | 
|---|
| 691 |     contents.
 | 
|---|
| 692 | 
 | 
|---|
| 693 |     \sa QTable::setText() text() setPixmap() QTable::updateCell()
 | 
|---|
| 694 | */
 | 
|---|
| 695 | 
 | 
|---|
| 696 | void QTableItem::setText( const QString &str )
 | 
|---|
| 697 | {
 | 
|---|
| 698 |     txt = str;
 | 
|---|
| 699 | }
 | 
|---|
| 700 | 
 | 
|---|
| 701 | /*!
 | 
|---|
| 702 |     This virtual function is used to paint the contents of an item
 | 
|---|
| 703 |     using the painter \a p in the rectangular area \a cr using the
 | 
|---|
| 704 |     color group \a cg.
 | 
|---|
| 705 | 
 | 
|---|
| 706 |     If \a selected is TRUE the cell is displayed in a way that
 | 
|---|
| 707 |     indicates that it is highlighted.
 | 
|---|
| 708 | 
 | 
|---|
| 709 |     You don't usually need to use this function but if you want to
 | 
|---|
| 710 |     draw custom content in a cell you will need to reimplement it.
 | 
|---|
| 711 | 
 | 
|---|
| 712 |     The painter passed to this function is translated so that 0, 0
 | 
|---|
| 713 |     is the top-left corner of the item that is being painted.
 | 
|---|
| 714 | 
 | 
|---|
| 715 |     Note that the painter is not clipped by default in order to get
 | 
|---|
| 716 |     maximum efficiency. If you want clipping, use
 | 
|---|
| 717 | 
 | 
|---|
| 718 |     \code
 | 
|---|
| 719 |     p->setClipRect( table()->cellRect(row, col), QPainter::ClipPainter );
 | 
|---|
| 720 |     //... your drawing code
 | 
|---|
| 721 |     p->setClipping( FALSE );
 | 
|---|
| 722 |     \endcode
 | 
|---|
| 723 | 
 | 
|---|
| 724 | */
 | 
|---|
| 725 | 
 | 
|---|
| 726 | void QTableItem::paint( QPainter *p, const QColorGroup &cg,
 | 
|---|
| 727 |                         const QRect &cr, bool selected )
 | 
|---|
| 728 | {
 | 
|---|
| 729 |     p->fillRect( 0, 0, cr.width(), cr.height(),
 | 
|---|
| 730 |                  selected ? cg.brush( QColorGroup::Highlight )
 | 
|---|
| 731 |                           : cg.brush( QColorGroup::Base ) );
 | 
|---|
| 732 | 
 | 
|---|
| 733 |     int w = cr.width();
 | 
|---|
| 734 |     int h = cr.height();
 | 
|---|
| 735 | 
 | 
|---|
| 736 |     int x = 0;
 | 
|---|
| 737 |     if ( !pix.isNull() ) {
 | 
|---|
| 738 |         p->drawPixmap( 0, ( cr.height() - pix.height() ) / 2, pix );
 | 
|---|
| 739 |         x = pix.width() + 2;
 | 
|---|
| 740 |     }
 | 
|---|
| 741 | 
 | 
|---|
| 742 |     if ( selected )
 | 
|---|
| 743 |         p->setPen( cg.highlightedText() );
 | 
|---|
| 744 |     else
 | 
|---|
| 745 |         p->setPen( cg.text() );
 | 
|---|
| 746 |     p->drawText( x + 2, 0, w - x - 4, h,
 | 
|---|
| 747 |                  wordwrap ? (alignment() | WordBreak) : alignment(), text() );
 | 
|---|
| 748 | }
 | 
|---|
| 749 | 
 | 
|---|
| 750 | /*!
 | 
|---|
| 751 |     This virtual function creates an editor which the user can
 | 
|---|
| 752 |     interact with to edit the cell's contents. The default
 | 
|---|
| 753 |     implementation creates a QLineEdit.
 | 
|---|
| 754 | 
 | 
|---|
| 755 |     If the function returns 0, the cell is read-only.
 | 
|---|
| 756 | 
 | 
|---|
| 757 |     The returned widget should preferably be invisible, ideally with
 | 
|---|
| 758 |     QTable::viewport() as parent.
 | 
|---|
| 759 | 
 | 
|---|
| 760 |     If you reimplement this function you'll almost certainly need to
 | 
|---|
| 761 |     reimplement setContentFromEditor(), and may need to reimplement
 | 
|---|
| 762 |     sizeHint().
 | 
|---|
| 763 |     Also note that you need to call setReplaceable( FALSE ) when creating the item.
 | 
|---|
| 764 |     Otherwise a QLineEdit is used as the editor.
 | 
|---|
| 765 | 
 | 
|---|
| 766 |     \quotefile table/statistics/statistics.cpp
 | 
|---|
| 767 |     \skipto createEditor
 | 
|---|
| 768 |     \printto }
 | 
|---|
| 769 | 
 | 
|---|
| 770 |     \sa QTable::createEditor() setContentFromEditor() QTable::viewport() setReplaceable()
 | 
|---|
| 771 | */
 | 
|---|
| 772 | 
 | 
|---|
| 773 | QWidget *QTableItem::createEditor() const
 | 
|---|
| 774 | {
 | 
|---|
| 775 |     QLineEdit *e = new QLineEdit( table()->viewport(), "qt_tableeditor" );
 | 
|---|
| 776 |     e->setFrame( FALSE );
 | 
|---|
| 777 |     e->setText( text() );
 | 
|---|
| 778 |     return e;
 | 
|---|
| 779 | }
 | 
|---|
| 780 | 
 | 
|---|
| 781 | /*!
 | 
|---|
| 782 |     Whenever the content of a cell has been edited by the editor \a w,
 | 
|---|
| 783 |     QTable calls this virtual function to copy the new values into the
 | 
|---|
| 784 |     QTableItem.
 | 
|---|
| 785 | 
 | 
|---|
| 786 |     If you reimplement createEditor() and return something that is not
 | 
|---|
| 787 |     a QLineEdit you will almost certainly have to reimplement this
 | 
|---|
| 788 |     function.
 | 
|---|
| 789 | 
 | 
|---|
| 790 |     \quotefile table/statistics/statistics.cpp
 | 
|---|
| 791 |     \skipto setContentFromEditor
 | 
|---|
| 792 |     \printto }
 | 
|---|
| 793 | 
 | 
|---|
| 794 |     \sa QTable::setCellContentFromEditor()
 | 
|---|
| 795 | */
 | 
|---|
| 796 | 
 | 
|---|
| 797 | void QTableItem::setContentFromEditor( QWidget *w )
 | 
|---|
| 798 | {
 | 
|---|
| 799 |     QLineEdit *le = ::qt_cast<QLineEdit*>(w);
 | 
|---|
| 800 |     if ( le ) {
 | 
|---|
| 801 |         QString input = le->text();
 | 
|---|
| 802 |         if ( le->validator() )
 | 
|---|
| 803 |             le->validator()->fixup( input );
 | 
|---|
| 804 |         setText( input );
 | 
|---|
| 805 |     }
 | 
|---|
| 806 | }
 | 
|---|
| 807 | 
 | 
|---|
| 808 | /*!
 | 
|---|
| 809 |     The alignment function returns how the text contents of the cell
 | 
|---|
| 810 |     are aligned when drawn. The default implementation aligns numbers
 | 
|---|
| 811 |     to the right and any other text to the left.
 | 
|---|
| 812 | 
 | 
|---|
| 813 |     \sa Qt::AlignmentFlags
 | 
|---|
| 814 | */
 | 
|---|
| 815 | 
 | 
|---|
| 816 | // ed: For consistency reasons a setAlignment() should be provided
 | 
|---|
| 817 | // as well.
 | 
|---|
| 818 | 
 | 
|---|
| 819 | int QTableItem::alignment() const
 | 
|---|
| 820 | {
 | 
|---|
| 821 |     bool num;
 | 
|---|
| 822 |     bool ok1 = FALSE, ok2 = FALSE;
 | 
|---|
| 823 |     (void)text().toInt( &ok1 );
 | 
|---|
| 824 |     if ( !ok1 )
 | 
|---|
| 825 |         (void)text().toDouble( &ok2 ); // ### should be .-aligned
 | 
|---|
| 826 |     num = ok1 || ok2;
 | 
|---|
| 827 | 
 | 
|---|
| 828 |     return ( num ? AlignRight : AlignLeft ) | AlignVCenter;
 | 
|---|
| 829 | }
 | 
|---|
| 830 | 
 | 
|---|
| 831 | /*!
 | 
|---|
| 832 |     If \a b is TRUE, the cell's text will be wrapped over multiple
 | 
|---|
| 833 |     lines, when necessary, to fit the width of the cell; otherwise the
 | 
|---|
| 834 |     text will be written as a single line.
 | 
|---|
| 835 | 
 | 
|---|
| 836 |     \sa wordWrap() QTable::adjustColumn() QTable::setColumnStretchable()
 | 
|---|
| 837 | */
 | 
|---|
| 838 | 
 | 
|---|
| 839 | void QTableItem::setWordWrap( bool b )
 | 
|---|
| 840 | {
 | 
|---|
| 841 |     wordwrap = b;
 | 
|---|
| 842 | }
 | 
|---|
| 843 | 
 | 
|---|
| 844 | /*!
 | 
|---|
| 845 |     Returns TRUE if word wrap is enabled for the cell; otherwise
 | 
|---|
| 846 |     returns FALSE.
 | 
|---|
| 847 | 
 | 
|---|
| 848 |     \sa setWordWrap()
 | 
|---|
| 849 | */
 | 
|---|
| 850 | 
 | 
|---|
| 851 | bool QTableItem::wordWrap() const
 | 
|---|
| 852 | {
 | 
|---|
| 853 |     return wordwrap;
 | 
|---|
| 854 | }
 | 
|---|
| 855 | 
 | 
|---|
| 856 | /*! \internal */
 | 
|---|
| 857 | 
 | 
|---|
| 858 | void QTableItem::updateEditor( int oldRow, int oldCol )
 | 
|---|
| 859 | {
 | 
|---|
| 860 |     if ( edType != Always )
 | 
|---|
| 861 |         return;
 | 
|---|
| 862 |     if ( oldRow != -1 && oldCol != -1 )
 | 
|---|
| 863 |         table()->clearCellWidget( oldRow, oldCol );
 | 
|---|
| 864 |     if ( rw != -1 && cl != -1 )
 | 
|---|
| 865 |         table()->setCellWidget( rw, cl, createEditor() );
 | 
|---|
| 866 | }
 | 
|---|
| 867 | 
 | 
|---|
| 868 | /*!
 | 
|---|
| 869 |     Returns the table item's edit type.
 | 
|---|
| 870 | 
 | 
|---|
| 871 |     This is set when the table item is constructed.
 | 
|---|
| 872 | 
 | 
|---|
| 873 |     \sa EditType QTableItem()
 | 
|---|
| 874 | */
 | 
|---|
| 875 | 
 | 
|---|
| 876 | QTableItem::EditType QTableItem::editType() const
 | 
|---|
| 877 | {
 | 
|---|
| 878 |     return edType;
 | 
|---|
| 879 | }
 | 
|---|
| 880 | 
 | 
|---|
| 881 | /*!
 | 
|---|
| 882 |     If \a b is TRUE it is acceptable to replace the contents of the
 | 
|---|
| 883 |     cell with the contents of another QTableItem. If \a b is FALSE the
 | 
|---|
| 884 |     contents of the cell may not be replaced by the contents of
 | 
|---|
| 885 |     another table item. Table items that span more than one cell may
 | 
|---|
| 886 |     not have their contents replaced by another table item.
 | 
|---|
| 887 | 
 | 
|---|
| 888 |     (This differs from \l EditType because EditType is concerned with
 | 
|---|
| 889 |     whether the \e user is able to change the contents of a cell.)
 | 
|---|
| 890 | 
 | 
|---|
| 891 |     \sa isReplaceable()
 | 
|---|
| 892 | */
 | 
|---|
| 893 | 
 | 
|---|
| 894 | void QTableItem::setReplaceable( bool b )
 | 
|---|
| 895 | {
 | 
|---|
| 896 |     tcha = b;
 | 
|---|
| 897 | }
 | 
|---|
| 898 | 
 | 
|---|
| 899 | /*!
 | 
|---|
| 900 |     This function returns whether the contents of the cell may be
 | 
|---|
| 901 |     replaced with the contents of another table item. Regardless of
 | 
|---|
| 902 |     this setting, table items that span more than one cell may not
 | 
|---|
| 903 |     have their contents replaced by another table item.
 | 
|---|
| 904 | 
 | 
|---|
| 905 |     (This differs from \l EditType because EditType is concerned with
 | 
|---|
| 906 |     whether the \e user is able to change the contents of a cell.)
 | 
|---|
| 907 | 
 | 
|---|
| 908 |     \sa setReplaceable() EditType
 | 
|---|
| 909 | */
 | 
|---|
| 910 | 
 | 
|---|
| 911 | bool QTableItem::isReplaceable() const
 | 
|---|
| 912 | {
 | 
|---|
| 913 |     if ( rowspan > 1 || colspan > 1 )
 | 
|---|
| 914 |         return FALSE;
 | 
|---|
| 915 |     return tcha;
 | 
|---|
| 916 | }
 | 
|---|
| 917 | 
 | 
|---|
| 918 | /*!
 | 
|---|
| 919 |     This virtual function returns the key that should be used for
 | 
|---|
| 920 |     sorting. The default implementation returns the text() of the
 | 
|---|
| 921 |     relevant item.
 | 
|---|
| 922 | 
 | 
|---|
| 923 |     \sa QTable::setSorting()
 | 
|---|
| 924 | */
 | 
|---|
| 925 | 
 | 
|---|
| 926 | QString QTableItem::key() const
 | 
|---|
| 927 | {
 | 
|---|
| 928 |     return text();
 | 
|---|
| 929 | }
 | 
|---|
| 930 | 
 | 
|---|
| 931 | /*!
 | 
|---|
| 932 |     This virtual function returns the size a cell needs to show its
 | 
|---|
| 933 |     entire content.
 | 
|---|
| 934 | 
 | 
|---|
| 935 |     If you subclass QTableItem you will often need to reimplement this
 | 
|---|
| 936 |     function.
 | 
|---|
| 937 | */
 | 
|---|
| 938 | 
 | 
|---|
| 939 | QSize QTableItem::sizeHint() const
 | 
|---|
| 940 | {
 | 
|---|
| 941 |     QSize strutSize = QApplication::globalStrut();
 | 
|---|
| 942 |     if ( edType == Always && table()->cellWidget( rw, cl ) )
 | 
|---|
| 943 |         return table()->cellWidget( rw, cl )->sizeHint().expandedTo( strutSize );
 | 
|---|
| 944 | 
 | 
|---|
| 945 |     QSize s;
 | 
|---|
| 946 |     int x = 0;
 | 
|---|
| 947 |     if ( !pix.isNull() ) {
 | 
|---|
| 948 |         s = pix.size();
 | 
|---|
| 949 |         s.setWidth( s.width() + 2 );
 | 
|---|
| 950 |         x = pix.width() + 2;
 | 
|---|
| 951 |     }
 | 
|---|
| 952 | 
 | 
|---|
| 953 |     QString t = text();
 | 
|---|
| 954 |     if ( !wordwrap && t.find( '\n' ) == -1 )
 | 
|---|
| 955 |         return QSize( s.width() + table()->fontMetrics().width( text() ) + 10,
 | 
|---|
| 956 |                       QMAX( s.height(), table()->fontMetrics().height() ) ).expandedTo( strutSize );
 | 
|---|
| 957 | 
 | 
|---|
| 958 |     QRect r = table()->fontMetrics().boundingRect( x + 2, 0, table()->columnWidth( col() ) - x - 4, 0,
 | 
|---|
| 959 |                                                    wordwrap ? (alignment() | WordBreak) : alignment(),
 | 
|---|
| 960 |                                                    text() );
 | 
|---|
| 961 |     r.setWidth( QMAX( r.width() + 10, table()->columnWidth( col() ) ) );
 | 
|---|
| 962 |     return QSize( r.width(), QMAX( s.height(), r.height() ) ).expandedTo( strutSize );
 | 
|---|
| 963 | }
 | 
|---|
| 964 | 
 | 
|---|
| 965 | /*!
 | 
|---|
| 966 |     Changes the extent of the QTableItem so that it spans multiple
 | 
|---|
| 967 |     cells covering \a rs rows and \a cs columns. The top left cell is
 | 
|---|
| 968 |     the original cell.
 | 
|---|
| 969 | 
 | 
|---|
| 970 |     \warning This function only works if the item has already been
 | 
|---|
| 971 |     inserted into the table using e.g. QTable::setItem(). This
 | 
|---|
| 972 |     function also checks to make sure if \a rs and \a cs are within
 | 
|---|
| 973 |     the bounds of the table and returns without changing the span if
 | 
|---|
| 974 |     they are not. In addition swapping, inserting or removing rows and
 | 
|---|
| 975 |     columns that cross QTableItems spanning more than one cell is not
 | 
|---|
| 976 |     supported.
 | 
|---|
| 977 | 
 | 
|---|
| 978 |     \sa rowSpan() colSpan()
 | 
|---|
| 979 | */
 | 
|---|
| 980 | 
 | 
|---|
| 981 | void QTableItem::setSpan( int rs, int cs )
 | 
|---|
| 982 | {
 | 
|---|
| 983 |     if ( rs == rowspan && cs == colspan )
 | 
|---|
| 984 |         return;
 | 
|---|
| 985 | 
 | 
|---|
| 986 |     if ( !table()->d->hasRowSpan )
 | 
|---|
| 987 |         table()->d->hasRowSpan = rs > 1;
 | 
|---|
| 988 |     if ( !table()->d->hasColSpan )
 | 
|---|
| 989 |         table()->d->hasColSpan = cs > 1;
 | 
|---|
| 990 |     // return if we are thinking too big...
 | 
|---|
| 991 |     if ( rw + rs > table()->numRows() )
 | 
|---|
| 992 |         return;
 | 
|---|
| 993 | 
 | 
|---|
| 994 |     if ( cl + cs > table()->numCols() )
 | 
|---|
| 995 |         return;
 | 
|---|
| 996 | 
 | 
|---|
| 997 |     if ( rw == -1 || cl == -1 )
 | 
|---|
| 998 |         return;
 | 
|---|
| 999 | 
 | 
|---|
| 1000 |     int rrow = rw;
 | 
|---|
| 1001 |     int rcol = cl;
 | 
|---|
| 1002 |     if ( rowspan > 1 || colspan > 1 ) {
 | 
|---|
| 1003 |         QTable* t = table();
 | 
|---|
| 1004 |         t->takeItem( this );
 | 
|---|
| 1005 |         t->setItem( rrow, rcol, this );
 | 
|---|
| 1006 |     }
 | 
|---|
| 1007 | 
 | 
|---|
| 1008 |     rowspan = rs;
 | 
|---|
| 1009 |     colspan = cs;
 | 
|---|
| 1010 | 
 | 
|---|
| 1011 |     for ( int r = 0; r < rowspan; ++r ) {
 | 
|---|
| 1012 |         for ( int c = 0; c < colspan; ++c ) {
 | 
|---|
| 1013 |             if ( r == 0 && c == 0 )
 | 
|---|
| 1014 |                 continue;
 | 
|---|
| 1015 |             qt_update_cell_widget = FALSE;
 | 
|---|
| 1016 |             table()->setItem( r + rw, c + cl, this );
 | 
|---|
| 1017 |             qt_update_cell_widget = TRUE;
 | 
|---|
| 1018 |             rw = rrow;
 | 
|---|
| 1019 |             cl = rcol;
 | 
|---|
| 1020 |         }
 | 
|---|
| 1021 |     }
 | 
|---|
| 1022 | 
 | 
|---|
| 1023 |     table()->updateCell( rw, cl );
 | 
|---|
| 1024 |     QWidget *w = table()->cellWidget( rw, cl );
 | 
|---|
| 1025 |     if ( w )
 | 
|---|
| 1026 |         w->resize( table()->cellGeometry( rw, cl ).size() );
 | 
|---|
| 1027 | }
 | 
|---|
| 1028 | 
 | 
|---|
| 1029 | /*!
 | 
|---|
| 1030 |     Returns the row span of the table item, usually 1.
 | 
|---|
| 1031 | 
 | 
|---|
| 1032 |     \sa setSpan() colSpan()
 | 
|---|
| 1033 | */
 | 
|---|
| 1034 | 
 | 
|---|
| 1035 | int QTableItem::rowSpan() const
 | 
|---|
| 1036 | {
 | 
|---|
| 1037 |     return rowspan;
 | 
|---|
| 1038 | }
 | 
|---|
| 1039 | 
 | 
|---|
| 1040 | /*!
 | 
|---|
| 1041 |     Returns the column span of the table item, usually 1.
 | 
|---|
| 1042 | 
 | 
|---|
| 1043 |     \sa setSpan() rowSpan()
 | 
|---|
| 1044 | */
 | 
|---|
| 1045 | 
 | 
|---|
| 1046 | int QTableItem::colSpan() const
 | 
|---|
| 1047 | {
 | 
|---|
| 1048 |     return colspan;
 | 
|---|
| 1049 | }
 | 
|---|
| 1050 | 
 | 
|---|
| 1051 | /*!
 | 
|---|
| 1052 |     Sets row \a r as the table item's row. Usually you do not need to
 | 
|---|
| 1053 |     call this function.
 | 
|---|
| 1054 | 
 | 
|---|
| 1055 |     If the cell spans multiple rows, this function sets the top row
 | 
|---|
| 1056 |     and retains the height of the multi-cell table item.
 | 
|---|
| 1057 | 
 | 
|---|
| 1058 |     \sa row() setCol() rowSpan()
 | 
|---|
| 1059 | */
 | 
|---|
| 1060 | 
 | 
|---|
| 1061 | void QTableItem::setRow( int r )
 | 
|---|
| 1062 | {
 | 
|---|
| 1063 |     rw = r;
 | 
|---|
| 1064 | }
 | 
|---|
| 1065 | 
 | 
|---|
| 1066 | /*!
 | 
|---|
| 1067 |     Sets column \a c as the table item's column. Usually you will not
 | 
|---|
| 1068 |     need to call this function.
 | 
|---|
| 1069 | 
 | 
|---|
| 1070 |     If the cell spans multiple columns, this function sets the
 | 
|---|
| 1071 |     left-most column and retains the width of the multi-cell table
 | 
|---|
| 1072 |     item.
 | 
|---|
| 1073 | 
 | 
|---|
| 1074 |     \sa col() setRow() colSpan()
 | 
|---|
| 1075 | */
 | 
|---|
| 1076 | 
 | 
|---|
| 1077 | void QTableItem::setCol( int c )
 | 
|---|
| 1078 | {
 | 
|---|
| 1079 |     cl = c;
 | 
|---|
| 1080 | }
 | 
|---|
| 1081 | 
 | 
|---|
| 1082 | /*!
 | 
|---|
| 1083 |     Returns the row where the table item is located. If the cell spans
 | 
|---|
| 1084 |     multiple rows, this function returns the top-most row.
 | 
|---|
| 1085 | 
 | 
|---|
| 1086 |     \sa col() setRow()
 | 
|---|
| 1087 | */
 | 
|---|
| 1088 | 
 | 
|---|
| 1089 | int QTableItem::row() const
 | 
|---|
| 1090 | {
 | 
|---|
| 1091 |     return rw;
 | 
|---|
| 1092 | }
 | 
|---|
| 1093 | 
 | 
|---|
| 1094 | /*!
 | 
|---|
| 1095 |     Returns the column where the table item is located. If the cell
 | 
|---|
| 1096 |     spans multiple columns, this function returns the left-most
 | 
|---|
| 1097 |     column.
 | 
|---|
| 1098 | 
 | 
|---|
| 1099 |     \sa row() setCol()
 | 
|---|
| 1100 | */
 | 
|---|
| 1101 | 
 | 
|---|
| 1102 | int QTableItem::col() const
 | 
|---|
| 1103 | {
 | 
|---|
| 1104 |     return cl;
 | 
|---|
| 1105 | }
 | 
|---|
| 1106 | 
 | 
|---|
| 1107 | /*!
 | 
|---|
| 1108 |     If \a b is TRUE, the table item is enabled; if \a b is FALSE the
 | 
|---|
| 1109 |     table item is disabled.
 | 
|---|
| 1110 | 
 | 
|---|
| 1111 |     A disabled item doesn't respond to user interaction.
 | 
|---|
| 1112 | 
 | 
|---|
| 1113 |     \sa isEnabled()
 | 
|---|
| 1114 | */
 | 
|---|
| 1115 | 
 | 
|---|
| 1116 | void QTableItem::setEnabled( bool b )
 | 
|---|
| 1117 | {
 | 
|---|
| 1118 |     if ( b == (bool)enabled )
 | 
|---|
| 1119 |         return;
 | 
|---|
| 1120 |     enabled = b;
 | 
|---|
| 1121 |     table()->updateCell( row(), col() );
 | 
|---|
| 1122 | }
 | 
|---|
| 1123 | 
 | 
|---|
| 1124 | /*!
 | 
|---|
| 1125 |     Returns TRUE if the table item is enabled; otherwise returns FALSE.
 | 
|---|
| 1126 | 
 | 
|---|
| 1127 |     \sa setEnabled()
 | 
|---|
| 1128 | */
 | 
|---|
| 1129 | 
 | 
|---|
| 1130 | bool QTableItem::isEnabled() const
 | 
|---|
| 1131 | {
 | 
|---|
| 1132 |     return (bool)enabled;
 | 
|---|
| 1133 | }
 | 
|---|
| 1134 | 
 | 
|---|
| 1135 | /*!
 | 
|---|
| 1136 |     \class QComboTableItem
 | 
|---|
| 1137 |     \brief The QComboTableItem class provides a means of using
 | 
|---|
| 1138 |     comboboxes in QTables.
 | 
|---|
| 1139 | \if defined(commercial)
 | 
|---|
| 1140 |     It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
 | 
|---|
| 1141 | \endif
 | 
|---|
| 1142 | 
 | 
|---|
| 1143 |     \ingroup advanced
 | 
|---|
| 1144 |     \module table
 | 
|---|
| 1145 | 
 | 
|---|
| 1146 |     A QComboTableItem is a table item which looks and behaves like a
 | 
|---|
| 1147 |     combobox. The advantage of using QComboTableItems rather than real
 | 
|---|
| 1148 |     comboboxes is that a QComboTableItem uses far less resources than
 | 
|---|
| 1149 |     real comboboxes in \l{QTable}s. When the cell has the focus it
 | 
|---|
| 1150 |     displays a real combobox which the user can interact with. When
 | 
|---|
| 1151 |     the cell does not have the focus the cell \e looks like a
 | 
|---|
| 1152 |     combobox. Only text items (i.e. no pixmaps) may be used in
 | 
|---|
| 1153 |     QComboTableItems.
 | 
|---|
| 1154 | 
 | 
|---|
| 1155 |     QComboTableItem items have the edit type \c WhenCurrent (see
 | 
|---|
| 1156 |     \l{EditType}). The QComboTableItem's list of items is provided by
 | 
|---|
| 1157 |     a QStringList passed to the constructor.
 | 
|---|
| 1158 | 
 | 
|---|
| 1159 |     The list of items may be changed using setStringList(). The
 | 
|---|
| 1160 |     current item can be set with setCurrentItem() and retrieved with
 | 
|---|
| 1161 |     currentItem(). The text of the current item can be obtained with
 | 
|---|
| 1162 |     currentText(), and the text of a particular item can be retrieved
 | 
|---|
| 1163 |     with text().
 | 
|---|
| 1164 | 
 | 
|---|
| 1165 |     If isEditable() is TRUE the QComboTableItem will permit the user
 | 
|---|
| 1166 |     to either choose an existing list item, or create a new list item
 | 
|---|
| 1167 |     by entering their own text; otherwise the user may only choose one
 | 
|---|
| 1168 |     of the existing list items.
 | 
|---|
| 1169 | 
 | 
|---|
| 1170 |     To populate a table cell with a QComboTableItem use
 | 
|---|
| 1171 |     QTable::setItem().
 | 
|---|
| 1172 | 
 | 
|---|
| 1173 |     QComboTableItems may be deleted with QTable::clearCell().
 | 
|---|
| 1174 | 
 | 
|---|
| 1175 |     QComboTableItems can be distinguished from \l{QTableItem}s and
 | 
|---|
| 1176 |     \l{QCheckTableItem}s using their Run Time Type Identification
 | 
|---|
| 1177 |     number (see rtti()).
 | 
|---|
| 1178 | 
 | 
|---|
| 1179 |     \img qtableitems.png Table Items
 | 
|---|
| 1180 | 
 | 
|---|
| 1181 |     \sa QCheckTableItem QTableItem QComboBox
 | 
|---|
| 1182 | */
 | 
|---|
| 1183 | 
 | 
|---|
| 1184 | QComboBox *QComboTableItem::fakeCombo = 0;
 | 
|---|
| 1185 | QWidget *QComboTableItem::fakeComboWidget = 0;
 | 
|---|
| 1186 | int QComboTableItem::fakeRef = 0;
 | 
|---|
| 1187 | 
 | 
|---|
| 1188 | /*!
 | 
|---|
| 1189 |     Creates a combo table item for the table \a table. The combobox's
 | 
|---|
| 1190 |     list of items is passed in the \a list argument. If \a editable is
 | 
|---|
| 1191 |     TRUE the user may type in new list items; if \a editable is FALSE
 | 
|---|
| 1192 |     the user may only select from the list of items provided.
 | 
|---|
| 1193 | 
 | 
|---|
| 1194 |     By default QComboTableItems cannot be replaced by other table
 | 
|---|
| 1195 |     items since isReplaceable() returns FALSE by default.
 | 
|---|
| 1196 | 
 | 
|---|
| 1197 |     \sa QTable::clearCell() EditType
 | 
|---|
| 1198 | */
 | 
|---|
| 1199 | 
 | 
|---|
| 1200 | QComboTableItem::QComboTableItem( QTable *table, const QStringList &list, bool editable )
 | 
|---|
| 1201 |     : QTableItem( table, WhenCurrent, "" ), entries( list ), current( 0 ), edit( editable )
 | 
|---|
| 1202 | {
 | 
|---|
| 1203 |     setReplaceable( FALSE );
 | 
|---|
| 1204 |     if ( !QComboTableItem::fakeCombo ) {
 | 
|---|
| 1205 |         QComboTableItem::fakeComboWidget = new QWidget( 0, 0 );
 | 
|---|
| 1206 |         QComboTableItem::fakeCombo = new QComboBox( FALSE, QComboTableItem::fakeComboWidget, 0 );
 | 
|---|
| 1207 |         QComboTableItem::fakeCombo->hide();
 | 
|---|
| 1208 |     }
 | 
|---|
| 1209 |     ++QComboTableItem::fakeRef;
 | 
|---|
| 1210 |     if ( entries.count() )
 | 
|---|
| 1211 |         setText( *entries.at( current ) );
 | 
|---|
| 1212 | }
 | 
|---|
| 1213 | 
 | 
|---|
| 1214 | /*!
 | 
|---|
| 1215 |     QComboTableItem destructor.
 | 
|---|
| 1216 | */
 | 
|---|
| 1217 | QComboTableItem::~QComboTableItem()
 | 
|---|
| 1218 | {
 | 
|---|
| 1219 |     if (--QComboTableItem::fakeRef <= 0) {
 | 
|---|
| 1220 |         delete QComboTableItem::fakeComboWidget;
 | 
|---|
| 1221 |         QComboTableItem::fakeComboWidget = 0;
 | 
|---|
| 1222 |         QComboTableItem::fakeCombo = 0;
 | 
|---|
| 1223 |     }
 | 
|---|
| 1224 | }
 | 
|---|
| 1225 | 
 | 
|---|
| 1226 | /*!
 | 
|---|
| 1227 |     Sets the list items of this QComboTableItem to the strings in the
 | 
|---|
| 1228 |     string list \a l.
 | 
|---|
| 1229 | */
 | 
|---|
| 1230 | 
 | 
|---|
| 1231 | void QComboTableItem::setStringList( const QStringList &l )
 | 
|---|
| 1232 | {
 | 
|---|
| 1233 |     entries = l;
 | 
|---|
| 1234 |     current = 0;
 | 
|---|
| 1235 |     if ( entries.count() )
 | 
|---|
| 1236 |         setText( *entries.at( current ) );
 | 
|---|
| 1237 |     if ( table()->cellWidget( row(), col() ) ) {
 | 
|---|
| 1238 |         cb->clear();
 | 
|---|
| 1239 |         cb->insertStringList( entries );
 | 
|---|
| 1240 |     }
 | 
|---|
| 1241 |     table()->updateCell( row(), col() );
 | 
|---|
| 1242 | }
 | 
|---|
| 1243 | 
 | 
|---|
| 1244 | /*! \reimp */
 | 
|---|
| 1245 | 
 | 
|---|
| 1246 | QWidget *QComboTableItem::createEditor() const
 | 
|---|
| 1247 | {
 | 
|---|
| 1248 |     // create an editor - a combobox in our case
 | 
|---|
| 1249 |     ( (QComboTableItem*)this )->cb = new QComboBox( edit, table()->viewport(), "qt_editor_cb" );
 | 
|---|
| 1250 |     cb->insertStringList( entries );
 | 
|---|
| 1251 |     cb->setCurrentItem( current );
 | 
|---|
| 1252 |     QObject::connect( cb, SIGNAL( activated(int) ), table(), SLOT( doValueChanged() ) );
 | 
|---|
| 1253 |     return cb;
 | 
|---|
| 1254 | }
 | 
|---|
| 1255 | 
 | 
|---|
| 1256 | /*! \reimp */
 | 
|---|
| 1257 | 
 | 
|---|
| 1258 | void QComboTableItem::setContentFromEditor( QWidget *w )
 | 
|---|
| 1259 | {
 | 
|---|
| 1260 |     QComboBox *cb = ::qt_cast<QComboBox*>(w);
 | 
|---|
| 1261 |     if ( cb ) {
 | 
|---|
| 1262 |         entries.clear();
 | 
|---|
| 1263 |         for ( int i = 0; i < cb->count(); ++i )
 | 
|---|
| 1264 |             entries << cb->text( i );
 | 
|---|
| 1265 |         current = cb->currentItem();
 | 
|---|
| 1266 |         setText( *entries.at( current ) );
 | 
|---|
| 1267 |     }
 | 
|---|
| 1268 | }
 | 
|---|
| 1269 | 
 | 
|---|
| 1270 | /*! \reimp */
 | 
|---|
| 1271 | 
 | 
|---|
| 1272 | void QComboTableItem::paint( QPainter *p, const QColorGroup &cg,
 | 
|---|
| 1273 |                            const QRect &cr, bool selected )
 | 
|---|
| 1274 | {
 | 
|---|
| 1275 |     fakeCombo->resize( cr.width(), cr.height() );
 | 
|---|
| 1276 | 
 | 
|---|
| 1277 |     QColorGroup c( cg );
 | 
|---|
| 1278 |     if ( selected ) {
 | 
|---|
| 1279 |         c.setBrush( QColorGroup::Base, cg.brush( QColorGroup::Highlight ) );
 | 
|---|
| 1280 |         c.setColor( QColorGroup::Text, cg.highlightedText() );
 | 
|---|
| 1281 |     }
 | 
|---|
| 1282 | 
 | 
|---|
| 1283 |     QStyle::SFlags flags = QStyle::Style_Default;
 | 
|---|
| 1284 |     if(isEnabled() && table()->isEnabled())
 | 
|---|
| 1285 |         flags |= QStyle::Style_Enabled;
 | 
|---|
| 1286 |     table()->style().drawComplexControl( QStyle::CC_ComboBox, p, fakeCombo, fakeCombo->rect(), c, flags );
 | 
|---|
| 1287 | 
 | 
|---|
| 1288 |     p->save();
 | 
|---|
| 1289 |     QRect textR = table()->style().querySubControlMetrics(QStyle::CC_ComboBox, fakeCombo,
 | 
|---|
| 1290 |                                                          QStyle::SC_ComboBoxEditField);
 | 
|---|
| 1291 |     int align = alignment(); // alignment() changes entries
 | 
|---|
| 1292 |     p->drawText( textR, wordWrap() ? ( align | WordBreak ) : align, *entries.at( current ) );
 | 
|---|
| 1293 |     p->restore();
 | 
|---|
| 1294 | }
 | 
|---|
| 1295 | 
 | 
|---|
| 1296 | /*!
 | 
|---|
| 1297 |     Sets the list item \a i to be the combo table item's current list
 | 
|---|
| 1298 |     item.
 | 
|---|
| 1299 | 
 | 
|---|
| 1300 |     \sa currentItem()
 | 
|---|
| 1301 | */
 | 
|---|
| 1302 | 
 | 
|---|
| 1303 | void QComboTableItem::setCurrentItem( int i )
 | 
|---|
| 1304 | {
 | 
|---|
| 1305 |     QWidget *w = table()->cellWidget( row(), col() );
 | 
|---|
| 1306 |     QComboBox *cb = ::qt_cast<QComboBox*>(w);
 | 
|---|
| 1307 |     if ( cb ) {
 | 
|---|
| 1308 |         cb->setCurrentItem( i );
 | 
|---|
| 1309 |         current = i;
 | 
|---|
| 1310 |         setText( cb->currentText() );
 | 
|---|
| 1311 |     } else {
 | 
|---|
| 1312 |         current = i;
 | 
|---|
| 1313 |         setText( *entries.at( i ) );
 | 
|---|
| 1314 |         table()->updateCell( row(), col() );
 | 
|---|
| 1315 |     }
 | 
|---|
| 1316 | }
 | 
|---|
| 1317 | 
 | 
|---|
| 1318 | /*!
 | 
|---|
| 1319 |     \overload
 | 
|---|
| 1320 | 
 | 
|---|
| 1321 |     Sets the list item whose text is \a s to be the combo table item's
 | 
|---|
| 1322 |     current list item. Does nothing if no list item has the text \a s.
 | 
|---|
| 1323 | 
 | 
|---|
| 1324 |     \sa currentItem()
 | 
|---|
| 1325 | */
 | 
|---|
| 1326 | 
 | 
|---|
| 1327 | void QComboTableItem::setCurrentItem( const QString &s )
 | 
|---|
| 1328 | {
 | 
|---|
| 1329 |     int i = entries.findIndex( s );
 | 
|---|
| 1330 |     if ( i != -1 )
 | 
|---|
| 1331 |         setCurrentItem( i );
 | 
|---|
| 1332 | }
 | 
|---|
| 1333 | 
 | 
|---|
| 1334 | /*!
 | 
|---|
| 1335 |     Returns the index of the combo table item's current list item.
 | 
|---|
| 1336 | 
 | 
|---|
| 1337 |     \sa setCurrentItem()
 | 
|---|
| 1338 | */
 | 
|---|
| 1339 | 
 | 
|---|
| 1340 | int QComboTableItem::currentItem() const
 | 
|---|
| 1341 | {
 | 
|---|
| 1342 |     QWidget *w = table()->cellWidget( row(), col() );
 | 
|---|
| 1343 |     QComboBox *cb = ::qt_cast<QComboBox*>(w);
 | 
|---|
| 1344 |     if ( cb )
 | 
|---|
| 1345 |         return cb->currentItem();
 | 
|---|
| 1346 |     return current;
 | 
|---|
| 1347 | }
 | 
|---|
| 1348 | 
 | 
|---|
| 1349 | /*!
 | 
|---|
| 1350 |     Returns the text of the combo table item's current list item.
 | 
|---|
| 1351 | 
 | 
|---|
| 1352 |     \sa currentItem() text()
 | 
|---|
| 1353 | */
 | 
|---|
| 1354 | 
 | 
|---|
| 1355 | QString QComboTableItem::currentText() const
 | 
|---|
| 1356 | {
 | 
|---|
| 1357 |     QWidget *w = table()->cellWidget( row(), col() );
 | 
|---|
| 1358 |     QComboBox *cb = ::qt_cast<QComboBox*>(w);
 | 
|---|
| 1359 |     if ( cb )
 | 
|---|
| 1360 |         return cb->currentText();
 | 
|---|
| 1361 |     return *entries.at( current );
 | 
|---|
| 1362 | }
 | 
|---|
| 1363 | 
 | 
|---|
| 1364 | /*!
 | 
|---|
| 1365 |     Returns the total number of list items in the combo table item.
 | 
|---|
| 1366 | */
 | 
|---|
| 1367 | 
 | 
|---|
| 1368 | int QComboTableItem::count() const
 | 
|---|
| 1369 | {
 | 
|---|
| 1370 |     QWidget *w = table()->cellWidget( row(), col() );
 | 
|---|
| 1371 |     QComboBox *cb = ::qt_cast<QComboBox*>(w);
 | 
|---|
| 1372 |     if ( cb )
 | 
|---|
| 1373 |         return cb->count();
 | 
|---|
| 1374 |     return (int)entries.count();    //### size_t/int cast
 | 
|---|
| 1375 | }
 | 
|---|
| 1376 | 
 | 
|---|
| 1377 | /*!
 | 
|---|
| 1378 |     Returns the text of the combo's list item at index \a i.
 | 
|---|
| 1379 | 
 | 
|---|
| 1380 |     \sa currentText()
 | 
|---|
| 1381 | */
 | 
|---|
| 1382 | 
 | 
|---|
| 1383 | QString QComboTableItem::text( int i ) const
 | 
|---|
| 1384 | {
 | 
|---|
| 1385 |     QWidget *w = table()->cellWidget( row(), col() );
 | 
|---|
| 1386 |     QComboBox *cb = ::qt_cast<QComboBox*>(w);
 | 
|---|
| 1387 |     if ( cb )
 | 
|---|
| 1388 |         return cb->text( i );
 | 
|---|
| 1389 |     return *entries.at( i );
 | 
|---|
| 1390 | }
 | 
|---|
| 1391 | 
 | 
|---|
| 1392 | /*!
 | 
|---|
| 1393 |     If \a b is TRUE the combo table item can be edited, i.e. the user
 | 
|---|
| 1394 |     may enter a new text item themselves. If \a b is FALSE the user may
 | 
|---|
| 1395 |     may only choose one of the existing items.
 | 
|---|
| 1396 | 
 | 
|---|
| 1397 |     \sa isEditable()
 | 
|---|
| 1398 | */
 | 
|---|
| 1399 | 
 | 
|---|
| 1400 | void QComboTableItem::setEditable( bool b )
 | 
|---|
| 1401 | {
 | 
|---|
| 1402 |     edit = b;
 | 
|---|
| 1403 | }
 | 
|---|
| 1404 | 
 | 
|---|
| 1405 | /*!
 | 
|---|
| 1406 |     Returns TRUE if the user can add their own list items to the
 | 
|---|
| 1407 |     combobox's list of items; otherwise returns FALSE.
 | 
|---|
| 1408 | 
 | 
|---|
| 1409 |     \sa setEditable()
 | 
|---|
| 1410 | */
 | 
|---|
| 1411 | 
 | 
|---|
| 1412 | bool QComboTableItem::isEditable() const
 | 
|---|
| 1413 | {
 | 
|---|
| 1414 |     return edit;
 | 
|---|
| 1415 | }
 | 
|---|
| 1416 | 
 | 
|---|
| 1417 | int QComboTableItem::RTTI = 1;
 | 
|---|
| 1418 | 
 | 
|---|
| 1419 | /*!
 | 
|---|
| 1420 |     \fn int QComboTableItem::rtti() const
 | 
|---|
| 1421 | 
 | 
|---|
| 1422 |     Returns 1.
 | 
|---|
| 1423 | 
 | 
|---|
| 1424 |     Make your derived classes return their own values for rtti()to
 | 
|---|
| 1425 |     distinguish between different table item subclasses. You should
 | 
|---|
| 1426 |     use values greater than 1000, preferably a large random number, to
 | 
|---|
| 1427 |     allow for extensions to this class.
 | 
|---|
| 1428 | 
 | 
|---|
| 1429 | 
 | 
|---|
| 1430 |     \sa QTableItem::rtti()
 | 
|---|
| 1431 | */
 | 
|---|
| 1432 | 
 | 
|---|
| 1433 | int QComboTableItem::rtti() const
 | 
|---|
| 1434 | {
 | 
|---|
| 1435 |     return RTTI;
 | 
|---|
| 1436 | }
 | 
|---|
| 1437 | 
 | 
|---|
| 1438 | /*! \reimp */
 | 
|---|
| 1439 | 
 | 
|---|
| 1440 | QSize QComboTableItem::sizeHint() const
 | 
|---|
| 1441 | {
 | 
|---|
| 1442 |     fakeCombo->insertItem( currentText() );
 | 
|---|
| 1443 |     fakeCombo->setCurrentItem( fakeCombo->count() - 1 );
 | 
|---|
| 1444 |     QSize sh = fakeCombo->sizeHint();
 | 
|---|
| 1445 |     fakeCombo->removeItem( fakeCombo->count() - 1 );
 | 
|---|
| 1446 |     return sh.expandedTo( QApplication::globalStrut() );
 | 
|---|
| 1447 | }
 | 
|---|
| 1448 | 
 | 
|---|
| 1449 | /*!
 | 
|---|
| 1450 |     \class QCheckTableItem
 | 
|---|
| 1451 |     \brief The QCheckTableItem class provides checkboxes in QTables.
 | 
|---|
| 1452 | \if defined(commercial)
 | 
|---|
| 1453 |     It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
 | 
|---|
| 1454 | \endif
 | 
|---|
| 1455 | 
 | 
|---|
| 1456 |     \ingroup advanced
 | 
|---|
| 1457 |     \module table
 | 
|---|
| 1458 | 
 | 
|---|
| 1459 |     A QCheckTableItem is a table item which looks and behaves like a
 | 
|---|
| 1460 |     checkbox. The advantage of using QCheckTableItems rather than real
 | 
|---|
| 1461 |     checkboxes is that a QCheckTableItem uses far less resources than
 | 
|---|
| 1462 |     a real checkbox would in a \l{QTable}. When the cell has the focus
 | 
|---|
| 1463 |     it displays a real checkbox which the user can interact with. When
 | 
|---|
| 1464 |     the cell does not have the focus the cell \e looks like a
 | 
|---|
| 1465 |     checkbox. Pixmaps may not be used in QCheckTableItems.
 | 
|---|
| 1466 | 
 | 
|---|
| 1467 |     QCheckTableItem items have the edit type \c WhenCurrent (see
 | 
|---|
| 1468 |     \l{EditType}).
 | 
|---|
| 1469 | 
 | 
|---|
| 1470 |     To change the checkbox's label use setText(). The checkbox can be
 | 
|---|
| 1471 |     checked and unchecked with setChecked() and its state retrieved
 | 
|---|
| 1472 |     using isChecked().
 | 
|---|
| 1473 | 
 | 
|---|
| 1474 |     To populate a table cell with a QCheckTableItem use
 | 
|---|
| 1475 |     QTable::setItem().
 | 
|---|
| 1476 | 
 | 
|---|
| 1477 |     QCheckTableItems can be distinguished from \l{QTableItem}s and
 | 
|---|
| 1478 |     \l{QComboTableItem}s using their Run Time Type Identification
 | 
|---|
| 1479 |     (rtti) value.
 | 
|---|
| 1480 | 
 | 
|---|
| 1481 |     \img qtableitems.png Table Items
 | 
|---|
| 1482 | 
 | 
|---|
| 1483 |     \sa rtti() EditType QComboTableItem QTableItem QCheckBox
 | 
|---|
| 1484 | */
 | 
|---|
| 1485 | 
 | 
|---|
| 1486 | /*!
 | 
|---|
| 1487 |     Creates a QCheckTableItem with an \l{EditType} of \c WhenCurrent
 | 
|---|
| 1488 |     as a child of \a table. The checkbox is initially unchecked and
 | 
|---|
| 1489 |     its label is set to the string \a txt.
 | 
|---|
| 1490 | */
 | 
|---|
| 1491 | 
 | 
|---|
| 1492 | QCheckTableItem::QCheckTableItem( QTable *table, const QString &txt )
 | 
|---|
| 1493 |     : QTableItem( table, WhenCurrent, txt ), checked( FALSE )
 | 
|---|
| 1494 | {
 | 
|---|
| 1495 | }
 | 
|---|
| 1496 | 
 | 
|---|
| 1497 | /*! \reimp */
 | 
|---|
| 1498 | 
 | 
|---|
| 1499 | void QCheckTableItem::setText( const QString &t )
 | 
|---|
| 1500 | {
 | 
|---|
| 1501 |     QTableItem::setText( t );
 | 
|---|
| 1502 |     QWidget *w = table()->cellWidget( row(), col() );
 | 
|---|
| 1503 |     QCheckBox *cb = ::qt_cast<QCheckBox*>(w);
 | 
|---|
| 1504 |     if ( cb )
 | 
|---|
| 1505 |         cb->setText( t );
 | 
|---|
| 1506 | }
 | 
|---|
| 1507 | 
 | 
|---|
| 1508 | 
 | 
|---|
| 1509 | /*! \reimp */
 | 
|---|
| 1510 | 
 | 
|---|
| 1511 | QWidget *QCheckTableItem::createEditor() const
 | 
|---|
| 1512 | {
 | 
|---|
| 1513 |     // create an editor - a combobox in our case
 | 
|---|
| 1514 |     ( (QCheckTableItem*)this )->cb = new QCheckBox( table()->viewport(), "qt_editor_checkbox" );
 | 
|---|
| 1515 |     cb->setChecked( checked );
 | 
|---|
| 1516 |     cb->setText( text() );
 | 
|---|
| 1517 |     cb->setBackgroundColor( table()->viewport()->backgroundColor() );
 | 
|---|
| 1518 |     QObject::connect( cb, SIGNAL( toggled(bool) ), table(), SLOT( doValueChanged() ) );
 | 
|---|
| 1519 |     return cb;
 | 
|---|
| 1520 | }
 | 
|---|
| 1521 | 
 | 
|---|
| 1522 | /*! \reimp */
 | 
|---|
| 1523 | 
 | 
|---|
| 1524 | void QCheckTableItem::setContentFromEditor( QWidget *w )
 | 
|---|
| 1525 | {
 | 
|---|
| 1526 |     QCheckBox *cb = ::qt_cast<QCheckBox*>(w);
 | 
|---|
| 1527 |     if ( cb )
 | 
|---|
| 1528 |         checked = cb->isChecked();
 | 
|---|
| 1529 | }
 | 
|---|
| 1530 | 
 | 
|---|
| 1531 | /*! \reimp */
 | 
|---|
| 1532 | 
 | 
|---|
| 1533 | void QCheckTableItem::paint( QPainter *p, const QColorGroup &cg,
 | 
|---|
| 1534 |                                 const QRect &cr, bool selected )
 | 
|---|
| 1535 | {
 | 
|---|
| 1536 |     p->fillRect( 0, 0, cr.width(), cr.height(),
 | 
|---|
| 1537 |                  selected ? cg.brush( QColorGroup::Highlight )
 | 
|---|
| 1538 |                           : cg.brush( QColorGroup::Base ) );
 | 
|---|
| 1539 | 
 | 
|---|
| 1540 |     int w = cr.width();
 | 
|---|
| 1541 |     int h = cr.height();
 | 
|---|
| 1542 |     QSize sz = QSize( table()->style().pixelMetric( QStyle::PM_IndicatorWidth ),
 | 
|---|
| 1543 |                       table()->style().pixelMetric( QStyle::PM_IndicatorHeight ) );
 | 
|---|
| 1544 |     QColorGroup c( cg );
 | 
|---|
| 1545 |     c.setBrush( QColorGroup::Background, c.brush( QColorGroup::Base ) );
 | 
|---|
| 1546 |     QStyle::SFlags flags = QStyle::Style_Default;
 | 
|---|
| 1547 |     if(isEnabled())
 | 
|---|
| 1548 |         flags |= QStyle::Style_Enabled;
 | 
|---|
| 1549 |     if ( checked )
 | 
|---|
| 1550 |         flags |= QStyle::Style_On;
 | 
|---|
| 1551 |     else
 | 
|---|
| 1552 |         flags |= QStyle::Style_Off;
 | 
|---|
| 1553 |     if ( isEnabled() && table()->isEnabled() )
 | 
|---|
| 1554 |         flags |= QStyle::Style_Enabled;
 | 
|---|
| 1555 | 
 | 
|---|
| 1556 |     table()->style().drawPrimitive( QStyle::PE_Indicator, p,
 | 
|---|
| 1557 |                                     QRect( 0, ( cr.height() - sz.height() ) / 2, sz.width(), sz.height() ), c, flags );
 | 
|---|
| 1558 |     int x = sz.width() + 6;
 | 
|---|
| 1559 |     w = w - x;
 | 
|---|
| 1560 |     if ( selected )
 | 
|---|
| 1561 |         p->setPen( cg.highlightedText() );
 | 
|---|
| 1562 |     else
 | 
|---|
| 1563 |         p->setPen( cg.text() );
 | 
|---|
| 1564 |     p->drawText( x, 0, w, h, wordWrap() ? ( alignment() | WordBreak ) : alignment(), text() );
 | 
|---|
| 1565 | }
 | 
|---|
| 1566 | 
 | 
|---|
| 1567 | /*!
 | 
|---|
| 1568 |     If \a b is TRUE the checkbox is checked; if \a b is FALSE the
 | 
|---|
| 1569 |     checkbox is unchecked.
 | 
|---|
| 1570 | 
 | 
|---|
| 1571 |     \sa isChecked()
 | 
|---|
| 1572 | */
 | 
|---|
| 1573 | 
 | 
|---|
| 1574 | void QCheckTableItem::setChecked( bool b )
 | 
|---|
| 1575 | {
 | 
|---|
| 1576 |     checked = b;
 | 
|---|
| 1577 |     table()->updateCell( row(), col() );
 | 
|---|
| 1578 |     QWidget *w = table()->cellWidget( row(), col() );
 | 
|---|
| 1579 |     QCheckBox *cb = ::qt_cast<QCheckBox*>(w);
 | 
|---|
| 1580 |     if ( cb )
 | 
|---|
| 1581 |         cb->setChecked( b );
 | 
|---|
| 1582 | }
 | 
|---|
| 1583 | 
 | 
|---|
| 1584 | /*!
 | 
|---|
| 1585 |     Returns TRUE if the checkbox table item is checked; otherwise
 | 
|---|
| 1586 |     returns FALSE.
 | 
|---|
| 1587 | 
 | 
|---|
| 1588 |     \sa setChecked()
 | 
|---|
| 1589 | */
 | 
|---|
| 1590 | 
 | 
|---|
| 1591 | bool QCheckTableItem::isChecked() const
 | 
|---|
| 1592 | {
 | 
|---|
| 1593 |     // #### why was this next line here. It must not be here, as
 | 
|---|
| 1594 |     // #### people want to call isChecked() from within paintCell()
 | 
|---|
| 1595 |     // #### and end up in an infinite loop that way
 | 
|---|
| 1596 |     // table()->updateCell( row(), col() );
 | 
|---|
| 1597 |     QWidget *w = table()->cellWidget( row(), col() );
 | 
|---|
| 1598 |     QCheckBox *cb = ::qt_cast<QCheckBox*>(w);
 | 
|---|
| 1599 |     if ( cb )
 | 
|---|
| 1600 |         return cb->isChecked();
 | 
|---|
| 1601 |     return checked;
 | 
|---|
| 1602 | }
 | 
|---|
| 1603 | 
 | 
|---|
| 1604 | int QCheckTableItem::RTTI = 2;
 | 
|---|
| 1605 | 
 | 
|---|
| 1606 | /*!
 | 
|---|
| 1607 |     \fn int QCheckTableItem::rtti() const
 | 
|---|
| 1608 | 
 | 
|---|
| 1609 |     Returns 2.
 | 
|---|
| 1610 | 
 | 
|---|
| 1611 |     Make your derived classes return their own values for rtti()to
 | 
|---|
| 1612 |     distinguish between different table item subclasses. You should
 | 
|---|
| 1613 |     use values greater than 1000, preferably a large random number, to
 | 
|---|
| 1614 |     allow for extensions to this class.
 | 
|---|
| 1615 | 
 | 
|---|
| 1616 |     \sa QTableItem::rtti()
 | 
|---|
| 1617 | */
 | 
|---|
| 1618 | 
 | 
|---|
| 1619 | int QCheckTableItem::rtti() const
 | 
|---|
| 1620 | {
 | 
|---|
| 1621 |     return RTTI;
 | 
|---|
| 1622 | }
 | 
|---|
| 1623 | 
 | 
|---|
| 1624 | /*! \reimp */
 | 
|---|
| 1625 | 
 | 
|---|
| 1626 | QSize QCheckTableItem::sizeHint() const
 | 
|---|
| 1627 | {
 | 
|---|
| 1628 |     QSize sz = QSize( table()->style().pixelMetric( QStyle::PM_IndicatorWidth ),
 | 
|---|
| 1629 |                       table()->style().pixelMetric( QStyle::PM_IndicatorHeight ) );
 | 
|---|
| 1630 |     sz.setWidth( sz.width() + 6 );
 | 
|---|
| 1631 |     QSize sh( QTableItem::sizeHint() );
 | 
|---|
| 1632 |     return QSize( sh.width() + sz.width(), QMAX( sh.height(), sz.height() ) ).
 | 
|---|
| 1633 |         expandedTo( QApplication::globalStrut() );
 | 
|---|
| 1634 | }
 | 
|---|
| 1635 | 
 | 
|---|
| 1636 | /*! \file table/small-table-demo/main.cpp */
 | 
|---|
| 1637 | /*! \file table/bigtable/main.cpp */
 | 
|---|
| 1638 | /*! \file table/statistics/statistics.cpp */
 | 
|---|
| 1639 | 
 | 
|---|
| 1640 | /*!
 | 
|---|
| 1641 |     \class QTable
 | 
|---|
| 1642 |     \brief The QTable class provides a flexible editable table widget.
 | 
|---|
| 1643 | \if defined(commercial)
 | 
|---|
| 1644 |     It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
 | 
|---|
| 1645 | \endif
 | 
|---|
| 1646 | 
 | 
|---|
| 1647 |     \mainclass
 | 
|---|
| 1648 |     \ingroup advanced
 | 
|---|
| 1649 |     \module table
 | 
|---|
| 1650 | 
 | 
|---|
| 1651 |     QTable is easy to use, although it does have a large API because
 | 
|---|
| 1652 |     of the comprehensive functionality that it provides. QTable
 | 
|---|
| 1653 |     includes functions for manipulating \link #headers
 | 
|---|
| 1654 |     headers\endlink, \link #columnsrows rows and columns\endlink,
 | 
|---|
| 1655 |     \link #cells cells\endlink and \link #selections
 | 
|---|
| 1656 |     selections\endlink. QTable also provides in-place editing and
 | 
|---|
| 1657 |     \link dnd.html drag and drop\endlink, as well as a useful set of
 | 
|---|
| 1658 |     \link #signals signals\endlink. QTable efficiently supports very
 | 
|---|
| 1659 |     large tables, for example, tables one million by one million cells
 | 
|---|
| 1660 |     are perfectly possible. QTable is economical with memory, using
 | 
|---|
| 1661 |     none for unused cells.
 | 
|---|
| 1662 | 
 | 
|---|
| 1663 |     \code
 | 
|---|
| 1664 |     QTable *table = new QTable( 100, 250, this );
 | 
|---|
| 1665 |     table->setPixmap( 3, 2, pix );
 | 
|---|
| 1666 |     table->setText( 3, 2, "A pixmap" );
 | 
|---|
| 1667 |     \endcode
 | 
|---|
| 1668 | 
 | 
|---|
| 1669 |     The first line constructs the table specifying its size in rows
 | 
|---|
| 1670 |     and columns. We then insert a pixmap and some text into the \e
 | 
|---|
| 1671 |     same \link #cells cell\endlink, with the pixmap appearing to the
 | 
|---|
| 1672 |     left of the text. QTable cells can be populated with
 | 
|---|
| 1673 |     \l{QTableItem}s, \l{QComboTableItem}s or by \l{QCheckTableItem}s.
 | 
|---|
| 1674 |     By default a vertical header appears at the left of the table
 | 
|---|
| 1675 |     showing row numbers and a horizontal header appears at the top of
 | 
|---|
| 1676 |     the table showing column numbers. (The numbers displayed start at
 | 
|---|
| 1677 |     1, although row and column numbers within QTable begin at 0.)
 | 
|---|
| 1678 | 
 | 
|---|
| 1679 |     If you want to use mouse tracking call setMouseTracking( TRUE ) on
 | 
|---|
| 1680 |     the \e viewport; (see \link qscrollview.html#allviews
 | 
|---|
| 1681 |     QScrollView\endlink).
 | 
|---|
| 1682 | 
 | 
|---|
| 1683 |     \img qtableitems.png Table Items
 | 
|---|
| 1684 | 
 | 
|---|
| 1685 |     \target headers
 | 
|---|
| 1686 |     \section1 Headers
 | 
|---|
| 1687 | 
 | 
|---|
| 1688 |     QTable supports a header column, e.g. to display row numbers, and
 | 
|---|
| 1689 |     a header row, e.g to display column titles. To set row or column
 | 
|---|
| 1690 |     labels use QHeader::setLabel() on the pointers returned by
 | 
|---|
| 1691 |     verticalHeader() and horizontalHeader() respectively. The vertical
 | 
|---|
| 1692 |     header is displayed within the table's left margin whose width is
 | 
|---|
| 1693 |     set with setLeftMargin(). The horizontal header is displayed
 | 
|---|
| 1694 |     within the table's top margin whose height is set with
 | 
|---|
| 1695 |     setTopMargin(). The table's grid can be switched off with
 | 
|---|
| 1696 |     setShowGrid(). If you want to hide a horizontal header call
 | 
|---|
| 1697 |     hide(), and call setTopMargin( 0 ) so that the area the header
 | 
|---|
| 1698 |     would have occupied is reduced to zero size.
 | 
|---|
| 1699 | 
 | 
|---|
| 1700 |     Header labels are indexed via their section numbers. Note that the
 | 
|---|
| 1701 |     default behavior of QHeader regarding section numbers is overriden
 | 
|---|
| 1702 |     for QTable. See the explanation below in the Rows and Columns
 | 
|---|
| 1703 |     section in the discussion of moving columns and rows.
 | 
|---|
| 1704 | 
 | 
|---|
| 1705 |     \target columnsrows
 | 
|---|
| 1706 |     \section1 Rows and Columns
 | 
|---|
| 1707 | 
 | 
|---|
| 1708 |     Row and column sizes are set with setRowHeight() and
 | 
|---|
| 1709 |     setColumnWidth(). If you want a row high enough to show the
 | 
|---|
| 1710 |     tallest item in its entirety, use adjustRow(). Similarly, to make
 | 
|---|
| 1711 |     a column wide enough to show the widest item use adjustColumn().
 | 
|---|
| 1712 |     If you want the row height and column width to adjust
 | 
|---|
| 1713 |     automatically as the height and width of the table changes use
 | 
|---|
| 1714 |     setRowStretchable() and setColumnStretchable().
 | 
|---|
| 1715 | 
 | 
|---|
| 1716 |     Rows and columns can be hidden and shown with hideRow(),
 | 
|---|
| 1717 |     hideColumn(), showRow() and showColumn(). New rows and columns are
 | 
|---|
| 1718 |     inserted using insertRows() and insertColumns(). Additional rows
 | 
|---|
| 1719 |     and columns are added at the  bottom (rows) or right (columns) if
 | 
|---|
| 1720 |     you set setNumRows() or setNumCols() to be larger than numRows()
 | 
|---|
| 1721 |     or numCols(). Existing rows and columns are removed with
 | 
|---|
| 1722 |     removeRow() and removeColumn(). Multiple rows and columns can be
 | 
|---|
| 1723 |     removed with removeRows() and removeColumns().
 | 
|---|
| 1724 | 
 | 
|---|
| 1725 |     Rows and columns can be set to be moveable using
 | 
|---|
| 1726 |     rowMovingEnabled() and columnMovingEnabled(). The user can drag
 | 
|---|
| 1727 |     them to reorder them holding down the Ctrl key and dragging the
 | 
|---|
| 1728 |     mouse. For performance reasons, the default behavior of QHeader
 | 
|---|
| 1729 |     section numbers is overridden by QTable. Currently in QTable, when
 | 
|---|
| 1730 |     a row or column is dragged and reordered, the section number is
 | 
|---|
| 1731 |     also changed to its new position. Therefore, there is no
 | 
|---|
| 1732 |     difference between the section and the index fields in QHeader.
 | 
|---|
| 1733 |     The QTable QHeader classes do not provide a mechanism for indexing
 | 
|---|
| 1734 |     independently of the user interface ordering.
 | 
|---|
| 1735 | 
 | 
|---|
| 1736 |     The table can be sorted using sortColumn(). Users can sort a
 | 
|---|
| 1737 |     column by clicking its header if setSorting() is set to TRUE. Rows
 | 
|---|
| 1738 |     can be swapped with swapRows(), columns with swapColumns() and
 | 
|---|
| 1739 |     cells with swapCells().
 | 
|---|
| 1740 | 
 | 
|---|
| 1741 |     For editable tables (see setReadOnly()) you can set the read-only
 | 
|---|
| 1742 |     property of individual rows and columns with setRowReadOnly() and
 | 
|---|
| 1743 |     setColumnReadOnly(). (Whether a cell is editable or read-only
 | 
|---|
| 1744 |     depends on these settings and the cell's \link
 | 
|---|
| 1745 |     qtableitem.html#wheneditable QTableItem::EditType\endlink.)
 | 
|---|
| 1746 | 
 | 
|---|
| 1747 |     The row and column which have the focus are returned by
 | 
|---|
| 1748 |     currentRow() and currentColumn() respectively.
 | 
|---|
| 1749 | 
 | 
|---|
| 1750 |     Although many QTable functions operate in terms of rows and
 | 
|---|
| 1751 |     columns the indexOf() function returns a single integer
 | 
|---|
| 1752 |     identifying a particular cell.
 | 
|---|
| 1753 | 
 | 
|---|
| 1754 |     \target cells
 | 
|---|
| 1755 |     \section1 Cells
 | 
|---|
| 1756 | 
 | 
|---|
| 1757 |     All of a QTable's cells are empty when the table is constructed.
 | 
|---|
| 1758 | 
 | 
|---|
| 1759 |     There are two approaches to populating the table's cells. The
 | 
|---|
| 1760 |     first and simplest approach is to use QTableItems or QTableItem
 | 
|---|
| 1761 |     subclasses. The second approach doesn't use QTableItems at all
 | 
|---|
| 1762 |     which is useful for very large sparse tables but requires you to
 | 
|---|
| 1763 |     reimplement a number of functions. We'll look at each approach in
 | 
|---|
| 1764 |     turn.
 | 
|---|
| 1765 | 
 | 
|---|
| 1766 |     To put a string in a cell use setText(). This function will create
 | 
|---|
| 1767 |     a new QTableItem for the cell if one doesn't already exist, and
 | 
|---|
| 1768 |     displays the text in it. By default the table item's widget will
 | 
|---|
| 1769 |     be a QLineEdit. A pixmap may be put in a cell with setPixmap(),
 | 
|---|
| 1770 |     which also creates a table item if required. A cell may contain \e
 | 
|---|
| 1771 |     both a pixmap and text; the pixmap is displayed to the left of the
 | 
|---|
| 1772 |     text. Another approach is to construct a QTableItem or QTableItem
 | 
|---|
| 1773 |     subclass, set its properties, then insert it into a cell with
 | 
|---|
| 1774 |     setItem().
 | 
|---|
| 1775 | 
 | 
|---|
| 1776 |     If you want cells which contain comboboxes use the QComboTableItem
 | 
|---|
| 1777 |     class. Similarly if you require cells containing checkboxes use
 | 
|---|
| 1778 |     the QCheckTableItem class. These table items look and behave just
 | 
|---|
| 1779 |     like the combobox or checkbox widgets but consume far less memory.
 | 
|---|
| 1780 | 
 | 
|---|
| 1781 |     \quotefile table/small-table-demo/main.cpp
 | 
|---|
| 1782 |     \skipto int j
 | 
|---|
| 1783 |     \printuntil QCheckTableItem
 | 
|---|
| 1784 |     In the example above we create a column of QCheckTableItems and
 | 
|---|
| 1785 |     insert them into the table using setItem().
 | 
|---|
| 1786 | 
 | 
|---|
| 1787 |     QTable takes ownership of its QTableItems and will delete them
 | 
|---|
| 1788 |     when the table itself is destroyed. You can take ownership of a
 | 
|---|
| 1789 |     table item using takeItem() which you use to move a cell's
 | 
|---|
| 1790 |     contents from one cell to another, either within the same table,
 | 
|---|
| 1791 |     or from one table to another. (See also, swapCells()).
 | 
|---|
| 1792 | 
 | 
|---|
| 1793 |     In-place editing of the text in QTableItems, and the values in
 | 
|---|
| 1794 |     QComboTableItems and QCheckTableItems works automatically. Cells
 | 
|---|
| 1795 |     may be editable or read-only, see \link
 | 
|---|
| 1796 |     qtableitem.html#wheneditable QTableItem::EditType\endlink. If you
 | 
|---|
| 1797 |     want fine control over editing see beginEdit() and endEdit().
 | 
|---|
| 1798 | 
 | 
|---|
| 1799 |     The contents of a cell can be retrieved as a QTableItem using
 | 
|---|
| 1800 |     item(), or as a string with text() or as a pixmap (if there is
 | 
|---|
| 1801 |     one) with pixmap(). A cell's bounding rectangle is given by
 | 
|---|
| 1802 |     cellGeometry(). Use updateCell() to repaint a cell, for example to
 | 
|---|
| 1803 |     clear away a cell's visual representation after it has been
 | 
|---|
| 1804 |     deleted with clearCell(). The table can be forced to scroll to
 | 
|---|
| 1805 |     show a particular cell with ensureCellVisible(). The isSelected()
 | 
|---|
| 1806 |     function indicates if a cell is selected.
 | 
|---|
| 1807 | 
 | 
|---|
| 1808 |     It is possible to use your own widget as a cell's widget using
 | 
|---|
| 1809 |     setCellWidget(), but subclassing QTableItem might be a simpler
 | 
|---|
| 1810 |     approach. The cell's widget (if there is one) can be removed with
 | 
|---|
| 1811 |     clearCellWidget().
 | 
|---|
| 1812 | 
 | 
|---|
| 1813 |     \keyword notes on large tables
 | 
|---|
| 1814 |     \target bigtables
 | 
|---|
| 1815 |     \section2 Large tables
 | 
|---|
| 1816 | 
 | 
|---|
| 1817 |     For large, sparse, tables using QTableItems or other widgets is
 | 
|---|
| 1818 |     inefficient. The solution is to \e draw the cell as it should
 | 
|---|
| 1819 |     appear and to create and destroy cell editors on demand.
 | 
|---|
| 1820 | 
 | 
|---|
| 1821 |     This approach requires that you reimplement various functions.
 | 
|---|
| 1822 |     Reimplement paintCell() to display your data, and createEditor()
 | 
|---|
| 1823 |     and setCellContentFromEditor() to support in-place editing. It
 | 
|---|
| 1824 |     is very important to reimplement resizeData() to have no
 | 
|---|
| 1825 |     functionality, to prevent QTable from attempting to create a huge
 | 
|---|
| 1826 |     array. You will also need to reimplement item(), setItem(),
 | 
|---|
| 1827 |     takeItem(), clearCell(), and insertWidget(), cellWidget() and
 | 
|---|
| 1828 |     clearCellWidget(). In almost every circumstance (for sorting,
 | 
|---|
| 1829 |     removing and inserting columns and rows, etc.), you also need
 | 
|---|
| 1830 |     to reimplement swapRows(), swapCells() and swapColumns(), including
 | 
|---|
| 1831 |     header handling.
 | 
|---|
| 1832 | 
 | 
|---|
| 1833 |     If you represent active cells with a dictionary of QTableItems and
 | 
|---|
| 1834 |     QWidgets, i.e. only store references to cells that are actually
 | 
|---|
| 1835 |     used, many of the functions can be implemented with a single line
 | 
|---|
| 1836 |     of code. (See the \l table/bigtable/main.cpp example.)
 | 
|---|
| 1837 | 
 | 
|---|
| 1838 |     For more information on cells see the QTableItem documenation.
 | 
|---|
| 1839 | 
 | 
|---|
| 1840 |     \target selections
 | 
|---|
| 1841 |     \section1 Selections
 | 
|---|
| 1842 | 
 | 
|---|
| 1843 |     QTable's support single selection, multi-selection (multiple
 | 
|---|
| 1844 |     cells) or no selection. The selection mode is set with
 | 
|---|
| 1845 |     setSelectionMode(). Use isSelected() to determine if a particular
 | 
|---|
| 1846 |     cell is selected, and isRowSelected() and isColumnSelected() to
 | 
|---|
| 1847 |     see if a row or column is selected.
 | 
|---|
| 1848 | 
 | 
|---|
| 1849 |     QTable's support many simultaneous selections. You can
 | 
|---|
| 1850 |     programmatically select cells with addSelection(). The number of
 | 
|---|
| 1851 |     selections is given by numSelections(). The current selection is
 | 
|---|
| 1852 |     returned by currentSelection(). You can remove a selection with
 | 
|---|
| 1853 |     removeSelection() and remove all selections with
 | 
|---|
| 1854 |     clearSelection(). Selections are QTableSelection objects.
 | 
|---|
| 1855 | 
 | 
|---|
| 1856 |     To easily add a new selection use selectCells(), selectRow() or
 | 
|---|
| 1857 |     selectColumn().
 | 
|---|
| 1858 | 
 | 
|---|
| 1859 |     Alternatively, use addSelection() to add new selections using
 | 
|---|
| 1860 |     QTableSelection objects. The advantage of using QTableSelection
 | 
|---|
| 1861 |     objects is that you can call QTableSelection::expandTo() to resize
 | 
|---|
| 1862 |     the selection and can query and compare them.
 | 
|---|
| 1863 | 
 | 
|---|
| 1864 |     The number of selections is given by numSelections(). The current
 | 
|---|
| 1865 |     selection is returned by currentSelection(). You can remove a
 | 
|---|
| 1866 |     selection with removeSelection() and remove all selections with
 | 
|---|
| 1867 |     clearSelection().
 | 
|---|
| 1868 | 
 | 
|---|
| 1869 |     \target signals
 | 
|---|
| 1870 |     \section1 Signals
 | 
|---|
| 1871 | 
 | 
|---|
| 1872 |     When the user clicks a cell the currentChanged() signal is
 | 
|---|
| 1873 |     emitted. You can also connect to the lower level clicked(),
 | 
|---|
| 1874 |     doubleClicked() and pressed() signals. If the user changes the
 | 
|---|
| 1875 |     selection the selectionChanged() signal is emitted; similarly if
 | 
|---|
| 1876 |     the user changes a cell's value the valueChanged() signal is
 | 
|---|
| 1877 |     emitted. If the user right-clicks (or presses the appropriate
 | 
|---|
| 1878 |     platform-specific key sequence) the contextMenuRequested() signal
 | 
|---|
| 1879 |     is emitted. If the user drops a drag and drop object the dropped()
 | 
|---|
| 1880 |     signal is emitted with the drop event.
 | 
|---|
| 1881 | */
 | 
|---|
| 1882 | 
 | 
|---|
| 1883 | /*!
 | 
|---|
| 1884 |     \fn void QTable::currentChanged( int row, int col )
 | 
|---|
| 1885 | 
 | 
|---|
| 1886 |     This signal is emitted when the current cell has changed to \a
 | 
|---|
| 1887 |     row, \a col.
 | 
|---|
| 1888 | */
 | 
|---|
| 1889 | 
 | 
|---|
| 1890 | /*!
 | 
|---|
| 1891 |     \fn void QTable::valueChanged( int row, int col )
 | 
|---|
| 1892 | 
 | 
|---|
| 1893 |     This signal is emitted when the user changed the value in the cell
 | 
|---|
| 1894 |     at \a row, \a col.
 | 
|---|
| 1895 | */
 | 
|---|
| 1896 | 
 | 
|---|
| 1897 | /*!
 | 
|---|
| 1898 |     \fn int QTable::currentRow() const
 | 
|---|
| 1899 | 
 | 
|---|
| 1900 |     Returns the current row.
 | 
|---|
| 1901 | 
 | 
|---|
| 1902 |     \sa currentColumn()
 | 
|---|
| 1903 | */
 | 
|---|
| 1904 | 
 | 
|---|
| 1905 | /*!
 | 
|---|
| 1906 |     \fn int QTable::currentColumn() const
 | 
|---|
| 1907 | 
 | 
|---|
| 1908 |     Returns the current column.
 | 
|---|
| 1909 | 
 | 
|---|
| 1910 |     \sa currentRow()
 | 
|---|
| 1911 | */
 | 
|---|
| 1912 | 
 | 
|---|
| 1913 | /*!
 | 
|---|
| 1914 |     \enum QTable::EditMode
 | 
|---|
| 1915 | 
 | 
|---|
| 1916 |     \value NotEditing  No cell is currently being edited.
 | 
|---|
| 1917 | 
 | 
|---|
| 1918 |     \value Editing  A cell is currently being edited. The editor was
 | 
|---|
| 1919 |     initialised with the cell's contents.
 | 
|---|
| 1920 | 
 | 
|---|
| 1921 |     \value Replacing  A cell is currently being edited. The editor was
 | 
|---|
| 1922 |     not initialised with the cell's contents.
 | 
|---|
| 1923 | */
 | 
|---|
| 1924 | 
 | 
|---|
| 1925 | /*!
 | 
|---|
| 1926 |     \enum QTable::SelectionMode
 | 
|---|
| 1927 | 
 | 
|---|
| 1928 |     \value NoSelection No cell can be selected by the user.
 | 
|---|
| 1929 | 
 | 
|---|
| 1930 |     \value Single The user may only select a single range of cells.
 | 
|---|
| 1931 | 
 | 
|---|
| 1932 |     \value Multi The user may select multiple ranges of cells.
 | 
|---|
| 1933 | 
 | 
|---|
| 1934 |     \value SingleRow The user may select one row at once.
 | 
|---|
| 1935 | 
 | 
|---|
| 1936 |     \value MultiRow The user may select multiple rows.
 | 
|---|
| 1937 | */
 | 
|---|
| 1938 | 
 | 
|---|
| 1939 | /*!
 | 
|---|
| 1940 |     \enum QTable::FocusStyle
 | 
|---|
| 1941 | 
 | 
|---|
| 1942 |     Specifies how the current cell (focus cell) is drawn.
 | 
|---|
| 1943 | 
 | 
|---|
| 1944 |     \value FollowStyle The current cell is drawn according to the
 | 
|---|
| 1945 |     current style and the cell's background is also drawn selected, if
 | 
|---|
| 1946 |     the current cell is within a selection
 | 
|---|
| 1947 | 
 | 
|---|
| 1948 |     \value SpreadSheet The current cell is drawn as in a spreadsheet.
 | 
|---|
| 1949 |     This means, it is signified by a black rectangle around the cell,
 | 
|---|
| 1950 |     and the background of the current cell is always drawn with the
 | 
|---|
| 1951 |     widget's base color - even when selected.
 | 
|---|
| 1952 | 
 | 
|---|
| 1953 | */
 | 
|---|
| 1954 | 
 | 
|---|
| 1955 | /*!
 | 
|---|
| 1956 |     \fn void QTable::clicked( int row, int col, int button, const QPoint &mousePos )
 | 
|---|
| 1957 | 
 | 
|---|
| 1958 |     This signal is emitted when mouse button \a button is clicked. The
 | 
|---|
| 1959 |     cell where the event took place is at \a row, \a col, and the
 | 
|---|
| 1960 |     mouse's position is in \a mousePos.
 | 
|---|
| 1961 | */
 | 
|---|
| 1962 | 
 | 
|---|
| 1963 | /*!
 | 
|---|
| 1964 |     \fn void QTable::doubleClicked( int row, int col, int button, const QPoint &mousePos )
 | 
|---|
| 1965 | 
 | 
|---|
| 1966 |     This signal is emitted when mouse button \a button is
 | 
|---|
| 1967 |     double-clicked. The cell where the event took place is at \a row,
 | 
|---|
| 1968 |     \a col, and the mouse's position is in \a mousePos.
 | 
|---|
| 1969 | */
 | 
|---|
| 1970 | 
 | 
|---|
| 1971 | /*!
 | 
|---|
| 1972 |     \fn void QTable::pressed( int row, int col, int button, const QPoint &mousePos )
 | 
|---|
| 1973 | 
 | 
|---|
| 1974 |     This signal is emitted when mouse button \a button is pressed. The
 | 
|---|
| 1975 |     cell where the event took place is at \a row, \a col, and the
 | 
|---|
| 1976 |     mouse's position is in \a mousePos.
 | 
|---|
| 1977 | */
 | 
|---|
| 1978 | 
 | 
|---|
| 1979 | /*!
 | 
|---|
| 1980 |     \fn void QTable::selectionChanged()
 | 
|---|
| 1981 | 
 | 
|---|
| 1982 |     This signal is emitted whenever a selection changes.
 | 
|---|
| 1983 | 
 | 
|---|
| 1984 |     \sa QTableSelection
 | 
|---|
| 1985 | */
 | 
|---|
| 1986 | 
 | 
|---|
| 1987 | /*!
 | 
|---|
| 1988 |     \fn void QTable::contextMenuRequested( int row, int col, const QPoint & pos )
 | 
|---|
| 1989 | 
 | 
|---|
| 1990 |     This signal is emitted when the user invokes a context menu with
 | 
|---|
| 1991 |     the right mouse button (or with a system-specific keypress). The
 | 
|---|
| 1992 |     cell where the event took place is at \a row, \a col. \a pos is
 | 
|---|
| 1993 |     the position where the context menu will appear in the global
 | 
|---|
| 1994 |     coordinate system.
 | 
|---|
| 1995 | */
 | 
|---|
| 1996 | 
 | 
|---|
| 1997 | /*!
 | 
|---|
| 1998 |     Creates an empty table object called \a name as a child of \a
 | 
|---|
| 1999 |     parent.
 | 
|---|
| 2000 | 
 | 
|---|
| 2001 |     Call setNumRows() and setNumCols() to set the table size before
 | 
|---|
| 2002 |     populating the table if you're using QTableItems.
 | 
|---|
| 2003 | 
 | 
|---|
| 2004 |     \sa QWidget::clearWFlags() Qt::WidgetFlags
 | 
|---|
| 2005 | */
 | 
|---|
| 2006 | 
 | 
|---|
| 2007 | QTable::QTable( QWidget *parent, const char *name )
 | 
|---|
| 2008 |     : QScrollView( parent, name, WNoAutoErase | WStaticContents ),
 | 
|---|
| 2009 |       leftHeader( 0 ), topHeader( 0 ),
 | 
|---|
| 2010 |       currentSel( 0 ), lastSortCol( -1 ), sGrid( TRUE ), mRows( FALSE ), mCols( FALSE ),
 | 
|---|
| 2011 |       asc( TRUE ), doSort( TRUE ), readOnly( FALSE )
 | 
|---|
| 2012 | {
 | 
|---|
| 2013 |     init( 0, 0 );
 | 
|---|
| 2014 | }
 | 
|---|
| 2015 | 
 | 
|---|
| 2016 | /*!
 | 
|---|
| 2017 |     Constructs an empty table called \a name with \a numRows rows and
 | 
|---|
| 2018 |     \a numCols columns. The table is a child of \a parent.
 | 
|---|
| 2019 | 
 | 
|---|
| 2020 |     If you're using \l{QTableItem}s to populate the table's cells, you
 | 
|---|
| 2021 |     can create QTableItem, QComboTableItem and QCheckTableItem items
 | 
|---|
| 2022 |     and insert them into the table using setItem(). (See the notes on
 | 
|---|
| 2023 |     large tables for an alternative to using QTableItems.)
 | 
|---|
| 2024 | 
 | 
|---|
| 2025 |     \sa QWidget::clearWFlags() Qt::WidgetFlags
 | 
|---|
| 2026 | */
 | 
|---|
| 2027 | 
 | 
|---|
| 2028 | QTable::QTable( int numRows, int numCols, QWidget *parent, const char *name )
 | 
|---|
| 2029 |     : QScrollView( parent, name, WNoAutoErase | WStaticContents ),
 | 
|---|
| 2030 |       leftHeader( 0 ), topHeader( 0 ),
 | 
|---|
| 2031 |       currentSel( 0 ), lastSortCol( -1 ), sGrid( TRUE ), mRows( FALSE ), mCols( FALSE ),
 | 
|---|
| 2032 |       asc( TRUE ), doSort( TRUE ), readOnly( FALSE )
 | 
|---|
| 2033 | {
 | 
|---|
| 2034 |     init( numRows, numCols );
 | 
|---|
| 2035 | }
 | 
|---|
| 2036 | 
 | 
|---|
| 2037 | /*! \internal
 | 
|---|
| 2038 | */
 | 
|---|
| 2039 | 
 | 
|---|
| 2040 | void QTable::init( int rows, int cols )
 | 
|---|
| 2041 | {
 | 
|---|
| 2042 | #ifndef QT_NO_DRAGANDDROP
 | 
|---|
| 2043 |     setDragAutoScroll( FALSE );
 | 
|---|
| 2044 | #endif
 | 
|---|
| 2045 |     d = new QTablePrivate;
 | 
|---|
| 2046 |     d->geomTimer = new QTimer( this );
 | 
|---|
| 2047 |     d->lastVisCol = 0;
 | 
|---|
| 2048 |     d->lastVisRow = 0;
 | 
|---|
| 2049 |     connect( d->geomTimer, SIGNAL( timeout() ), this, SLOT( updateGeometriesSlot() ) );
 | 
|---|
| 2050 |     shouldClearSelection = FALSE;
 | 
|---|
| 2051 |     dEnabled = FALSE;
 | 
|---|
| 2052 |     roRows.setAutoDelete( TRUE );
 | 
|---|
| 2053 |     roCols.setAutoDelete( TRUE );
 | 
|---|
| 2054 |     setSorting( FALSE );
 | 
|---|
| 2055 | 
 | 
|---|
| 2056 |     unused = TRUE; // It's unused, ain't it? :)
 | 
|---|
| 2057 | 
 | 
|---|
| 2058 |     selMode = Multi;
 | 
|---|
| 2059 | 
 | 
|---|
| 2060 |     contents.setAutoDelete( TRUE );
 | 
|---|
| 2061 |     widgets.setAutoDelete( TRUE );
 | 
|---|
| 2062 | 
 | 
|---|
| 2063 |     // Enable clipper and set background mode
 | 
|---|
| 2064 |     enableClipper( qt_table_clipper_enabled );
 | 
|---|
| 2065 | 
 | 
|---|
| 2066 |     viewport()->setFocusProxy( this );
 | 
|---|
| 2067 |     viewport()->setFocusPolicy( WheelFocus );
 | 
|---|
| 2068 | 
 | 
|---|
| 2069 |     viewport()->setBackgroundMode( PaletteBase );
 | 
|---|
| 2070 |     setBackgroundMode( PaletteBackground, PaletteBase );
 | 
|---|
| 2071 |     setResizePolicy( Manual );
 | 
|---|
| 2072 |     selections.setAutoDelete( TRUE );
 | 
|---|
| 2073 | 
 | 
|---|
| 2074 |     // Create headers
 | 
|---|
| 2075 |     leftHeader = new QTableHeader( rows, this, this, "left table header" );
 | 
|---|
| 2076 |     leftHeader->setOrientation( Vertical );
 | 
|---|
| 2077 |     leftHeader->setTracking( TRUE );
 | 
|---|
| 2078 |     leftHeader->setMovingEnabled( TRUE );
 | 
|---|
| 2079 |     topHeader = new QTableHeader( cols, this, this, "right table header" );
 | 
|---|
| 2080 |     topHeader->setOrientation( Horizontal );
 | 
|---|
| 2081 |     topHeader->setTracking( TRUE );
 | 
|---|
| 2082 |     topHeader->setMovingEnabled( TRUE );
 | 
|---|
| 2083 |     if ( QApplication::reverseLayout() )
 | 
|---|
| 2084 |         setMargins( 0, fontMetrics().height() + 4, 30, 0 );
 | 
|---|
| 2085 |     else
 | 
|---|
| 2086 |         setMargins( 30, fontMetrics().height() + 4, 0, 0 );
 | 
|---|
| 2087 | 
 | 
|---|
| 2088 |     topHeader->setUpdatesEnabled( FALSE );
 | 
|---|
| 2089 |     leftHeader->setUpdatesEnabled( FALSE );
 | 
|---|
| 2090 |     // Initialize headers
 | 
|---|
| 2091 |     int i = 0;
 | 
|---|
| 2092 |     for ( i = 0; i < numCols(); ++i )
 | 
|---|
| 2093 |         topHeader->resizeSection( i, QMAX( 100, QApplication::globalStrut().height() ) );
 | 
|---|
| 2094 |     for ( i = 0; i < numRows(); ++i )
 | 
|---|
| 2095 |         leftHeader->resizeSection( i, QMAX( 20, QApplication::globalStrut().width() ) );
 | 
|---|
| 2096 |     topHeader->setUpdatesEnabled( TRUE );
 | 
|---|
| 2097 |     leftHeader->setUpdatesEnabled( TRUE );
 | 
|---|
| 2098 | 
 | 
|---|
| 2099 |     // Prepare for contents
 | 
|---|
| 2100 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 2101 | 
 | 
|---|
| 2102 |     // Connect header, table and scrollbars
 | 
|---|
| 2103 |     connect( horizontalScrollBar(), SIGNAL( valueChanged(int) ),
 | 
|---|
| 2104 |              topHeader, SLOT( setOffset(int) ) );
 | 
|---|
| 2105 |     connect( verticalScrollBar(), SIGNAL( valueChanged(int) ),
 | 
|---|
| 2106 |              leftHeader, SLOT( setOffset(int) ) );
 | 
|---|
| 2107 |     connect( topHeader, SIGNAL( sectionSizeChanged(int) ),
 | 
|---|
| 2108 |              this, SLOT( columnWidthChanged(int) ) );
 | 
|---|
| 2109 |     connect( topHeader, SIGNAL( indexChange(int,int,int) ),
 | 
|---|
| 2110 |              this, SLOT( columnIndexChanged(int,int,int) ) );
 | 
|---|
| 2111 |     connect( topHeader, SIGNAL( sectionClicked(int) ),
 | 
|---|
| 2112 |              this, SLOT( columnClicked(int) ) );
 | 
|---|
| 2113 |     connect( leftHeader, SIGNAL( sectionSizeChanged(int) ),
 | 
|---|
| 2114 |              this, SLOT( rowHeightChanged(int) ) );
 | 
|---|
| 2115 |     connect( leftHeader, SIGNAL( indexChange(int,int,int) ),
 | 
|---|
| 2116 |              this, SLOT( rowIndexChanged(int,int,int) ) );
 | 
|---|
| 2117 | 
 | 
|---|
| 2118 |     // Initialize variables
 | 
|---|
| 2119 |     autoScrollTimer = new QTimer( this );
 | 
|---|
| 2120 |     connect( autoScrollTimer, SIGNAL( timeout() ),
 | 
|---|
| 2121 |              this, SLOT( doAutoScroll() ) );
 | 
|---|
| 2122 |     curRow = curCol = 0;
 | 
|---|
| 2123 |     topHeader->setSectionState( curCol, QTableHeader::Bold );
 | 
|---|
| 2124 |     leftHeader->setSectionState( curRow, QTableHeader::Bold );
 | 
|---|
| 2125 |     edMode = NotEditing;
 | 
|---|
| 2126 |     editRow = editCol = -1;
 | 
|---|
| 2127 | 
 | 
|---|
| 2128 |     drawActiveSelection = TRUE;
 | 
|---|
| 2129 | 
 | 
|---|
| 2130 |     installEventFilter( this );
 | 
|---|
| 2131 | 
 | 
|---|
| 2132 |     focusStl = SpreadSheet;
 | 
|---|
| 2133 | 
 | 
|---|
| 2134 |     was_visible = FALSE;
 | 
|---|
| 2135 | 
 | 
|---|
| 2136 |     // initial size
 | 
|---|
| 2137 |     resize( 640, 480 );
 | 
|---|
| 2138 | }
 | 
|---|
| 2139 | 
 | 
|---|
| 2140 | /*!
 | 
|---|
| 2141 |     Releases all the resources used by the QTable object,
 | 
|---|
| 2142 |     including all \l{QTableItem}s and their widgets.
 | 
|---|
| 2143 | */
 | 
|---|
| 2144 | 
 | 
|---|
| 2145 | QTable::~QTable()
 | 
|---|
| 2146 | {
 | 
|---|
| 2147 |     delete d;
 | 
|---|
| 2148 |     setUpdatesEnabled( FALSE );
 | 
|---|
| 2149 |     contents.setAutoDelete( TRUE );
 | 
|---|
| 2150 |     contents.clear();
 | 
|---|
| 2151 |     widgets.clear();
 | 
|---|
| 2152 | }
 | 
|---|
| 2153 | 
 | 
|---|
| 2154 | void QTable::setReadOnly( bool b )
 | 
|---|
| 2155 | {
 | 
|---|
| 2156 |     readOnly = b;
 | 
|---|
| 2157 | 
 | 
|---|
| 2158 |     QTableItem *i = item(curRow, curCol);
 | 
|---|
| 2159 |     if (readOnly && isEditing()) {
 | 
|---|
| 2160 |         endEdit(editRow, editCol, TRUE, FALSE);
 | 
|---|
| 2161 |     } else if (!readOnly && i && (i->editType() == QTableItem::WhenCurrent
 | 
|---|
| 2162 |                                   || i->editType() == QTableItem::Always)) {
 | 
|---|
| 2163 |         editCell(curRow, curCol);
 | 
|---|
| 2164 |     }
 | 
|---|
| 2165 | }
 | 
|---|
| 2166 | 
 | 
|---|
| 2167 | /*!
 | 
|---|
| 2168 |     If \a ro is TRUE, row \a row is set to be read-only; otherwise the
 | 
|---|
| 2169 |     row is set to be editable.
 | 
|---|
| 2170 | 
 | 
|---|
| 2171 |     Whether a cell in this row is editable or read-only depends on the
 | 
|---|
| 2172 |     cell's EditType, and this setting:
 | 
|---|
| 2173 |     see \link qtableitem.html#wheneditable QTableItem::EditType\endlink.
 | 
|---|
| 2174 | 
 | 
|---|
| 2175 |     \sa isRowReadOnly() setColumnReadOnly() setReadOnly()
 | 
|---|
| 2176 | */
 | 
|---|
| 2177 | 
 | 
|---|
| 2178 | void QTable::setRowReadOnly( int row, bool ro )
 | 
|---|
| 2179 | {
 | 
|---|
| 2180 |     if ( ro )
 | 
|---|
| 2181 |         roRows.replace( row, new int( 0 ) );
 | 
|---|
| 2182 |     else
 | 
|---|
| 2183 |         roRows.remove( row );
 | 
|---|
| 2184 | 
 | 
|---|
| 2185 |     if (curRow == row) {
 | 
|---|
| 2186 |         QTableItem *i = item(curRow, curCol);
 | 
|---|
| 2187 |         if (ro && isEditing()) {
 | 
|---|
| 2188 |             endEdit(editRow, editCol, TRUE, FALSE);
 | 
|---|
| 2189 |         } else if (!ro && i && (i->editType() == QTableItem::WhenCurrent
 | 
|---|
| 2190 |                                       || i->editType() == QTableItem::Always)) {
 | 
|---|
| 2191 |             editCell(curRow, curCol);
 | 
|---|
| 2192 |         }
 | 
|---|
| 2193 |     }
 | 
|---|
| 2194 | }
 | 
|---|
| 2195 | 
 | 
|---|
| 2196 | /*!
 | 
|---|
| 2197 |     If \a ro is TRUE, column \a col is set to be read-only; otherwise
 | 
|---|
| 2198 |     the column is set to be editable.
 | 
|---|
| 2199 | 
 | 
|---|
| 2200 |     Whether a cell in this column is editable or read-only depends on
 | 
|---|
| 2201 |     the cell's EditType, and this setting:
 | 
|---|
| 2202 |     see \link qtableitem.html#wheneditable QTableItem::EditType\endlink.
 | 
|---|
| 2203 | 
 | 
|---|
| 2204 |     \sa isColumnReadOnly() setRowReadOnly() setReadOnly()
 | 
|---|
| 2205 | 
 | 
|---|
| 2206 | */
 | 
|---|
| 2207 | 
 | 
|---|
| 2208 | void QTable::setColumnReadOnly( int col, bool ro )
 | 
|---|
| 2209 | {
 | 
|---|
| 2210 |     if ( ro )
 | 
|---|
| 2211 |         roCols.replace( col, new int( 0 ) );
 | 
|---|
| 2212 |     else
 | 
|---|
| 2213 |         roCols.remove( col );
 | 
|---|
| 2214 | 
 | 
|---|
| 2215 |     if (curCol == col) {
 | 
|---|
| 2216 |         QTableItem *i = item(curRow, curCol);
 | 
|---|
| 2217 |         if (ro && isEditing()) {
 | 
|---|
| 2218 |             endEdit(editRow, editCol, TRUE, FALSE);
 | 
|---|
| 2219 |         } else if (!ro && i && (i->editType() == QTableItem::WhenCurrent
 | 
|---|
| 2220 |                                       || i->editType() == QTableItem::Always)) {
 | 
|---|
| 2221 |             editCell(curRow, curCol);
 | 
|---|
| 2222 |         }
 | 
|---|
| 2223 |     }
 | 
|---|
| 2224 | }
 | 
|---|
| 2225 | 
 | 
|---|
| 2226 | /*!
 | 
|---|
| 2227 |     \property QTable::readOnly
 | 
|---|
| 2228 |     \brief whether the table is read-only
 | 
|---|
| 2229 | 
 | 
|---|
| 2230 |     Whether a cell in the table is editable or read-only depends on
 | 
|---|
| 2231 |     the cell's \link QTableItem::EditType EditType\link, and this setting:
 | 
|---|
| 2232 |     see \link qtableitem.html#wheneditable
 | 
|---|
| 2233 |     QTableItem::EditType\endlink.
 | 
|---|
| 2234 | 
 | 
|---|
| 2235 |     \sa QWidget::enabled setColumnReadOnly() setRowReadOnly()
 | 
|---|
| 2236 | */
 | 
|---|
| 2237 | 
 | 
|---|
| 2238 | bool QTable::isReadOnly() const
 | 
|---|
| 2239 | {
 | 
|---|
| 2240 |     return readOnly;
 | 
|---|
| 2241 | }
 | 
|---|
| 2242 | 
 | 
|---|
| 2243 | /*!
 | 
|---|
| 2244 |     Returns TRUE if row \a row is read-only; otherwise returns FALSE.
 | 
|---|
| 2245 | 
 | 
|---|
| 2246 |     Whether a cell in this row is editable or read-only depends on the
 | 
|---|
| 2247 |     cell's \link QTableItem::EditType EditType\endlink, and this
 | 
|---|
| 2248 |     setting: see \link qtableitem.html#wheneditable
 | 
|---|
| 2249 |     QTableItem::EditType\endlink.
 | 
|---|
| 2250 | 
 | 
|---|
| 2251 |     \sa setRowReadOnly() isColumnReadOnly()
 | 
|---|
| 2252 | */
 | 
|---|
| 2253 | 
 | 
|---|
| 2254 | bool QTable::isRowReadOnly( int row ) const
 | 
|---|
| 2255 | {
 | 
|---|
| 2256 |     return (roRows.find( row ) != 0);
 | 
|---|
| 2257 | }
 | 
|---|
| 2258 | 
 | 
|---|
| 2259 | /*!
 | 
|---|
| 2260 |     Returns TRUE if column \a col is read-only; otherwise returns
 | 
|---|
| 2261 |     FALSE.
 | 
|---|
| 2262 | 
 | 
|---|
| 2263 |     Whether a cell in this column is editable or read-only depends on
 | 
|---|
| 2264 |     the cell's EditType, and this setting: see \link
 | 
|---|
| 2265 |     qtableitem.html#wheneditable QTableItem::EditType\endlink.
 | 
|---|
| 2266 | 
 | 
|---|
| 2267 |     \sa setColumnReadOnly() isRowReadOnly()
 | 
|---|
| 2268 | */
 | 
|---|
| 2269 | 
 | 
|---|
| 2270 | bool QTable::isColumnReadOnly( int col ) const
 | 
|---|
| 2271 | {
 | 
|---|
| 2272 |     return (roCols.find( col ) != 0);
 | 
|---|
| 2273 | }
 | 
|---|
| 2274 | 
 | 
|---|
| 2275 | void QTable::setSelectionMode( SelectionMode mode )
 | 
|---|
| 2276 | {
 | 
|---|
| 2277 |     if ( mode == selMode )
 | 
|---|
| 2278 |         return;
 | 
|---|
| 2279 |     selMode = mode;
 | 
|---|
| 2280 |     clearSelection();
 | 
|---|
| 2281 |     if ( isRowSelection( selMode ) && numRows() > 0 && numCols() > 0 ) {
 | 
|---|
| 2282 |         currentSel = new QTableSelection();
 | 
|---|
| 2283 |         selections.append( currentSel );
 | 
|---|
| 2284 |         currentSel->init( curRow, 0 );
 | 
|---|
| 2285 |         currentSel->expandTo( curRow, numCols() - 1 );
 | 
|---|
| 2286 |         repaintSelections( 0, currentSel );
 | 
|---|
| 2287 |     }
 | 
|---|
| 2288 | }
 | 
|---|
| 2289 | 
 | 
|---|
| 2290 | /*!
 | 
|---|
| 2291 |     \property QTable::selectionMode
 | 
|---|
| 2292 |     \brief the current selection mode
 | 
|---|
| 2293 | 
 | 
|---|
| 2294 |     The default mode is \c Multi which allows the user to select
 | 
|---|
| 2295 |     multiple ranges of cells.
 | 
|---|
| 2296 | 
 | 
|---|
| 2297 |     \sa SelectionMode setSelectionMode()
 | 
|---|
| 2298 | */
 | 
|---|
| 2299 | 
 | 
|---|
| 2300 | QTable::SelectionMode QTable::selectionMode() const
 | 
|---|
| 2301 | {
 | 
|---|
| 2302 |     return selMode;
 | 
|---|
| 2303 | }
 | 
|---|
| 2304 | 
 | 
|---|
| 2305 | /*!
 | 
|---|
| 2306 |     \property QTable::focusStyle
 | 
|---|
| 2307 |     \brief how the current (focus) cell is drawn
 | 
|---|
| 2308 | 
 | 
|---|
| 2309 |     The default style is \c SpreadSheet.
 | 
|---|
| 2310 | 
 | 
|---|
| 2311 |     \sa QTable::FocusStyle
 | 
|---|
| 2312 | */
 | 
|---|
| 2313 | 
 | 
|---|
| 2314 | void QTable::setFocusStyle( FocusStyle fs )
 | 
|---|
| 2315 | {
 | 
|---|
| 2316 |     focusStl = fs;
 | 
|---|
| 2317 |     updateCell( curRow, curCol );
 | 
|---|
| 2318 | }
 | 
|---|
| 2319 | 
 | 
|---|
| 2320 | QTable::FocusStyle QTable::focusStyle() const
 | 
|---|
| 2321 | {
 | 
|---|
| 2322 |     return focusStl;
 | 
|---|
| 2323 | }
 | 
|---|
| 2324 | 
 | 
|---|
| 2325 | /*!
 | 
|---|
| 2326 |     This functions updates all the header states to be in sync with
 | 
|---|
| 2327 |     the current selections. This should be called after
 | 
|---|
| 2328 |     programatically changing, adding or removing selections, so that
 | 
|---|
| 2329 |     the headers are updated.
 | 
|---|
| 2330 | */
 | 
|---|
| 2331 | 
 | 
|---|
| 2332 | void QTable::updateHeaderStates()
 | 
|---|
| 2333 | {
 | 
|---|
| 2334 |     horizontalHeader()->setUpdatesEnabled( FALSE );
 | 
|---|
| 2335 |     verticalHeader()->setUpdatesEnabled( FALSE );
 | 
|---|
| 2336 | 
 | 
|---|
| 2337 |     ( (QTableHeader*)verticalHeader() )->setSectionStateToAll( QTableHeader::Normal );
 | 
|---|
| 2338 |     ( (QTableHeader*)horizontalHeader() )->setSectionStateToAll( QTableHeader::Normal );
 | 
|---|
| 2339 | 
 | 
|---|
| 2340 |     QPtrListIterator<QTableSelection> it( selections );
 | 
|---|
| 2341 |     QTableSelection *s;
 | 
|---|
| 2342 |     while ( ( s = it.current() ) != 0 ) {
 | 
|---|
| 2343 |         ++it;
 | 
|---|
| 2344 |         if ( s->isActive() ) {
 | 
|---|
| 2345 |             if ( s->leftCol() == 0 &&
 | 
|---|
| 2346 |                  s->rightCol() == numCols() - 1 ) {
 | 
|---|
| 2347 |                 for ( int i = 0; i < s->bottomRow() - s->topRow() + 1; ++i )
 | 
|---|
| 2348 |                     leftHeader->setSectionState( s->topRow() + i, QTableHeader::Selected );
 | 
|---|
| 2349 |             }
 | 
|---|
| 2350 |             if ( s->topRow() == 0 &&
 | 
|---|
| 2351 |                  s->bottomRow() == numRows() - 1 ) {
 | 
|---|
| 2352 |                 for ( int i = 0; i < s->rightCol() - s->leftCol() + 1; ++i )
 | 
|---|
| 2353 |                     topHeader->setSectionState( s->leftCol() + i, QTableHeader::Selected );
 | 
|---|
| 2354 |             }
 | 
|---|
| 2355 |         }
 | 
|---|
| 2356 |     }
 | 
|---|
| 2357 | 
 | 
|---|
| 2358 |     horizontalHeader()->setUpdatesEnabled( TRUE );
 | 
|---|
| 2359 |     verticalHeader()->setUpdatesEnabled( TRUE );
 | 
|---|
| 2360 |     horizontalHeader()->repaint( FALSE );
 | 
|---|
| 2361 |     verticalHeader()->repaint( FALSE );
 | 
|---|
| 2362 | }
 | 
|---|
| 2363 | 
 | 
|---|
| 2364 | /*!
 | 
|---|
| 2365 |     Returns the table's top QHeader.
 | 
|---|
| 2366 | 
 | 
|---|
| 2367 |     This header contains the column labels.
 | 
|---|
| 2368 | 
 | 
|---|
| 2369 |     To modify a column label use QHeader::setLabel(), e.g.
 | 
|---|
| 2370 |     \quotefile table/statistics/statistics.cpp
 | 
|---|
| 2371 |     \skipto horizontalHeader
 | 
|---|
| 2372 |     \printline
 | 
|---|
| 2373 | 
 | 
|---|
| 2374 |     \sa verticalHeader() setTopMargin() QHeader
 | 
|---|
| 2375 | */
 | 
|---|
| 2376 | 
 | 
|---|
| 2377 | QHeader *QTable::horizontalHeader() const
 | 
|---|
| 2378 | {
 | 
|---|
| 2379 |     return (QHeader*)topHeader;
 | 
|---|
| 2380 | }
 | 
|---|
| 2381 | 
 | 
|---|
| 2382 | /*!
 | 
|---|
| 2383 |     Returns the table's vertical QHeader.
 | 
|---|
| 2384 | 
 | 
|---|
| 2385 |     This header contains the row labels.
 | 
|---|
| 2386 | 
 | 
|---|
| 2387 |     \sa horizontalHeader() setLeftMargin() QHeader
 | 
|---|
| 2388 | */
 | 
|---|
| 2389 | 
 | 
|---|
| 2390 | QHeader *QTable::verticalHeader() const
 | 
|---|
| 2391 | {
 | 
|---|
| 2392 |     return (QHeader*)leftHeader;
 | 
|---|
| 2393 | }
 | 
|---|
| 2394 | 
 | 
|---|
| 2395 | void QTable::setShowGrid( bool b )
 | 
|---|
| 2396 | {
 | 
|---|
| 2397 |     if ( sGrid == b )
 | 
|---|
| 2398 |         return;
 | 
|---|
| 2399 |     sGrid = b;
 | 
|---|
| 2400 |     updateContents();
 | 
|---|
| 2401 | }
 | 
|---|
| 2402 | 
 | 
|---|
| 2403 | /*!
 | 
|---|
| 2404 |     \property QTable::showGrid
 | 
|---|
| 2405 |     \brief whether the table's grid is displayed
 | 
|---|
| 2406 | 
 | 
|---|
| 2407 |     The grid is shown by default.
 | 
|---|
| 2408 | */
 | 
|---|
| 2409 | 
 | 
|---|
| 2410 | bool QTable::showGrid() const
 | 
|---|
| 2411 | {
 | 
|---|
| 2412 |     return sGrid;
 | 
|---|
| 2413 | }
 | 
|---|
| 2414 | 
 | 
|---|
| 2415 | /*!
 | 
|---|
| 2416 |     \property QTable::columnMovingEnabled
 | 
|---|
| 2417 |     \brief whether columns can be moved by the user
 | 
|---|
| 2418 | 
 | 
|---|
| 2419 |     The default is FALSE. Columns are moved by dragging whilst holding
 | 
|---|
| 2420 |     down the Ctrl key.
 | 
|---|
| 2421 | 
 | 
|---|
| 2422 |     \sa rowMovingEnabled
 | 
|---|
| 2423 | */
 | 
|---|
| 2424 | 
 | 
|---|
| 2425 | void QTable::setColumnMovingEnabled( bool b )
 | 
|---|
| 2426 | {
 | 
|---|
| 2427 |     mCols = b;
 | 
|---|
| 2428 | }
 | 
|---|
| 2429 | 
 | 
|---|
| 2430 | bool QTable::columnMovingEnabled() const
 | 
|---|
| 2431 | {
 | 
|---|
| 2432 |     return mCols;
 | 
|---|
| 2433 | }
 | 
|---|
| 2434 | 
 | 
|---|
| 2435 | /*!
 | 
|---|
| 2436 |     \property QTable::rowMovingEnabled
 | 
|---|
| 2437 |     \brief whether rows can be moved by the user
 | 
|---|
| 2438 | 
 | 
|---|
| 2439 |     The default is FALSE. Rows are moved by dragging whilst holding
 | 
|---|
| 2440 |     down the Ctrl key.
 | 
|---|
| 2441 | 
 | 
|---|
| 2442 | 
 | 
|---|
| 2443 |     \sa columnMovingEnabled
 | 
|---|
| 2444 | */
 | 
|---|
| 2445 | 
 | 
|---|
| 2446 | void QTable::setRowMovingEnabled( bool b )
 | 
|---|
| 2447 | {
 | 
|---|
| 2448 |     mRows = b;
 | 
|---|
| 2449 | }
 | 
|---|
| 2450 | 
 | 
|---|
| 2451 | bool QTable::rowMovingEnabled() const
 | 
|---|
| 2452 | {
 | 
|---|
| 2453 |     return mRows;
 | 
|---|
| 2454 | }
 | 
|---|
| 2455 | 
 | 
|---|
| 2456 | /*!
 | 
|---|
| 2457 |     This is called when QTable's internal array needs to be resized to
 | 
|---|
| 2458 |     \a len elements.
 | 
|---|
| 2459 | 
 | 
|---|
| 2460 |     If you don't use QTableItems you should reimplement this as an
 | 
|---|
| 2461 |     empty method to avoid wasting memory. See the notes on large
 | 
|---|
| 2462 |     tables for further details.
 | 
|---|
| 2463 | */
 | 
|---|
| 2464 | 
 | 
|---|
| 2465 | void QTable::resizeData( int len )
 | 
|---|
| 2466 | {
 | 
|---|
| 2467 |     contents.resize( len );
 | 
|---|
| 2468 |     widgets.resize( len );
 | 
|---|
| 2469 | }
 | 
|---|
| 2470 | 
 | 
|---|
| 2471 | /*!
 | 
|---|
| 2472 |     Swaps the data in \a row1 and \a row2.
 | 
|---|
| 2473 | 
 | 
|---|
| 2474 |     This function is used to swap the positions of two rows. It is
 | 
|---|
| 2475 |     called when the user changes the order of rows (see
 | 
|---|
| 2476 |     setRowMovingEnabled()), and when rows are sorted.
 | 
|---|
| 2477 | 
 | 
|---|
| 2478 |     If you don't use \l{QTableItem}s and want your users to be able to
 | 
|---|
| 2479 |     swap rows, e.g. for sorting, you will need to reimplement this
 | 
|---|
| 2480 |     function. (See the notes on large tables.)
 | 
|---|
| 2481 | 
 | 
|---|
| 2482 |     If \a swapHeader is TRUE, the rows' header contents is also
 | 
|---|
| 2483 |     swapped.
 | 
|---|
| 2484 | 
 | 
|---|
| 2485 |     This function will not update the QTable, you will have to do
 | 
|---|
| 2486 |     this manually, e.g. by calling updateContents().
 | 
|---|
| 2487 | 
 | 
|---|
| 2488 |     \sa swapColumns() swapCells()
 | 
|---|
| 2489 | */
 | 
|---|
| 2490 | 
 | 
|---|
| 2491 | void QTable::swapRows( int row1, int row2, bool swapHeader )
 | 
|---|
| 2492 | {
 | 
|---|
| 2493 |     if ( swapHeader )
 | 
|---|
| 2494 |         leftHeader->swapSections( row1, row2, FALSE );
 | 
|---|
| 2495 | 
 | 
|---|
| 2496 |     QPtrVector<QTableItem> tmpContents;
 | 
|---|
| 2497 |     tmpContents.resize( numCols() );
 | 
|---|
| 2498 |     QPtrVector<QWidget> tmpWidgets;
 | 
|---|
| 2499 |     tmpWidgets.resize( numCols() );
 | 
|---|
| 2500 |     int i;
 | 
|---|
| 2501 | 
 | 
|---|
| 2502 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 2503 |     widgets.setAutoDelete( FALSE );
 | 
|---|
| 2504 |     for ( i = 0; i < numCols(); ++i ) {
 | 
|---|
| 2505 |         QTableItem *i1, *i2;
 | 
|---|
| 2506 |         i1 = item( row1, i );
 | 
|---|
| 2507 |         i2 = item( row2, i );
 | 
|---|
| 2508 |         if ( i1 || i2 ) {
 | 
|---|
| 2509 |             tmpContents.insert( i, i1 );
 | 
|---|
| 2510 |             contents.remove( indexOf( row1, i ) );
 | 
|---|
| 2511 |             contents.insert( indexOf( row1, i ), i2 );
 | 
|---|
| 2512 |             contents.remove( indexOf( row2, i ) );
 | 
|---|
| 2513 |             contents.insert( indexOf( row2, i ), tmpContents[ i ] );
 | 
|---|
| 2514 |             if ( contents[ indexOf( row1, i ) ] )
 | 
|---|
| 2515 |                 contents[ indexOf( row1, i ) ]->setRow( row1 );
 | 
|---|
| 2516 |             if ( contents[ indexOf( row2, i ) ] )
 | 
|---|
| 2517 |                 contents[ indexOf( row2, i ) ]->setRow( row2 );
 | 
|---|
| 2518 |         }
 | 
|---|
| 2519 | 
 | 
|---|
| 2520 |         QWidget *w1, *w2;
 | 
|---|
| 2521 |         w1 = cellWidget( row1, i );
 | 
|---|
| 2522 |         w2 = cellWidget( row2, i );
 | 
|---|
| 2523 |         if ( w1 || w2 ) {
 | 
|---|
| 2524 |             tmpWidgets.insert( i, w1 );
 | 
|---|
| 2525 |             widgets.remove( indexOf( row1, i ) );
 | 
|---|
| 2526 |             widgets.insert( indexOf( row1, i ), w2 );
 | 
|---|
| 2527 |             widgets.remove( indexOf( row2, i ) );
 | 
|---|
| 2528 |             widgets.insert( indexOf( row2, i ), tmpWidgets[ i ] );
 | 
|---|
| 2529 |         }
 | 
|---|
| 2530 |     }
 | 
|---|
| 2531 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 2532 |     widgets.setAutoDelete( TRUE );
 | 
|---|
| 2533 | 
 | 
|---|
| 2534 |     updateRowWidgets( row1 );
 | 
|---|
| 2535 |     updateRowWidgets( row2 );
 | 
|---|
| 2536 |     if ( curRow == row1 )
 | 
|---|
| 2537 |         curRow = row2;
 | 
|---|
| 2538 |     else if ( curRow == row2 )
 | 
|---|
| 2539 |         curRow = row1;
 | 
|---|
| 2540 |     if ( editRow == row1 )
 | 
|---|
| 2541 |         editRow = row2;
 | 
|---|
| 2542 |     else if ( editRow == row2 )
 | 
|---|
| 2543 |         editRow = row1;
 | 
|---|
| 2544 | }
 | 
|---|
| 2545 | 
 | 
|---|
| 2546 | /*!
 | 
|---|
| 2547 |     Sets the left margin to be \a m pixels wide.
 | 
|---|
| 2548 | 
 | 
|---|
| 2549 |     The verticalHeader(), which displays row labels, occupies this
 | 
|---|
| 2550 |     margin.
 | 
|---|
| 2551 | 
 | 
|---|
| 2552 |     In an Arabic or Hebrew localization, the verticalHeader() will
 | 
|---|
| 2553 |     appear on the right side of the table, and this call will set the
 | 
|---|
| 2554 |     right margin.
 | 
|---|
| 2555 | 
 | 
|---|
| 2556 |     \sa leftMargin() setTopMargin() verticalHeader()
 | 
|---|
| 2557 | */
 | 
|---|
| 2558 | 
 | 
|---|
| 2559 | void QTable::setLeftMargin( int m )
 | 
|---|
| 2560 | {
 | 
|---|
| 2561 |     if ( QApplication::reverseLayout() )
 | 
|---|
| 2562 |         setMargins( leftMargin(), topMargin(), m, bottomMargin() );
 | 
|---|
| 2563 |     else
 | 
|---|
| 2564 |         setMargins( m, topMargin(), rightMargin(), bottomMargin() );
 | 
|---|
| 2565 |     updateGeometries();
 | 
|---|
| 2566 | }
 | 
|---|
| 2567 | 
 | 
|---|
| 2568 | /*!
 | 
|---|
| 2569 |     Sets the top margin to be \a m pixels high.
 | 
|---|
| 2570 | 
 | 
|---|
| 2571 |     The horizontalHeader(), which displays column labels, occupies
 | 
|---|
| 2572 |     this margin.
 | 
|---|
| 2573 | 
 | 
|---|
| 2574 |     \sa topMargin() setLeftMargin()
 | 
|---|
| 2575 | */
 | 
|---|
| 2576 | 
 | 
|---|
| 2577 | void QTable::setTopMargin( int m )
 | 
|---|
| 2578 | {
 | 
|---|
| 2579 |     setMargins( leftMargin(), m, rightMargin(), bottomMargin() );
 | 
|---|
| 2580 |     updateGeometries();
 | 
|---|
| 2581 | }
 | 
|---|
| 2582 | 
 | 
|---|
| 2583 | /*!
 | 
|---|
| 2584 |     Swaps the data in \a col1 with \a col2.
 | 
|---|
| 2585 | 
 | 
|---|
| 2586 |     This function is used to swap the positions of two columns. It is
 | 
|---|
| 2587 |     called when the user changes the order of columns (see
 | 
|---|
| 2588 |     setColumnMovingEnabled(), and when columns are sorted.
 | 
|---|
| 2589 | 
 | 
|---|
| 2590 |     If you don't use \l{QTableItem}s and want your users to be able to
 | 
|---|
| 2591 |     swap columns you will need to reimplement this function. (See the
 | 
|---|
| 2592 |     notes on large tables.)
 | 
|---|
| 2593 | 
 | 
|---|
| 2594 |     If \a swapHeader is TRUE, the columns' header contents is also
 | 
|---|
| 2595 |     swapped.
 | 
|---|
| 2596 | 
 | 
|---|
| 2597 |     \sa swapCells()
 | 
|---|
| 2598 | */
 | 
|---|
| 2599 | 
 | 
|---|
| 2600 | void QTable::swapColumns( int col1, int col2, bool swapHeader )
 | 
|---|
| 2601 | {
 | 
|---|
| 2602 |     if ( swapHeader )
 | 
|---|
| 2603 |         topHeader->swapSections( col1, col2, FALSE );
 | 
|---|
| 2604 | 
 | 
|---|
| 2605 |     QPtrVector<QTableItem> tmpContents;
 | 
|---|
| 2606 |     tmpContents.resize( numRows() );
 | 
|---|
| 2607 |     QPtrVector<QWidget> tmpWidgets;
 | 
|---|
| 2608 |     tmpWidgets.resize( numRows() );
 | 
|---|
| 2609 |     int i;
 | 
|---|
| 2610 | 
 | 
|---|
| 2611 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 2612 |     widgets.setAutoDelete( FALSE );
 | 
|---|
| 2613 |     for ( i = 0; i < numRows(); ++i ) {
 | 
|---|
| 2614 |         QTableItem *i1, *i2;
 | 
|---|
| 2615 |         i1 = item( i, col1 );
 | 
|---|
| 2616 |         i2 = item( i, col2 );
 | 
|---|
| 2617 |         if ( i1 || i2 ) {
 | 
|---|
| 2618 |             tmpContents.insert( i, i1 );
 | 
|---|
| 2619 |             contents.remove( indexOf( i, col1 ) );
 | 
|---|
| 2620 |             contents.insert( indexOf( i, col1 ), i2 );
 | 
|---|
| 2621 |             contents.remove( indexOf( i, col2 ) );
 | 
|---|
| 2622 |             contents.insert( indexOf( i, col2 ), tmpContents[ i ] );
 | 
|---|
| 2623 |             if ( contents[ indexOf( i, col1 ) ] )
 | 
|---|
| 2624 |                 contents[ indexOf( i, col1 ) ]->setCol( col1 );
 | 
|---|
| 2625 |             if ( contents[ indexOf( i, col2 ) ] )
 | 
|---|
| 2626 |                 contents[ indexOf( i, col2 ) ]->setCol( col2 );
 | 
|---|
| 2627 |         }
 | 
|---|
| 2628 | 
 | 
|---|
| 2629 |         QWidget *w1, *w2;
 | 
|---|
| 2630 |         w1 = cellWidget( i, col1 );
 | 
|---|
| 2631 |         w2 = cellWidget( i, col2 );
 | 
|---|
| 2632 |         if ( w1 || w2 ) {
 | 
|---|
| 2633 |             tmpWidgets.insert( i, w1 );
 | 
|---|
| 2634 |             widgets.remove( indexOf( i, col1 ) );
 | 
|---|
| 2635 |             widgets.insert( indexOf( i, col1 ), w2 );
 | 
|---|
| 2636 |             widgets.remove( indexOf( i, col2 ) );
 | 
|---|
| 2637 |             widgets.insert( indexOf( i, col2 ), tmpWidgets[ i ] );
 | 
|---|
| 2638 |         }
 | 
|---|
| 2639 |     }
 | 
|---|
| 2640 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 2641 |     widgets.setAutoDelete( TRUE );
 | 
|---|
| 2642 | 
 | 
|---|
| 2643 |     columnWidthChanged( col1 );
 | 
|---|
| 2644 |     columnWidthChanged( col2 );
 | 
|---|
| 2645 |     if ( curCol == col1 )
 | 
|---|
| 2646 |         curCol = col2;
 | 
|---|
| 2647 |     else if ( curCol == col2 )
 | 
|---|
| 2648 |         curCol = col1;
 | 
|---|
| 2649 |     if ( editCol == col1 )
 | 
|---|
| 2650 |         editCol = col2;
 | 
|---|
| 2651 |     else if ( editCol == col2 )
 | 
|---|
| 2652 |         editCol = col1;
 | 
|---|
| 2653 | }
 | 
|---|
| 2654 | 
 | 
|---|
| 2655 | /*!
 | 
|---|
| 2656 |     Swaps the contents of the cell at \a row1, \a col1 with the
 | 
|---|
| 2657 |     contents of the cell at \a row2, \a col2.
 | 
|---|
| 2658 | 
 | 
|---|
| 2659 |     This function is also called when the table is sorted.
 | 
|---|
| 2660 | 
 | 
|---|
| 2661 |     If you don't use \l{QTableItem}s and want your users to be able to
 | 
|---|
| 2662 |     swap cells, you will need to reimplement this function. (See the
 | 
|---|
| 2663 |     notes on large tables.)
 | 
|---|
| 2664 | 
 | 
|---|
| 2665 |     \sa swapColumns() swapRows()
 | 
|---|
| 2666 | */
 | 
|---|
| 2667 | 
 | 
|---|
| 2668 | void QTable::swapCells( int row1, int col1, int row2, int col2 )
 | 
|---|
| 2669 | {
 | 
|---|
| 2670 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 2671 |     widgets.setAutoDelete( FALSE );
 | 
|---|
| 2672 |     QTableItem *i1, *i2;
 | 
|---|
| 2673 |     i1 = item( row1, col1 );
 | 
|---|
| 2674 |     i2 = item( row2, col2 );
 | 
|---|
| 2675 |     if ( i1 || i2 ) {
 | 
|---|
| 2676 |         QTableItem *tmp = i1;
 | 
|---|
| 2677 |         contents.remove( indexOf( row1, col1 ) );
 | 
|---|
| 2678 |         contents.insert( indexOf( row1, col1 ), i2 );
 | 
|---|
| 2679 |         contents.remove( indexOf( row2, col2 ) );
 | 
|---|
| 2680 |         contents.insert( indexOf( row2, col2 ), tmp );
 | 
|---|
| 2681 |         if ( contents[ indexOf( row1, col1 ) ] ) {
 | 
|---|
| 2682 |             contents[ indexOf( row1, col1 ) ]->setRow( row1 );
 | 
|---|
| 2683 |             contents[ indexOf( row1, col1 ) ]->setCol( col1 );
 | 
|---|
| 2684 |         }
 | 
|---|
| 2685 |         if ( contents[ indexOf( row2, col2 ) ] ) {
 | 
|---|
| 2686 |             contents[ indexOf( row2, col2 ) ]->setRow( row2 );
 | 
|---|
| 2687 |             contents[ indexOf( row2, col2 ) ]->setCol( col2 );
 | 
|---|
| 2688 |         }
 | 
|---|
| 2689 |     }
 | 
|---|
| 2690 | 
 | 
|---|
| 2691 |     QWidget *w1, *w2;
 | 
|---|
| 2692 |     w1 = cellWidget( row1, col1 );
 | 
|---|
| 2693 |     w2 = cellWidget( row2, col2 );
 | 
|---|
| 2694 |     if ( w1 || w2 ) {
 | 
|---|
| 2695 |         QWidget *tmp = w1;
 | 
|---|
| 2696 |         widgets.remove( indexOf( row1, col1 ) );
 | 
|---|
| 2697 |         widgets.insert( indexOf( row1, col1 ), w2 );
 | 
|---|
| 2698 |         widgets.remove( indexOf( row2, col2 ) );
 | 
|---|
| 2699 |         widgets.insert( indexOf( row2, col2 ), tmp );
 | 
|---|
| 2700 |     }
 | 
|---|
| 2701 | 
 | 
|---|
| 2702 |     updateRowWidgets( row1 );
 | 
|---|
| 2703 |     updateRowWidgets( row2 );
 | 
|---|
| 2704 |     updateColWidgets( col1 );
 | 
|---|
| 2705 |     updateColWidgets( col2 );
 | 
|---|
| 2706 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 2707 |     widgets.setAutoDelete( TRUE );
 | 
|---|
| 2708 | }
 | 
|---|
| 2709 | 
 | 
|---|
| 2710 | static bool is_child_of( QWidget *child, QWidget *parent )
 | 
|---|
| 2711 | {
 | 
|---|
| 2712 |     while ( child ) {
 | 
|---|
| 2713 |         if ( child == parent )
 | 
|---|
| 2714 |             return TRUE;
 | 
|---|
| 2715 |         child = child->parentWidget();
 | 
|---|
| 2716 |     }
 | 
|---|
| 2717 |     return FALSE;
 | 
|---|
| 2718 | }
 | 
|---|
| 2719 | 
 | 
|---|
| 2720 | /*!
 | 
|---|
| 2721 |     Draws the table contents on the painter \a p. This function is
 | 
|---|
| 2722 |     optimized so that it only draws the cells inside the \a cw pixels
 | 
|---|
| 2723 |     wide and \a ch pixels high clipping rectangle at position \a cx,
 | 
|---|
| 2724 |     \a cy.
 | 
|---|
| 2725 | 
 | 
|---|
| 2726 |     Additionally, drawContents() highlights the current cell.
 | 
|---|
| 2727 | */
 | 
|---|
| 2728 | 
 | 
|---|
| 2729 | void QTable::drawContents( QPainter *p, int cx, int cy, int cw, int ch )
 | 
|---|
| 2730 | {
 | 
|---|
| 2731 |     int colfirst = columnAt( cx );
 | 
|---|
| 2732 |     int collast = columnAt( cx + cw );
 | 
|---|
| 2733 |     int rowfirst = rowAt( cy );
 | 
|---|
| 2734 |     int rowlast = rowAt( cy + ch );
 | 
|---|
| 2735 | 
 | 
|---|
| 2736 |     if ( rowfirst == -1 || colfirst == -1 ) {
 | 
|---|
| 2737 |         paintEmptyArea( p, cx, cy, cw, ch );
 | 
|---|
| 2738 |         return;
 | 
|---|
| 2739 |     }
 | 
|---|
| 2740 | 
 | 
|---|
| 2741 |     drawActiveSelection = hasFocus() || viewport()->hasFocus() || d->inMenuMode
 | 
|---|
| 2742 |                         || is_child_of( qApp->focusWidget(), viewport() )
 | 
|---|
| 2743 |                         || !style().styleHint( QStyle::SH_ItemView_ChangeHighlightOnFocus, this );
 | 
|---|
| 2744 |     if ( rowlast == -1 )
 | 
|---|
| 2745 |         rowlast = numRows() - 1;
 | 
|---|
| 2746 |     if ( collast == -1 )
 | 
|---|
| 2747 |         collast = numCols() - 1;
 | 
|---|
| 2748 | 
 | 
|---|
| 2749 |     bool currentInSelection = FALSE;
 | 
|---|
| 2750 | 
 | 
|---|
| 2751 |     QPtrListIterator<QTableSelection> it( selections );
 | 
|---|
| 2752 |     QTableSelection *s;
 | 
|---|
| 2753 |     while ( ( s = it.current() ) != 0 ) {
 | 
|---|
| 2754 |         ++it;
 | 
|---|
| 2755 |         if ( s->isActive() &&
 | 
|---|
| 2756 |              curRow >= s->topRow() &&
 | 
|---|
| 2757 |              curRow <= s->bottomRow() &&
 | 
|---|
| 2758 |              curCol >= s->leftCol() &&
 | 
|---|
| 2759 |              curCol <= s->rightCol() ) {
 | 
|---|
| 2760 |             currentInSelection = s->topRow() != curRow || s->bottomRow() != curRow || s->leftCol() != curCol || s->rightCol() != curCol;
 | 
|---|
| 2761 |             break;
 | 
|---|
| 2762 |         }
 | 
|---|
| 2763 |     }
 | 
|---|
| 2764 | 
 | 
|---|
| 2765 |     // Go through the rows
 | 
|---|
| 2766 |     for ( int r = rowfirst; r <= rowlast; ++r ) {
 | 
|---|
| 2767 |         // get row position and height
 | 
|---|
| 2768 |         int rowp = rowPos( r );
 | 
|---|
| 2769 |         int rowh = rowHeight( r );
 | 
|---|
| 2770 | 
 | 
|---|
| 2771 |         // Go through the columns in row r
 | 
|---|
| 2772 |         // if we know from where to where, go through [colfirst, collast],
 | 
|---|
| 2773 |         // else go through all of them
 | 
|---|
| 2774 |         for ( int c = colfirst; c <= collast; ++c ) {
 | 
|---|
| 2775 |             // get position and width of column c
 | 
|---|
| 2776 |             int colp, colw;
 | 
|---|
| 2777 |             colp = columnPos( c );
 | 
|---|
| 2778 |             colw = columnWidth( c );
 | 
|---|
| 2779 |             int oldrp = rowp;
 | 
|---|
| 2780 |             int oldrh = rowh;
 | 
|---|
| 2781 | 
 | 
|---|
| 2782 |             QTableItem *itm = item( r, c );
 | 
|---|
| 2783 |             if ( itm &&
 | 
|---|
| 2784 |                  ( itm->colSpan() > 1 || itm->rowSpan() > 1 ) ) {
 | 
|---|
| 2785 |                 bool goon = r == itm->row() && c == itm->col() ||
 | 
|---|
| 2786 |                         r == rowfirst && c == itm->col() ||
 | 
|---|
| 2787 |                         r == itm->row() && c == colfirst;
 | 
|---|
| 2788 |                 if ( !goon )
 | 
|---|
| 2789 |                     continue;
 | 
|---|
| 2790 |                 rowp = rowPos( itm->row() );
 | 
|---|
| 2791 |                 rowh = 0;
 | 
|---|
| 2792 |                 int i;
 | 
|---|
| 2793 |                 for ( i = 0; i < itm->rowSpan(); ++i )
 | 
|---|
| 2794 |                     rowh += rowHeight( i + itm->row() );
 | 
|---|
| 2795 |                 colp = columnPos( itm->col() );
 | 
|---|
| 2796 |                 colw = 0;
 | 
|---|
| 2797 |                 for ( i = 0; i < itm->colSpan(); ++i )
 | 
|---|
| 2798 |                     colw += columnWidth( i + itm->col() );
 | 
|---|
| 2799 |             }
 | 
|---|
| 2800 | 
 | 
|---|
| 2801 |             // Translate painter and draw the cell
 | 
|---|
| 2802 |             p->translate( colp, rowp );
 | 
|---|
| 2803 |             bool selected = isSelected( r, c );
 | 
|---|
| 2804 |             if ( focusStl != FollowStyle && selected && !currentInSelection &&
 | 
|---|
| 2805 |                  r == curRow && c == curCol  )
 | 
|---|
| 2806 |                 selected = FALSE;
 | 
|---|
| 2807 |             paintCell( p, r, c, QRect( colp, rowp, colw, rowh ), selected );
 | 
|---|
| 2808 |             p->translate( -colp, -rowp );
 | 
|---|
| 2809 | 
 | 
|---|
| 2810 |             rowp = oldrp;
 | 
|---|
| 2811 |             rowh = oldrh;
 | 
|---|
| 2812 | 
 | 
|---|
| 2813 |             QWidget *w = cellWidget( r, c );
 | 
|---|
| 2814 |             QRect cg( cellGeometry( r, c ) );
 | 
|---|
| 2815 |             if ( w && w->geometry() != QRect( contentsToViewport( cg.topLeft() ), cg.size() - QSize( 1, 1 ) ) ) {
 | 
|---|
| 2816 |                 moveChild( w, colp, rowp );
 | 
|---|
| 2817 |                 w->resize( cg.size() - QSize( 1, 1 ) );
 | 
|---|
| 2818 |             }
 | 
|---|
| 2819 |         }
 | 
|---|
| 2820 |     }
 | 
|---|
| 2821 |     d->lastVisCol = collast;
 | 
|---|
| 2822 |     d->lastVisRow = rowlast;
 | 
|---|
| 2823 | 
 | 
|---|
| 2824 |     // draw indication of current cell
 | 
|---|
| 2825 |     QRect focusRect = cellGeometry( curRow, curCol );
 | 
|---|
| 2826 |     p->translate( focusRect.x(), focusRect.y() );
 | 
|---|
| 2827 |     paintFocus( p, focusRect );
 | 
|---|
| 2828 |     p->translate( -focusRect.x(), -focusRect.y() );
 | 
|---|
| 2829 | 
 | 
|---|
| 2830 |     // Paint empty rects
 | 
|---|
| 2831 |     paintEmptyArea( p, cx, cy, cw, ch );
 | 
|---|
| 2832 | 
 | 
|---|
| 2833 |     drawActiveSelection = TRUE;
 | 
|---|
| 2834 | }
 | 
|---|
| 2835 | 
 | 
|---|
| 2836 | /*!
 | 
|---|
| 2837 |     \reimp
 | 
|---|
| 2838 | 
 | 
|---|
| 2839 |     (Implemented to get rid of a compiler warning.)
 | 
|---|
| 2840 | */
 | 
|---|
| 2841 | 
 | 
|---|
| 2842 | void QTable::drawContents( QPainter * )
 | 
|---|
| 2843 | {
 | 
|---|
| 2844 | }
 | 
|---|
| 2845 | 
 | 
|---|
| 2846 | /*!
 | 
|---|
| 2847 |     Returns the geometry of cell \a row, \a col in the cell's
 | 
|---|
| 2848 |     coordinate system. This is a convenience function useful in
 | 
|---|
| 2849 |     paintCell(). It is equivalent to QRect( QPoint(0,0), cellGeometry(
 | 
|---|
| 2850 |     row, col).size() );
 | 
|---|
| 2851 | 
 | 
|---|
| 2852 |     \sa cellGeometry()
 | 
|---|
| 2853 | */
 | 
|---|
| 2854 | 
 | 
|---|
| 2855 | QRect QTable::cellRect( int row, int col ) const
 | 
|---|
| 2856 | {
 | 
|---|
| 2857 |     return QRect( QPoint(0,0), cellGeometry( row, col ).size() );
 | 
|---|
| 2858 | }
 | 
|---|
| 2859 | 
 | 
|---|
| 2860 | /*!
 | 
|---|
| 2861 |     \overload
 | 
|---|
| 2862 | 
 | 
|---|
| 2863 |     Use the other paintCell() function. This function is only included
 | 
|---|
| 2864 |     for backwards compatibilty.
 | 
|---|
| 2865 | */
 | 
|---|
| 2866 | 
 | 
|---|
| 2867 | void QTable::paintCell( QPainter* p, int row, int col,
 | 
|---|
| 2868 |                         const QRect &cr, bool selected )
 | 
|---|
| 2869 | {
 | 
|---|
| 2870 |     if ( cr.width() == 0 || cr.height() == 0 )
 | 
|---|
| 2871 |         return;
 | 
|---|
| 2872 | #if defined(Q_WS_WIN)
 | 
|---|
| 2873 |     const QColorGroup &cg = ( !drawActiveSelection && style().styleHint( QStyle::SH_ItemView_ChangeHighlightOnFocus ) ? palette().inactive() : colorGroup() );
 | 
|---|
| 2874 | #else
 | 
|---|
| 2875 |     const QColorGroup &cg = colorGroup();
 | 
|---|
| 2876 | #endif
 | 
|---|
| 2877 | 
 | 
|---|
| 2878 |     QTableItem *itm = item( row, col );
 | 
|---|
| 2879 |     QColorGroup cg2( cg );
 | 
|---|
| 2880 |     if ( itm && !itm->isEnabled() )
 | 
|---|
| 2881 |         cg2 = palette().disabled();
 | 
|---|
| 2882 | 
 | 
|---|
| 2883 |     paintCell( p, row, col, cr, selected, cg2 );
 | 
|---|
| 2884 | }
 | 
|---|
| 2885 | 
 | 
|---|
| 2886 | /*!
 | 
|---|
| 2887 |     Paints the cell at \a row, \a col on the painter \a p. The painter
 | 
|---|
| 2888 |     has already been translated to the cell's origin. \a cr describes
 | 
|---|
| 2889 |     the cell coordinates in the content coordinate system.
 | 
|---|
| 2890 | 
 | 
|---|
| 2891 |     If \a selected is TRUE the cell is highlighted.
 | 
|---|
| 2892 | 
 | 
|---|
| 2893 |     \a cg is the colorgroup which should be used to draw the cell
 | 
|---|
| 2894 |     content.
 | 
|---|
| 2895 | 
 | 
|---|
| 2896 |     If you want to draw custom cell content, for example right-aligned
 | 
|---|
| 2897 |     text, you must either reimplement paintCell(), or subclass
 | 
|---|
| 2898 |     QTableItem and reimplement QTableItem::paint() to do the custom
 | 
|---|
| 2899 |     drawing.
 | 
|---|
| 2900 | 
 | 
|---|
| 2901 |     If you're using a QTableItem subclass, for example, to store a
 | 
|---|
| 2902 |     data structure, then reimplementing QTableItem::paint() may be the
 | 
|---|
| 2903 |     best approach. For data you want to draw immediately, e.g. data
 | 
|---|
| 2904 |     retrieved from a database, it is probably best to reimplement
 | 
|---|
| 2905 |     paintCell(). Note that if you reimplement paintCell(), i.e. don't
 | 
|---|
| 2906 |     use \l{QTableItem}s, you must reimplement other functions: see the
 | 
|---|
| 2907 |     notes on large tables.
 | 
|---|
| 2908 | 
 | 
|---|
| 2909 |     Note that the painter is not clipped by default in order to get
 | 
|---|
| 2910 |     maximum efficiency. If you want clipping, use code like this:
 | 
|---|
| 2911 | 
 | 
|---|
| 2912 |     \code
 | 
|---|
| 2913 |     p->setClipRect( cellRect(row, col), QPainter::CoordPainter );
 | 
|---|
| 2914 |     //... your drawing code
 | 
|---|
| 2915 |     p->setClipping( FALSE );
 | 
|---|
| 2916 |     \endcode
 | 
|---|
| 2917 | */
 | 
|---|
| 2918 | 
 | 
|---|
| 2919 | void QTable::paintCell( QPainter *p, int row, int col,
 | 
|---|
| 2920 |                         const QRect &cr, bool selected, const QColorGroup &cg )
 | 
|---|
| 2921 | {
 | 
|---|
| 2922 |     if ( focusStl == SpreadSheet && selected &&
 | 
|---|
| 2923 |          row == curRow &&
 | 
|---|
| 2924 |          col == curCol && ( hasFocus() || viewport()->hasFocus() ) )
 | 
|---|
| 2925 |         selected = FALSE;
 | 
|---|
| 2926 | 
 | 
|---|
| 2927 |     int w = cr.width();
 | 
|---|
| 2928 |     int h = cr.height();
 | 
|---|
| 2929 |     int x2 = w - 1;
 | 
|---|
| 2930 |     int y2 = h - 1;
 | 
|---|
| 2931 | 
 | 
|---|
| 2932 | 
 | 
|---|
| 2933 |     QTableItem *itm = item( row, col );
 | 
|---|
| 2934 |     if ( itm ) {
 | 
|---|
| 2935 |         p->save();
 | 
|---|
| 2936 |         itm->paint( p, cg, cr, selected );
 | 
|---|
| 2937 |         p->restore();
 | 
|---|
| 2938 |     } else {
 | 
|---|
| 2939 |         p->fillRect( 0, 0, w, h, selected ? cg.brush( QColorGroup::Highlight ) : cg.brush( QColorGroup::Base ) );
 | 
|---|
| 2940 |     }
 | 
|---|
| 2941 | 
 | 
|---|
| 2942 |     if ( sGrid ) {
 | 
|---|
| 2943 |         // Draw our lines
 | 
|---|
| 2944 |         QPen pen( p->pen() );
 | 
|---|
| 2945 |         p->setPen( (QRgb) style().styleHint( QStyle::SH_Table_GridLineColor, this ) );
 | 
|---|
| 2946 |         p->drawLine( x2, 0, x2, y2 );
 | 
|---|
| 2947 |         p->drawLine( 0, y2, x2, y2 );
 | 
|---|
| 2948 |         p->setPen( pen );
 | 
|---|
| 2949 |     }
 | 
|---|
| 2950 | }
 | 
|---|
| 2951 | 
 | 
|---|
| 2952 | /*!
 | 
|---|
| 2953 |     Draws the focus rectangle of the current cell (see currentRow(),
 | 
|---|
| 2954 |     currentColumn()).
 | 
|---|
| 2955 | 
 | 
|---|
| 2956 |     The painter \a p is already translated to the cell's origin, while
 | 
|---|
| 2957 |     \a cr specifies the cell's geometry in content coordinates.
 | 
|---|
| 2958 | */
 | 
|---|
| 2959 | 
 | 
|---|
| 2960 | void QTable::paintFocus( QPainter *p, const QRect &cr )
 | 
|---|
| 2961 | {
 | 
|---|
| 2962 |     if ( !hasFocus() && !viewport()->hasFocus() )
 | 
|---|
| 2963 |         return;
 | 
|---|
| 2964 |     QRect focusRect( 0, 0, cr.width(), cr.height() );
 | 
|---|
| 2965 |     if ( focusStyle() == SpreadSheet ) {
 | 
|---|
| 2966 |         p->setPen( QPen( black, 1 ) );
 | 
|---|
| 2967 |         p->setBrush( NoBrush );
 | 
|---|
| 2968 |         p->drawRect( focusRect.x(), focusRect.y(), focusRect.width() - 1, focusRect.height() - 1 );
 | 
|---|
| 2969 |         p->drawRect( focusRect.x() - 1, focusRect.y() - 1, focusRect.width() + 1, focusRect.height() + 1 );
 | 
|---|
| 2970 |     } else {
 | 
|---|
| 2971 |         QColor c = isSelected( curRow, curCol, FALSE ) ?
 | 
|---|
| 2972 |                              colorGroup().highlight() : colorGroup().base();
 | 
|---|
| 2973 |         style().drawPrimitive( QStyle::PE_FocusRect, p, focusRect, colorGroup(),
 | 
|---|
| 2974 |                                ( isSelected( curRow, curCol, FALSE ) ?
 | 
|---|
| 2975 |                                  QStyle::Style_FocusAtBorder :
 | 
|---|
| 2976 |                                  QStyle::Style_Default ),
 | 
|---|
| 2977 |                                  QStyleOption(c) );
 | 
|---|
| 2978 |     }
 | 
|---|
| 2979 | }
 | 
|---|
| 2980 | 
 | 
|---|
| 2981 | /*!
 | 
|---|
| 2982 |     This function fills the \a cw pixels wide and \a ch pixels high
 | 
|---|
| 2983 |     rectangle starting at position \a cx, \a cy with the background
 | 
|---|
| 2984 |     color using the painter \a p.
 | 
|---|
| 2985 | 
 | 
|---|
| 2986 |     paintEmptyArea() is invoked by drawContents() to erase or fill
 | 
|---|
| 2987 |     unused areas.
 | 
|---|
| 2988 | */
 | 
|---|
| 2989 | 
 | 
|---|
| 2990 | void QTable::paintEmptyArea( QPainter *p, int cx, int cy, int cw, int ch )
 | 
|---|
| 2991 | {
 | 
|---|
| 2992 |     // Regions work with shorts, so avoid an overflow and adjust the
 | 
|---|
| 2993 |     // table size to the visible size
 | 
|---|
| 2994 |     QSize ts( tableSize() );
 | 
|---|
| 2995 |     ts.setWidth( QMIN( ts.width(), visibleWidth() ) );
 | 
|---|
| 2996 |     ts.setHeight( QMIN( ts.height(), visibleHeight() ) );
 | 
|---|
| 2997 | 
 | 
|---|
| 2998 |     // Region of the rect we should draw, calculated in viewport
 | 
|---|
| 2999 |     // coordinates, as a region can't handle bigger coordinates
 | 
|---|
| 3000 |     contentsToViewport2( cx, cy, cx, cy );
 | 
|---|
| 3001 |     QRegion reg( QRect( cx, cy, cw, ch ) );
 | 
|---|
| 3002 | 
 | 
|---|
| 3003 |     // Subtract the table from it
 | 
|---|
| 3004 |     reg = reg.subtract( QRect( QPoint( 0, 0 ), ts ) );
 | 
|---|
| 3005 | 
 | 
|---|
| 3006 |     // And draw the rectangles (transformed inc contents coordinates as needed)
 | 
|---|
| 3007 |     QMemArray<QRect> r = reg.rects();
 | 
|---|
| 3008 |     for ( int i = 0; i < (int)r.count(); ++i )
 | 
|---|
| 3009 |         p->fillRect( QRect(viewportToContents2(r[i].topLeft()),r[i].size()), viewport()->backgroundBrush() );
 | 
|---|
| 3010 | }
 | 
|---|
| 3011 | 
 | 
|---|
| 3012 | /*!
 | 
|---|
| 3013 |     Returns the QTableItem representing the contents of the cell at \a
 | 
|---|
| 3014 |     row, \a col.
 | 
|---|
| 3015 | 
 | 
|---|
| 3016 |     If \a row or \a col are out of range or no content has been set
 | 
|---|
| 3017 |     for this cell, item() returns 0.
 | 
|---|
| 3018 | 
 | 
|---|
| 3019 |     If you don't use \l{QTableItem}s you may need to reimplement this
 | 
|---|
| 3020 |     function: see the notes on large tables.
 | 
|---|
| 3021 | 
 | 
|---|
| 3022 |     \sa setItem()
 | 
|---|
| 3023 | */
 | 
|---|
| 3024 | 
 | 
|---|
| 3025 | QTableItem *QTable::item( int row, int col ) const
 | 
|---|
| 3026 | {
 | 
|---|
| 3027 |     if ( row < 0 || col < 0 || row > numRows() - 1 ||
 | 
|---|
| 3028 |          col > numCols() - 1 || row * col >= (int)contents.size() )
 | 
|---|
| 3029 |         return 0;
 | 
|---|
| 3030 | 
 | 
|---|
| 3031 |     return contents[ indexOf( row, col ) ];     // contents array lookup
 | 
|---|
| 3032 | }
 | 
|---|
| 3033 | 
 | 
|---|
| 3034 | /*!
 | 
|---|
| 3035 |     Inserts the table item \a item into the table at row \a row,
 | 
|---|
| 3036 |     column \a col, and repaints the cell. If a table item already
 | 
|---|
| 3037 |     exists in this cell it is deleted and replaced with \a item. The
 | 
|---|
| 3038 |     table takes ownership of the table item.
 | 
|---|
| 3039 | 
 | 
|---|
| 3040 |     If you don't use \l{QTableItem}s you may need to reimplement this
 | 
|---|
| 3041 |     function: see the notes on large tables.
 | 
|---|
| 3042 | 
 | 
|---|
| 3043 |     \sa item() takeItem()
 | 
|---|
| 3044 | */
 | 
|---|
| 3045 | 
 | 
|---|
| 3046 | void QTable::setItem( int row, int col, QTableItem *item )
 | 
|---|
| 3047 | {
 | 
|---|
| 3048 |     if ( !item )
 | 
|---|
| 3049 |         return;
 | 
|---|
| 3050 | 
 | 
|---|
| 3051 |     if ( (int)contents.size() != numRows() * numCols() )
 | 
|---|
| 3052 |         resizeData( numRows() * numCols() );
 | 
|---|
| 3053 | 
 | 
|---|
| 3054 |     int orow = item->row();
 | 
|---|
| 3055 |     int ocol = item->col();
 | 
|---|
| 3056 |     clearCell( row, col );
 | 
|---|
| 3057 | 
 | 
|---|
| 3058 |     contents.insert( indexOf( row, col ), item );
 | 
|---|
| 3059 |     item->setRow( row );
 | 
|---|
| 3060 |     item->setCol( col );
 | 
|---|
| 3061 |     item->t = this;
 | 
|---|
| 3062 |     updateCell( row, col );
 | 
|---|
| 3063 |     if ( qt_update_cell_widget )
 | 
|---|
| 3064 |         item->updateEditor( orow, ocol );
 | 
|---|
| 3065 | 
 | 
|---|
| 3066 |     if ( row == curRow && col == curCol && item->editType() == QTableItem::WhenCurrent ) {
 | 
|---|
| 3067 |         if ( beginEdit( row, col, FALSE ) )
 | 
|---|
| 3068 |             setEditMode( Editing, row, col );
 | 
|---|
| 3069 |     }
 | 
|---|
| 3070 | }
 | 
|---|
| 3071 | 
 | 
|---|
| 3072 | /*!
 | 
|---|
| 3073 |     Removes the QTableItem at \a row, \a col.
 | 
|---|
| 3074 | 
 | 
|---|
| 3075 |     If you don't use \l{QTableItem}s you may need to reimplement this
 | 
|---|
| 3076 |     function: see the notes on large tables.
 | 
|---|
| 3077 | */
 | 
|---|
| 3078 | 
 | 
|---|
| 3079 | void QTable::clearCell( int row, int col )
 | 
|---|
| 3080 | {
 | 
|---|
| 3081 |     if ( (int)contents.size() != numRows() * numCols() )
 | 
|---|
| 3082 |         resizeData( numRows() * numCols() );
 | 
|---|
| 3083 |     clearCellWidget( row, col );
 | 
|---|
| 3084 |     contents.setAutoDelete( TRUE );
 | 
|---|
| 3085 |     contents.remove( indexOf( row, col ) );
 | 
|---|
| 3086 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 3087 | }
 | 
|---|
| 3088 | 
 | 
|---|
| 3089 | /*!
 | 
|---|
| 3090 |     Sets the text in the cell at \a row, \a col to \a text.
 | 
|---|
| 3091 | 
 | 
|---|
| 3092 |     If the cell does not contain a table item a QTableItem is created
 | 
|---|
| 3093 |     with an \link QTableItem::EditType EditType\endlink of \c OnTyping,
 | 
|---|
| 3094 |     otherwise the existing table item's text (if any) is replaced with
 | 
|---|
| 3095 |     \a text.
 | 
|---|
| 3096 | 
 | 
|---|
| 3097 |     \sa text() setPixmap() setItem() QTableItem::setText()
 | 
|---|
| 3098 | */
 | 
|---|
| 3099 | 
 | 
|---|
| 3100 | void QTable::setText( int row, int col, const QString &text )
 | 
|---|
| 3101 | {
 | 
|---|
| 3102 |     QTableItem *itm = item( row, col );
 | 
|---|
| 3103 |     if ( itm ) {
 | 
|---|
| 3104 |         itm->setText( text );
 | 
|---|
| 3105 |         itm->updateEditor( row, col );
 | 
|---|
| 3106 |         updateCell( row, col );
 | 
|---|
| 3107 |     } else {
 | 
|---|
| 3108 |         QTableItem *i = new QTableItem( this, QTableItem::OnTyping,
 | 
|---|
| 3109 |                                         text, QPixmap() );
 | 
|---|
| 3110 |         setItem( row, col, i );
 | 
|---|
| 3111 |     }
 | 
|---|
| 3112 | }
 | 
|---|
| 3113 | 
 | 
|---|
| 3114 | /*!
 | 
|---|
| 3115 |     Sets the pixmap in the cell at \a row, \a col to \a pix.
 | 
|---|
| 3116 | 
 | 
|---|
| 3117 |     If the cell does not contain a table item a QTableItem is created
 | 
|---|
| 3118 |     with an \link QTableItem::EditType EditType\endlink of \c OnTyping,
 | 
|---|
| 3119 |     otherwise the existing table item's pixmap (if any) is replaced
 | 
|---|
| 3120 |     with \a pix.
 | 
|---|
| 3121 | 
 | 
|---|
| 3122 |     Note that \l{QComboTableItem}s and \l{QCheckTableItem}s don't show
 | 
|---|
| 3123 |     pixmaps.
 | 
|---|
| 3124 | 
 | 
|---|
| 3125 |     \sa pixmap() setText() setItem() QTableItem::setPixmap()
 | 
|---|
| 3126 | */
 | 
|---|
| 3127 | 
 | 
|---|
| 3128 | void QTable::setPixmap( int row, int col, const QPixmap &pix )
 | 
|---|
| 3129 | {
 | 
|---|
| 3130 |     QTableItem *itm = item( row, col );
 | 
|---|
| 3131 |     if ( itm ) {
 | 
|---|
| 3132 |         itm->setPixmap( pix );
 | 
|---|
| 3133 |         updateCell( row, col );
 | 
|---|
| 3134 |     } else {
 | 
|---|
| 3135 |         QTableItem *i = new QTableItem( this, QTableItem::OnTyping,
 | 
|---|
| 3136 |                                         QString::null, pix );
 | 
|---|
| 3137 |         setItem( row, col, i );
 | 
|---|
| 3138 |     }
 | 
|---|
| 3139 | }
 | 
|---|
| 3140 | 
 | 
|---|
| 3141 | /*!
 | 
|---|
| 3142 |     Returns the text in the cell at \a row, \a col, or QString::null
 | 
|---|
| 3143 |     if the relevant item does not exist or has no text.
 | 
|---|
| 3144 | 
 | 
|---|
| 3145 |     \sa setText() setPixmap()
 | 
|---|
| 3146 | */
 | 
|---|
| 3147 | 
 | 
|---|
| 3148 | QString QTable::text( int row, int col ) const
 | 
|---|
| 3149 | {
 | 
|---|
| 3150 |     QTableItem *itm = item( row, col );
 | 
|---|
| 3151 |     if ( itm )
 | 
|---|
| 3152 |         return itm->text();
 | 
|---|
| 3153 |     return QString::null;
 | 
|---|
| 3154 | }
 | 
|---|
| 3155 | 
 | 
|---|
| 3156 | /*!
 | 
|---|
| 3157 |     Returns the pixmap set for the cell at \a row, \a col, or a
 | 
|---|
| 3158 |     null-pixmap if the cell contains no pixmap.
 | 
|---|
| 3159 | 
 | 
|---|
| 3160 |     \sa setPixmap()
 | 
|---|
| 3161 | */
 | 
|---|
| 3162 | 
 | 
|---|
| 3163 | QPixmap QTable::pixmap( int row, int col ) const
 | 
|---|
| 3164 | {
 | 
|---|
| 3165 |     QTableItem *itm = item( row, col );
 | 
|---|
| 3166 |     if ( itm )
 | 
|---|
| 3167 |         return itm->pixmap();
 | 
|---|
| 3168 |     return QPixmap();
 | 
|---|
| 3169 | }
 | 
|---|
| 3170 | 
 | 
|---|
| 3171 | /*!
 | 
|---|
| 3172 |     Moves the focus to the cell at \a row, \a col.
 | 
|---|
| 3173 | 
 | 
|---|
| 3174 |     \sa currentRow() currentColumn()
 | 
|---|
| 3175 | */
 | 
|---|
| 3176 | 
 | 
|---|
| 3177 | void QTable::setCurrentCell( int row, int col )
 | 
|---|
| 3178 | {
 | 
|---|
| 3179 |     setCurrentCell( row, col, TRUE, TRUE );
 | 
|---|
| 3180 | }
 | 
|---|
| 3181 | 
 | 
|---|
| 3182 | // need to use a define, as leftMargin() is protected
 | 
|---|
| 3183 | #define VERTICALMARGIN \
 | 
|---|
| 3184 | ( QApplication::reverseLayout() ? \
 | 
|---|
| 3185 |        rightMargin() \
 | 
|---|
| 3186 |        : \
 | 
|---|
| 3187 |        leftMargin() \
 | 
|---|
| 3188 | )
 | 
|---|
| 3189 | 
 | 
|---|
| 3190 | /*! \internal */
 | 
|---|
| 3191 | 
 | 
|---|
| 3192 | void QTable::setCurrentCell( int row, int col, bool updateSelections, bool ensureVisible )
 | 
|---|
| 3193 | {
 | 
|---|
| 3194 |     QTableItem *oldItem = item( curRow, curCol );
 | 
|---|
| 3195 | 
 | 
|---|
| 3196 |     if ( row > numRows() - 1 )
 | 
|---|
| 3197 |         row = numRows() - 1;
 | 
|---|
| 3198 |     if ( col > numCols() - 1 )
 | 
|---|
| 3199 |         col = numCols() - 1;
 | 
|---|
| 3200 | 
 | 
|---|
| 3201 |     if ( curRow == row && curCol == col )
 | 
|---|
| 3202 |         return;
 | 
|---|
| 3203 | 
 | 
|---|
| 3204 | 
 | 
|---|
| 3205 |     QTableItem *itm = oldItem;
 | 
|---|
| 3206 |     if ( itm && itm->editType() != QTableItem::Always && itm->editType() != QTableItem::Never )
 | 
|---|
| 3207 |         endEdit( curRow, curCol, TRUE, FALSE );
 | 
|---|
| 3208 |     int oldRow = curRow;
 | 
|---|
| 3209 |     int oldCol = curCol;
 | 
|---|
| 3210 |     curRow = row;
 | 
|---|
| 3211 |     curCol = col;
 | 
|---|
| 3212 |     repaintCell( oldRow, oldCol );
 | 
|---|
| 3213 |     repaintCell( curRow, curCol );
 | 
|---|
| 3214 |     if ( ensureVisible )
 | 
|---|
| 3215 |         ensureCellVisible( curRow, curCol );
 | 
|---|
| 3216 |     emit currentChanged( row, col );
 | 
|---|
| 3217 | 
 | 
|---|
| 3218 |     if ( oldCol != curCol ) {
 | 
|---|
| 3219 |         if ( !isColumnSelected( oldCol ) )
 | 
|---|
| 3220 |             topHeader->setSectionState( oldCol, QTableHeader::Normal );
 | 
|---|
| 3221 |         else if ( isRowSelection( selectionMode() ) )
 | 
|---|
| 3222 |             topHeader->setSectionState( oldCol, QTableHeader::Selected );
 | 
|---|
| 3223 |         topHeader->setSectionState( curCol, isColumnSelected( curCol, TRUE ) ?
 | 
|---|
| 3224 |                                     QTableHeader::Selected : QTableHeader::Bold );
 | 
|---|
| 3225 |     }
 | 
|---|
| 3226 | 
 | 
|---|
| 3227 |     if ( oldRow != curRow ) {
 | 
|---|
| 3228 |         if ( !isRowSelected( oldRow ) )
 | 
|---|
| 3229 |             leftHeader->setSectionState( oldRow, QTableHeader::Normal );
 | 
|---|
| 3230 |         leftHeader->setSectionState( curRow, isRowSelected( curRow, TRUE ) ?
 | 
|---|
| 3231 |                                      QTableHeader::Selected : QTableHeader::Bold );
 | 
|---|
| 3232 |     }
 | 
|---|
| 3233 | 
 | 
|---|
| 3234 |     itm = item( curRow, curCol );
 | 
|---|
| 3235 | 
 | 
|---|
| 3236 |     QPoint cellPos( columnPos( curCol ) + leftMargin() - contentsX(),
 | 
|---|
| 3237 |                     rowPos( curRow ) + topMargin() - contentsY() );
 | 
|---|
| 3238 |     setMicroFocusHint( cellPos.x(), cellPos.y(), columnWidth( curCol ),
 | 
|---|
| 3239 |                        rowHeight( curRow ), ( itm && itm->editType() != QTableItem::Never ) );
 | 
|---|
| 3240 | 
 | 
|---|
| 3241 |     if ( cellWidget( oldRow, oldCol ) &&
 | 
|---|
| 3242 |          cellWidget( oldRow, oldCol )->hasFocus() )
 | 
|---|
| 3243 |         viewport()->setFocus();
 | 
|---|
| 3244 | 
 | 
|---|
| 3245 |     if ( itm && itm->editType() == QTableItem::WhenCurrent ) {
 | 
|---|
| 3246 |         if ( beginEdit( curRow, curCol, FALSE ) )
 | 
|---|
| 3247 |             setEditMode( Editing, row, col );
 | 
|---|
| 3248 |     } else if ( itm && itm->editType() == QTableItem::Always ) {
 | 
|---|
| 3249 |         if ( cellWidget( itm->row(), itm->col() ) )
 | 
|---|
| 3250 |             cellWidget( itm->row(), itm->col() )->setFocus();
 | 
|---|
| 3251 |     }
 | 
|---|
| 3252 | 
 | 
|---|
| 3253 |     if ( updateSelections && isRowSelection( selectionMode() ) &&
 | 
|---|
| 3254 |          !isSelected( curRow, curCol, FALSE ) ) {
 | 
|---|
| 3255 |         if ( selectionMode() == QTable::SingleRow )
 | 
|---|
| 3256 |             clearSelection();
 | 
|---|
| 3257 |         currentSel = new QTableSelection();
 | 
|---|
| 3258 |         selections.append( currentSel );
 | 
|---|
| 3259 |         currentSel->init( curRow, 0 );
 | 
|---|
| 3260 |         currentSel->expandTo( curRow, numCols() - 1 );
 | 
|---|
| 3261 |         repaintSelections( 0, currentSel );
 | 
|---|
| 3262 |     }
 | 
|---|
| 3263 | }
 | 
|---|
| 3264 | 
 | 
|---|
| 3265 | /*!
 | 
|---|
| 3266 |     Scrolls the table until the cell at \a row, \a col becomes
 | 
|---|
| 3267 |     visible.
 | 
|---|
| 3268 | */
 | 
|---|
| 3269 | 
 | 
|---|
| 3270 | void QTable::ensureCellVisible( int row, int col )
 | 
|---|
| 3271 | {
 | 
|---|
| 3272 |     if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() )
 | 
|---|
| 3273 |         return;
 | 
|---|
| 3274 |     int cw = columnWidth( col );
 | 
|---|
| 3275 |     int rh = rowHeight( row );
 | 
|---|
| 3276 |     if ( cw < visibleWidth() )
 | 
|---|
| 3277 |         ensureVisible( columnPos( col ) + cw / 2, rowPos( row ) + rh / 2, cw / 2, rh / 2 );
 | 
|---|
| 3278 |     else
 | 
|---|
| 3279 |         ensureVisible( columnPos( col ), rowPos( row ) + rh / 2, 0, rh / 2 );
 | 
|---|
| 3280 | }
 | 
|---|
| 3281 | 
 | 
|---|
| 3282 | /*!
 | 
|---|
| 3283 |     Returns TRUE if the cell at \a row, \a col is selected; otherwise
 | 
|---|
| 3284 |     returns FALSE.
 | 
|---|
| 3285 | 
 | 
|---|
| 3286 |     \sa isRowSelected() isColumnSelected()
 | 
|---|
| 3287 | */
 | 
|---|
| 3288 | 
 | 
|---|
| 3289 | bool QTable::isSelected( int row, int col ) const
 | 
|---|
| 3290 | {
 | 
|---|
| 3291 |     return isSelected( row, col, TRUE );
 | 
|---|
| 3292 | }
 | 
|---|
| 3293 | 
 | 
|---|
| 3294 | /*! \internal */
 | 
|---|
| 3295 | 
 | 
|---|
| 3296 | bool QTable::isSelected( int row, int col, bool includeCurrent ) const
 | 
|---|
| 3297 | {
 | 
|---|
| 3298 |     QPtrListIterator<QTableSelection> it( selections );
 | 
|---|
| 3299 |     QTableSelection *s;
 | 
|---|
| 3300 |     while ( ( s = it.current() ) != 0 ) {
 | 
|---|
| 3301 |         ++it;
 | 
|---|
| 3302 |         if ( s->isActive() &&
 | 
|---|
| 3303 |              row >= s->topRow() &&
 | 
|---|
| 3304 |              row <= s->bottomRow() &&
 | 
|---|
| 3305 |              col >= s->leftCol() &&
 | 
|---|
| 3306 |              col <= s->rightCol() )
 | 
|---|
| 3307 |             return TRUE;
 | 
|---|
| 3308 |         if ( includeCurrent && row == currentRow() && col == currentColumn() )
 | 
|---|
| 3309 |             return TRUE;
 | 
|---|
| 3310 |     }
 | 
|---|
| 3311 |     return FALSE;
 | 
|---|
| 3312 | }
 | 
|---|
| 3313 | 
 | 
|---|
| 3314 | /*!
 | 
|---|
| 3315 |     Returns TRUE if row \a row is selected; otherwise returns FALSE.
 | 
|---|
| 3316 | 
 | 
|---|
| 3317 |     If \a full is FALSE (the default), 'row is selected' means that at
 | 
|---|
| 3318 |     least one cell in the row is selected. If \a full is TRUE, then 'row
 | 
|---|
| 3319 |     is selected' means every cell in the row is selected.
 | 
|---|
| 3320 | 
 | 
|---|
| 3321 |     \sa isColumnSelected() isSelected()
 | 
|---|
| 3322 | */
 | 
|---|
| 3323 | 
 | 
|---|
| 3324 | bool QTable::isRowSelected( int row, bool full ) const
 | 
|---|
| 3325 | {
 | 
|---|
| 3326 |     if ( !full ) {
 | 
|---|
| 3327 |         QPtrListIterator<QTableSelection> it( selections );
 | 
|---|
| 3328 |         QTableSelection *s;
 | 
|---|
| 3329 |         while ( ( s = it.current() ) != 0 ) {
 | 
|---|
| 3330 |             ++it;
 | 
|---|
| 3331 |             if ( s->isActive() &&
 | 
|---|
| 3332 |                  row >= s->topRow() &&
 | 
|---|
| 3333 |                  row <= s->bottomRow() )
 | 
|---|
| 3334 |             return TRUE;
 | 
|---|
| 3335 |         if ( row == currentRow() )
 | 
|---|
| 3336 |             return TRUE;
 | 
|---|
| 3337 |         }
 | 
|---|
| 3338 |     } else {
 | 
|---|
| 3339 |         QPtrListIterator<QTableSelection> it( selections );
 | 
|---|
| 3340 |         QTableSelection *s;
 | 
|---|
| 3341 |         while ( ( s = it.current() ) != 0 ) {
 | 
|---|
| 3342 |             ++it;
 | 
|---|
| 3343 |             if ( s->isActive() &&
 | 
|---|
| 3344 |                  row >= s->topRow() &&
 | 
|---|
| 3345 |                  row <= s->bottomRow() &&
 | 
|---|
| 3346 |                  s->leftCol() == 0 &&
 | 
|---|
| 3347 |                  s->rightCol() == numCols() - 1 )
 | 
|---|
| 3348 |                 return TRUE;
 | 
|---|
| 3349 |         }
 | 
|---|
| 3350 |     }
 | 
|---|
| 3351 |     return FALSE;
 | 
|---|
| 3352 | }
 | 
|---|
| 3353 | 
 | 
|---|
| 3354 | /*!
 | 
|---|
| 3355 |     Returns TRUE if column \a col is selected; otherwise returns FALSE.
 | 
|---|
| 3356 | 
 | 
|---|
| 3357 |     If \a full is FALSE (the default), 'column is selected' means that
 | 
|---|
| 3358 |     at least one cell in the column is selected. If \a full is TRUE,
 | 
|---|
| 3359 |     then 'column is selected' means every cell in the column is
 | 
|---|
| 3360 |     selected.
 | 
|---|
| 3361 | 
 | 
|---|
| 3362 |     \sa isRowSelected() isSelected()
 | 
|---|
| 3363 | */
 | 
|---|
| 3364 | 
 | 
|---|
| 3365 | bool QTable::isColumnSelected( int col, bool full ) const
 | 
|---|
| 3366 | {
 | 
|---|
| 3367 |     if ( !full ) {
 | 
|---|
| 3368 |         QPtrListIterator<QTableSelection> it( selections );
 | 
|---|
| 3369 |         QTableSelection *s;
 | 
|---|
| 3370 |         while ( ( s = it.current() ) != 0 ) {
 | 
|---|
| 3371 |             ++it;
 | 
|---|
| 3372 |             if ( s->isActive() &&
 | 
|---|
| 3373 |                  col >= s->leftCol() &&
 | 
|---|
| 3374 |                  col <= s->rightCol() )
 | 
|---|
| 3375 |             return TRUE;
 | 
|---|
| 3376 |         if ( col == currentColumn() )
 | 
|---|
| 3377 |             return TRUE;
 | 
|---|
| 3378 |         }
 | 
|---|
| 3379 |     } else {
 | 
|---|
| 3380 |         QPtrListIterator<QTableSelection> it( selections );
 | 
|---|
| 3381 |         QTableSelection *s;
 | 
|---|
| 3382 |         while ( ( s = it.current() ) != 0 ) {
 | 
|---|
| 3383 |             ++it;
 | 
|---|
| 3384 |             if ( s->isActive() &&
 | 
|---|
| 3385 |                  col >= s->leftCol() &&
 | 
|---|
| 3386 |                  col <= s->rightCol() &&
 | 
|---|
| 3387 |                  s->topRow() == 0 &&
 | 
|---|
| 3388 |                  s->bottomRow() == numRows() - 1 )
 | 
|---|
| 3389 |                 return TRUE;
 | 
|---|
| 3390 |         }
 | 
|---|
| 3391 |     }
 | 
|---|
| 3392 |     return FALSE;
 | 
|---|
| 3393 | }
 | 
|---|
| 3394 | 
 | 
|---|
| 3395 | /*!
 | 
|---|
| 3396 |     \property QTable::numSelections
 | 
|---|
| 3397 |     \brief The number of selections.
 | 
|---|
| 3398 | 
 | 
|---|
| 3399 |     \sa currentSelection()
 | 
|---|
| 3400 | */
 | 
|---|
| 3401 | 
 | 
|---|
| 3402 | int QTable::numSelections() const
 | 
|---|
| 3403 | {
 | 
|---|
| 3404 |     return selections.count();
 | 
|---|
| 3405 | }
 | 
|---|
| 3406 | 
 | 
|---|
| 3407 | /*!
 | 
|---|
| 3408 |     Returns selection number \a num, or an inactive QTableSelection if \a
 | 
|---|
| 3409 |     num is out of range (see QTableSelection::isActive()).
 | 
|---|
| 3410 | */
 | 
|---|
| 3411 | 
 | 
|---|
| 3412 | QTableSelection QTable::selection( int num ) const
 | 
|---|
| 3413 | {
 | 
|---|
| 3414 |     if ( num < 0 || num >= (int)selections.count() )
 | 
|---|
| 3415 |         return QTableSelection();
 | 
|---|
| 3416 | 
 | 
|---|
| 3417 |     QTableSelection *s = ( (QTable*)this )->selections.at( num );
 | 
|---|
| 3418 |     return *s;
 | 
|---|
| 3419 | }
 | 
|---|
| 3420 | 
 | 
|---|
| 3421 | /*!
 | 
|---|
| 3422 |     Adds a selection described by \a s to the table and returns its
 | 
|---|
| 3423 |     number or -1 if the selection is invalid.
 | 
|---|
| 3424 | 
 | 
|---|
| 3425 |     Remember to call QTableSelection::init() and
 | 
|---|
| 3426 |     QTableSelection::expandTo() to make the selection valid (see also
 | 
|---|
| 3427 |     QTableSelection::isActive(), or use the
 | 
|---|
| 3428 |     QTableSelection(int,int,int,int) constructor).
 | 
|---|
| 3429 | 
 | 
|---|
| 3430 |     \sa numSelections() removeSelection() clearSelection()
 | 
|---|
| 3431 | */
 | 
|---|
| 3432 | 
 | 
|---|
| 3433 | int QTable::addSelection( const QTableSelection &s )
 | 
|---|
| 3434 | {
 | 
|---|
| 3435 |     if ( !s.isActive() )
 | 
|---|
| 3436 |         return -1;
 | 
|---|
| 3437 | 
 | 
|---|
| 3438 |     const int maxr = numRows()-1;
 | 
|---|
| 3439 |     const int maxc = numCols()-1;
 | 
|---|
| 3440 |     QTableSelection *sel = new QTableSelection( QMIN(s.anchorRow(), maxr), QMIN(s.anchorCol(), maxc),
 | 
|---|
| 3441 |                                     QMIN(s.bottomRow(), maxr), QMIN(s.rightCol(), maxc) );
 | 
|---|
| 3442 | 
 | 
|---|
| 3443 |     selections.append( sel );
 | 
|---|
| 3444 | 
 | 
|---|
| 3445 |     repaintSelections( 0, sel, TRUE, TRUE );
 | 
|---|
| 3446 | 
 | 
|---|
| 3447 |     emit selectionChanged();
 | 
|---|
| 3448 | 
 | 
|---|
| 3449 |     return selections.count() - 1;
 | 
|---|
| 3450 | }
 | 
|---|
| 3451 | 
 | 
|---|
| 3452 | /*!
 | 
|---|
| 3453 |     If the table has a selection, \a s, this selection is removed from
 | 
|---|
| 3454 |     the table.
 | 
|---|
| 3455 | 
 | 
|---|
| 3456 |     \sa addSelection() numSelections()
 | 
|---|
| 3457 | */
 | 
|---|
| 3458 | 
 | 
|---|
| 3459 | void QTable::removeSelection( const QTableSelection &s )
 | 
|---|
| 3460 | {
 | 
|---|
| 3461 |     selections.setAutoDelete( FALSE );
 | 
|---|
| 3462 |     for ( QTableSelection *sel = selections.first(); sel; sel = selections.next() ) {
 | 
|---|
| 3463 |         if ( s == *sel ) {
 | 
|---|
| 3464 |             selections.removeRef( sel );
 | 
|---|
| 3465 |             repaintSelections( sel, 0, TRUE, TRUE );
 | 
|---|
| 3466 |             if ( sel == currentSel )
 | 
|---|
| 3467 |                 currentSel = 0;
 | 
|---|
| 3468 |             delete sel;
 | 
|---|
| 3469 |         }
 | 
|---|
| 3470 |     }
 | 
|---|
| 3471 |     selections.setAutoDelete( TRUE );
 | 
|---|
| 3472 |     emit selectionChanged();
 | 
|---|
| 3473 | }
 | 
|---|
| 3474 | 
 | 
|---|
| 3475 | /*!
 | 
|---|
| 3476 |     \overload
 | 
|---|
| 3477 | 
 | 
|---|
| 3478 |     Removes selection number \a num from the table.
 | 
|---|
| 3479 | 
 | 
|---|
| 3480 |     \sa numSelections() addSelection() clearSelection()
 | 
|---|
| 3481 | */
 | 
|---|
| 3482 | 
 | 
|---|
| 3483 | void QTable::removeSelection( int num )
 | 
|---|
| 3484 | {
 | 
|---|
| 3485 |     if ( num < 0 || num >= (int)selections.count() )
 | 
|---|
| 3486 |         return;
 | 
|---|
| 3487 | 
 | 
|---|
| 3488 |     QTableSelection *s = selections.at( num );
 | 
|---|
| 3489 |     if ( s == currentSel )
 | 
|---|
| 3490 |         currentSel = 0;
 | 
|---|
| 3491 |     selections.removeRef( s );
 | 
|---|
| 3492 |     repaintContents( FALSE );
 | 
|---|
| 3493 | }
 | 
|---|
| 3494 | 
 | 
|---|
| 3495 | /*!
 | 
|---|
| 3496 |     Returns the number of the current selection or -1 if there is no
 | 
|---|
| 3497 |     current selection.
 | 
|---|
| 3498 | 
 | 
|---|
| 3499 |     \sa numSelections()
 | 
|---|
| 3500 | */
 | 
|---|
| 3501 | 
 | 
|---|
| 3502 | int QTable::currentSelection() const
 | 
|---|
| 3503 | {
 | 
|---|
| 3504 |     if ( !currentSel )
 | 
|---|
| 3505 |         return -1;
 | 
|---|
| 3506 |     return ( (QTable*)this )->selections.findRef( currentSel );
 | 
|---|
| 3507 | }
 | 
|---|
| 3508 | 
 | 
|---|
| 3509 | /*! Selects the range starting at \a start_row and \a start_col and
 | 
|---|
| 3510 |   ending at \a end_row and \a end_col.
 | 
|---|
| 3511 | 
 | 
|---|
| 3512 |   \sa QTableSelection
 | 
|---|
| 3513 | */
 | 
|---|
| 3514 | 
 | 
|---|
| 3515 | void QTable::selectCells( int start_row, int start_col, int end_row, int end_col )
 | 
|---|
| 3516 | {
 | 
|---|
| 3517 |     const int maxr = numRows()-1;
 | 
|---|
| 3518 |     const int maxc = numCols()-1;
 | 
|---|
| 3519 | 
 | 
|---|
| 3520 |     start_row = QMIN( maxr, QMAX( 0, start_row ) );
 | 
|---|
| 3521 |     start_col = QMIN( maxc, QMAX( 0, start_col ) );
 | 
|---|
| 3522 |     end_row = QMIN( maxr, end_row );
 | 
|---|
| 3523 |     end_col = QMIN( maxc, end_col );
 | 
|---|
| 3524 |     QTableSelection sel( start_row, start_col, end_row, end_col );
 | 
|---|
| 3525 |     addSelection( sel );
 | 
|---|
| 3526 | }
 | 
|---|
| 3527 | 
 | 
|---|
| 3528 | /*! Selects the row \a row.
 | 
|---|
| 3529 | 
 | 
|---|
| 3530 |   \sa QTableSelection
 | 
|---|
| 3531 | */
 | 
|---|
| 3532 | 
 | 
|---|
| 3533 | // ### Make this virtual in 4.0 and remove hack for QDataTable
 | 
|---|
| 3534 | void QTable::selectRow( int row )
 | 
|---|
| 3535 | {
 | 
|---|
| 3536 |     row = QMIN(numRows()-1, row);
 | 
|---|
| 3537 |     if ( row < 0 )
 | 
|---|
| 3538 |         return;
 | 
|---|
| 3539 |     bool isDataTable = FALSE;
 | 
|---|
| 3540 | #ifndef QT_NO_SQL
 | 
|---|
| 3541 |     isDataTable = ::qt_cast<QDataTable*>(this) != 0;
 | 
|---|
| 3542 | #endif
 | 
|---|
| 3543 |     if ( isDataTable || selectionMode() == SingleRow ) {
 | 
|---|
| 3544 |         setCurrentCell( row, currentColumn() );
 | 
|---|
| 3545 |     } else {
 | 
|---|
| 3546 |         QTableSelection sel( row, 0, row, numCols() - 1 );
 | 
|---|
| 3547 |         addSelection( sel );
 | 
|---|
| 3548 |     }
 | 
|---|
| 3549 | }
 | 
|---|
| 3550 | 
 | 
|---|
| 3551 | /*! Selects the column \a col.
 | 
|---|
| 3552 | 
 | 
|---|
| 3553 |   \sa QTableSelection
 | 
|---|
| 3554 | */
 | 
|---|
| 3555 | 
 | 
|---|
| 3556 | // ### Make this virtual in 4.0
 | 
|---|
| 3557 | void QTable::selectColumn( int col )
 | 
|---|
| 3558 | {
 | 
|---|
| 3559 |     col = QMIN(numCols()-1, col);
 | 
|---|
| 3560 |     QTableSelection sel( 0, col, numRows() - 1, col );
 | 
|---|
| 3561 |     addSelection( sel );
 | 
|---|
| 3562 | }
 | 
|---|
| 3563 | 
 | 
|---|
| 3564 | /*! \reimp
 | 
|---|
| 3565 | */
 | 
|---|
| 3566 | void QTable::contentsMousePressEvent( QMouseEvent* e )
 | 
|---|
| 3567 | {
 | 
|---|
| 3568 |     contentsMousePressEventEx( e );
 | 
|---|
| 3569 | }
 | 
|---|
| 3570 | 
 | 
|---|
| 3571 | void QTable::contentsMousePressEventEx( QMouseEvent* e )
 | 
|---|
| 3572 | {
 | 
|---|
| 3573 |     shouldClearSelection = FALSE;
 | 
|---|
| 3574 |     if ( isEditing() ) {
 | 
|---|
| 3575 |         if ( !cellGeometry( editRow, editCol ).contains( e->pos() ) ) {
 | 
|---|
| 3576 |             endEdit( editRow, editCol, TRUE, edMode != Editing );
 | 
|---|
| 3577 |         } else {
 | 
|---|
| 3578 |             e->ignore();
 | 
|---|
| 3579 |             return;
 | 
|---|
| 3580 |         }
 | 
|---|
| 3581 |     }
 | 
|---|
| 3582 | 
 | 
|---|
| 3583 |     d->redirectMouseEvent = FALSE;
 | 
|---|
| 3584 | 
 | 
|---|
| 3585 |     int tmpRow = rowAt( e->pos().y() );
 | 
|---|
| 3586 |     int tmpCol = columnAt( e->pos().x() );
 | 
|---|
| 3587 |     pressedRow = tmpRow;
 | 
|---|
| 3588 |     pressedCol = tmpCol;
 | 
|---|
| 3589 |     fixRow( tmpRow, e->pos().y() );
 | 
|---|
| 3590 |     fixCol( tmpCol, e->pos().x() );
 | 
|---|
| 3591 |     startDragCol = -1;
 | 
|---|
| 3592 |     startDragRow = -1;
 | 
|---|
| 3593 | 
 | 
|---|
| 3594 |     if ( isSelected( tmpRow, tmpCol ) ) {
 | 
|---|
| 3595 |         startDragCol = tmpCol;
 | 
|---|
| 3596 |         startDragRow = tmpRow;
 | 
|---|
| 3597 |         dragStartPos = e->pos();
 | 
|---|
| 3598 |     }
 | 
|---|
| 3599 | 
 | 
|---|
| 3600 |     QTableItem *itm = item( pressedRow, pressedCol );
 | 
|---|
| 3601 |     if ( itm && !itm->isEnabled() ) {
 | 
|---|
| 3602 |         emit pressed( tmpRow, tmpCol, e->button(), e->pos() );
 | 
|---|
| 3603 |         return;
 | 
|---|
| 3604 |     }
 | 
|---|
| 3605 | 
 | 
|---|
| 3606 |     if ( ( e->state() & ShiftButton ) == ShiftButton ) {
 | 
|---|
| 3607 |         int oldRow = curRow;
 | 
|---|
| 3608 |         int oldCol = curCol;
 | 
|---|
| 3609 |         setCurrentCell( tmpRow, tmpCol, selMode == SingleRow, TRUE );
 | 
|---|
| 3610 |         if ( selMode != NoSelection && selMode != SingleRow ) {
 | 
|---|
| 3611 |             if ( !currentSel ) {
 | 
|---|
| 3612 |                 currentSel = new QTableSelection();
 | 
|---|
| 3613 |                 selections.append( currentSel );
 | 
|---|
| 3614 |                 if ( !isRowSelection( selectionMode() ) )
 | 
|---|
| 3615 |                     currentSel->init( oldRow, oldCol );
 | 
|---|
| 3616 |                 else
 | 
|---|
| 3617 |                     currentSel->init( oldRow, 0 );
 | 
|---|
| 3618 |             }
 | 
|---|
| 3619 |             QTableSelection oldSelection = *currentSel;
 | 
|---|
| 3620 |             if ( !isRowSelection( selectionMode() ) )
 | 
|---|
| 3621 |                 currentSel->expandTo( tmpRow, tmpCol );
 | 
|---|
| 3622 |             else
 | 
|---|
| 3623 |                 currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 3624 |             repaintSelections( &oldSelection, currentSel );
 | 
|---|
| 3625 |             emit selectionChanged();
 | 
|---|
| 3626 |         }
 | 
|---|
| 3627 |     } else if ( ( e->state() & ControlButton ) == ControlButton ) {
 | 
|---|
| 3628 |         setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 3629 |         if ( selMode != NoSelection ) {
 | 
|---|
| 3630 |             if ( selMode == Single || selMode == SingleRow && !isSelected( tmpRow, tmpCol, FALSE ) )
 | 
|---|
| 3631 |                 clearSelection();
 | 
|---|
| 3632 |             if ( !(selMode == SingleRow && isSelected( tmpRow, tmpCol, FALSE )) ) {
 | 
|---|
| 3633 |                 currentSel = new QTableSelection();
 | 
|---|
| 3634 |                 selections.append( currentSel );
 | 
|---|
| 3635 |                 if ( !isRowSelection( selectionMode() ) ) {
 | 
|---|
| 3636 |                     currentSel->init( tmpRow, tmpCol );
 | 
|---|
| 3637 |                     currentSel->expandTo( tmpRow, tmpCol );
 | 
|---|
| 3638 |                 } else {
 | 
|---|
| 3639 |                     currentSel->init( tmpRow, 0 );
 | 
|---|
| 3640 |                     currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 3641 |                     repaintSelections( 0, currentSel );
 | 
|---|
| 3642 |                 }
 | 
|---|
| 3643 |                 emit selectionChanged();
 | 
|---|
| 3644 |             }
 | 
|---|
| 3645 |         }
 | 
|---|
| 3646 |     } else {
 | 
|---|
| 3647 |         setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 3648 |         QTableItem *itm = item( tmpRow, tmpCol );
 | 
|---|
| 3649 |         if ( itm && itm->editType() == QTableItem::WhenCurrent ) {
 | 
|---|
| 3650 |             QWidget *w = cellWidget( tmpRow, tmpCol );
 | 
|---|
| 3651 |             if ( ::qt_cast<QComboBox*>(w) || ::qt_cast<QButton*>(w) ) {
 | 
|---|
| 3652 |                 QMouseEvent ev( e->type(), w->mapFromGlobal( e->globalPos() ),
 | 
|---|
| 3653 |                                 e->globalPos(), e->button(), e->state() );
 | 
|---|
| 3654 |                 QApplication::sendPostedEvents( w, 0 );
 | 
|---|
| 3655 |                 QApplication::sendEvent( w, &ev );
 | 
|---|
| 3656 |                 d->redirectMouseEvent = TRUE;
 | 
|---|
| 3657 |             }
 | 
|---|
| 3658 |         }
 | 
|---|
| 3659 |         if ( isSelected( tmpRow, tmpCol, FALSE ) ) {
 | 
|---|
| 3660 |             shouldClearSelection = TRUE;
 | 
|---|
| 3661 |         } else {
 | 
|---|
| 3662 |             bool b = signalsBlocked();
 | 
|---|
| 3663 |             if ( selMode != NoSelection )
 | 
|---|
| 3664 |                 blockSignals( TRUE );
 | 
|---|
| 3665 |             clearSelection();
 | 
|---|
| 3666 |             blockSignals( b );
 | 
|---|
| 3667 |             if ( selMode != NoSelection ) {
 | 
|---|
| 3668 |                 currentSel = new QTableSelection();
 | 
|---|
| 3669 |                 selections.append( currentSel );
 | 
|---|
| 3670 |                 if ( !isRowSelection( selectionMode() ) ) {
 | 
|---|
| 3671 |                     currentSel->init( tmpRow, tmpCol );
 | 
|---|
| 3672 |                     currentSel->expandTo( tmpRow, tmpCol );
 | 
|---|
| 3673 |                 } else {
 | 
|---|
| 3674 |                     currentSel->init( tmpRow, 0 );
 | 
|---|
| 3675 |                     currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 3676 |                     repaintSelections( 0, currentSel );
 | 
|---|
| 3677 |                 }
 | 
|---|
| 3678 |                 emit selectionChanged();
 | 
|---|
| 3679 |             }
 | 
|---|
| 3680 |         }
 | 
|---|
| 3681 |     }
 | 
|---|
| 3682 | 
 | 
|---|
| 3683 |     emit pressed( tmpRow, tmpCol, e->button(), e->pos() );
 | 
|---|
| 3684 | }
 | 
|---|
| 3685 | 
 | 
|---|
| 3686 | /*! \reimp
 | 
|---|
| 3687 | */
 | 
|---|
| 3688 | 
 | 
|---|
| 3689 | void QTable::contentsMouseDoubleClickEvent( QMouseEvent *e )
 | 
|---|
| 3690 | {
 | 
|---|
| 3691 |     if ( e->button() != LeftButton )
 | 
|---|
| 3692 |         return;
 | 
|---|
| 3693 |     if ( !isRowSelection( selectionMode() ) )
 | 
|---|
| 3694 |         clearSelection();
 | 
|---|
| 3695 |     int tmpRow = rowAt( e->pos().y() );
 | 
|---|
| 3696 |     int tmpCol = columnAt( e->pos().x() );
 | 
|---|
| 3697 |     QTableItem *itm = item( tmpRow, tmpCol );
 | 
|---|
| 3698 |     if ( itm && !itm->isEnabled() )
 | 
|---|
| 3699 |         return;
 | 
|---|
| 3700 |     if ( tmpRow != -1 && tmpCol != -1 ) {
 | 
|---|
| 3701 |         if ( beginEdit( tmpRow, tmpCol, FALSE ) )
 | 
|---|
| 3702 |             setEditMode( Editing, tmpRow, tmpCol );
 | 
|---|
| 3703 |     }
 | 
|---|
| 3704 | 
 | 
|---|
| 3705 |     emit doubleClicked( tmpRow, tmpCol, e->button(), e->pos() );
 | 
|---|
| 3706 | }
 | 
|---|
| 3707 | 
 | 
|---|
| 3708 | /*!
 | 
|---|
| 3709 |     Sets the current edit mode to \a mode, the current edit row to \a
 | 
|---|
| 3710 |     row and the current edit column to \a col.
 | 
|---|
| 3711 | 
 | 
|---|
| 3712 |     \sa EditMode
 | 
|---|
| 3713 | */
 | 
|---|
| 3714 | 
 | 
|---|
| 3715 | void QTable::setEditMode( EditMode mode, int row, int col )
 | 
|---|
| 3716 | {
 | 
|---|
| 3717 |     edMode = mode;
 | 
|---|
| 3718 |     editRow = row;
 | 
|---|
| 3719 |     editCol = col;
 | 
|---|
| 3720 | }
 | 
|---|
| 3721 | 
 | 
|---|
| 3722 | 
 | 
|---|
| 3723 | /*! \reimp
 | 
|---|
| 3724 | */
 | 
|---|
| 3725 | 
 | 
|---|
| 3726 | void QTable::contentsMouseMoveEvent( QMouseEvent *e )
 | 
|---|
| 3727 | {
 | 
|---|
| 3728 |     if ( (e->state() & MouseButtonMask) == NoButton )
 | 
|---|
| 3729 |         return;
 | 
|---|
| 3730 |     int tmpRow = rowAt( e->pos().y() );
 | 
|---|
| 3731 |     int tmpCol = columnAt( e->pos().x() );
 | 
|---|
| 3732 |     fixRow( tmpRow, e->pos().y() );
 | 
|---|
| 3733 |     fixCol( tmpCol, e->pos().x() );
 | 
|---|
| 3734 | 
 | 
|---|
| 3735 | #ifndef QT_NO_DRAGANDDROP
 | 
|---|
| 3736 |     if ( dragEnabled() && startDragRow != -1 && startDragCol != -1 ) {
 | 
|---|
| 3737 |         if (QPoint(dragStartPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
 | 
|---|
| 3738 |             startDrag();
 | 
|---|
| 3739 |         return;
 | 
|---|
| 3740 |     }
 | 
|---|
| 3741 | #endif
 | 
|---|
| 3742 |     if ( selectionMode() == MultiRow && ( e->state() & ControlButton ) == ControlButton )
 | 
|---|
| 3743 |         shouldClearSelection = FALSE;
 | 
|---|
| 3744 | 
 | 
|---|
| 3745 |     if ( shouldClearSelection ) {
 | 
|---|
| 3746 |         clearSelection();
 | 
|---|
| 3747 |         if ( selMode != NoSelection ) {
 | 
|---|
| 3748 |             currentSel = new QTableSelection();
 | 
|---|
| 3749 |             selections.append( currentSel );
 | 
|---|
| 3750 |             if ( !isRowSelection( selectionMode() ) )
 | 
|---|
| 3751 |                 currentSel->init( tmpRow, tmpCol );
 | 
|---|
| 3752 |             else
 | 
|---|
| 3753 |                 currentSel->init( tmpRow, 0 );
 | 
|---|
| 3754 |             emit selectionChanged();
 | 
|---|
| 3755 |         }
 | 
|---|
| 3756 |         shouldClearSelection = FALSE;
 | 
|---|
| 3757 |     }
 | 
|---|
| 3758 | 
 | 
|---|
| 3759 |     QPoint pos = mapFromGlobal( e->globalPos() );
 | 
|---|
| 3760 |     pos -= QPoint( leftHeader->width(), topHeader->height() );
 | 
|---|
| 3761 |     autoScrollTimer->stop();
 | 
|---|
| 3762 |     doAutoScroll();
 | 
|---|
| 3763 |     if ( pos.x() < 0 || pos.x() > visibleWidth() || pos.y() < 0 || pos.y() > visibleHeight() )
 | 
|---|
| 3764 |         autoScrollTimer->start( 100, TRUE );
 | 
|---|
| 3765 | }
 | 
|---|
| 3766 | 
 | 
|---|
| 3767 | /*! \internal
 | 
|---|
| 3768 |  */
 | 
|---|
| 3769 | 
 | 
|---|
| 3770 | void QTable::doValueChanged()
 | 
|---|
| 3771 | {
 | 
|---|
| 3772 |     emit valueChanged( editRow, editCol );
 | 
|---|
| 3773 | }
 | 
|---|
| 3774 | 
 | 
|---|
| 3775 | /*! \internal
 | 
|---|
| 3776 | */
 | 
|---|
| 3777 | 
 | 
|---|
| 3778 | void QTable::doAutoScroll()
 | 
|---|
| 3779 | {
 | 
|---|
| 3780 |     QPoint pos = QCursor::pos();
 | 
|---|
| 3781 |     pos = mapFromGlobal( pos );
 | 
|---|
| 3782 |     pos -= QPoint( leftHeader->width(), topHeader->height() );
 | 
|---|
| 3783 | 
 | 
|---|
| 3784 |     int tmpRow = curRow;
 | 
|---|
| 3785 |     int tmpCol = curCol;
 | 
|---|
| 3786 |     if ( pos.y() < 0 )
 | 
|---|
| 3787 |         tmpRow--;
 | 
|---|
| 3788 |     else if ( pos.y() > visibleHeight() )
 | 
|---|
| 3789 |         tmpRow++;
 | 
|---|
| 3790 |     if ( pos.x() < 0 )
 | 
|---|
| 3791 |         tmpCol--;
 | 
|---|
| 3792 |     else if ( pos.x() > visibleWidth() )
 | 
|---|
| 3793 |         tmpCol++;
 | 
|---|
| 3794 | 
 | 
|---|
| 3795 |     pos += QPoint( contentsX(), contentsY() );
 | 
|---|
| 3796 |     if ( tmpRow == curRow )
 | 
|---|
| 3797 |         tmpRow = rowAt( pos.y() );
 | 
|---|
| 3798 |     if ( tmpCol == curCol )
 | 
|---|
| 3799 |         tmpCol = columnAt( pos.x() );
 | 
|---|
| 3800 |     pos -= QPoint( contentsX(), contentsY() );
 | 
|---|
| 3801 | 
 | 
|---|
| 3802 |     fixRow( tmpRow, pos.y() );
 | 
|---|
| 3803 |     fixCol( tmpCol, pos.x() );
 | 
|---|
| 3804 | 
 | 
|---|
| 3805 |     if ( tmpRow < 0 || tmpRow > numRows() - 1 )
 | 
|---|
| 3806 |         tmpRow = currentRow();
 | 
|---|
| 3807 |     if ( tmpCol < 0 || tmpCol > numCols() - 1 )
 | 
|---|
| 3808 |         tmpCol = currentColumn();
 | 
|---|
| 3809 | 
 | 
|---|
| 3810 |     ensureCellVisible( tmpRow, tmpCol );
 | 
|---|
| 3811 | 
 | 
|---|
| 3812 |     if ( currentSel && selMode != NoSelection ) {
 | 
|---|
| 3813 |         QTableSelection oldSelection = *currentSel;
 | 
|---|
| 3814 |         bool useOld = TRUE;
 | 
|---|
| 3815 |         if ( selMode != SingleRow ) {
 | 
|---|
| 3816 |             if ( !isRowSelection( selectionMode() ) ) {
 | 
|---|
| 3817 |                 currentSel->expandTo( tmpRow, tmpCol );
 | 
|---|
| 3818 |             } else {
 | 
|---|
| 3819 |                 currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 3820 |             }
 | 
|---|
| 3821 |         } else {
 | 
|---|
| 3822 |             bool currentInSelection = tmpRow == curRow && isSelected( tmpRow, tmpCol );
 | 
|---|
| 3823 |             if ( !currentInSelection ) {
 | 
|---|
| 3824 |                 useOld = FALSE;
 | 
|---|
| 3825 |                 clearSelection();
 | 
|---|
| 3826 |                 currentSel = new QTableSelection();
 | 
|---|
| 3827 |                 selections.append( currentSel );
 | 
|---|
| 3828 |                 currentSel->init( tmpRow, 0 );
 | 
|---|
| 3829 |                 currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 3830 |                 repaintSelections( 0, currentSel );
 | 
|---|
| 3831 |             } else {
 | 
|---|
| 3832 |                 currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 3833 |             }
 | 
|---|
| 3834 |         }
 | 
|---|
| 3835 |         setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 3836 |         repaintSelections( useOld ? &oldSelection : 0, currentSel );
 | 
|---|
| 3837 |         if ( currentSel && oldSelection != *currentSel )
 | 
|---|
| 3838 |             emit selectionChanged();
 | 
|---|
| 3839 |     } else {
 | 
|---|
| 3840 |         setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 3841 |     }
 | 
|---|
| 3842 | 
 | 
|---|
| 3843 |     if ( pos.x() < 0 || pos.x() > visibleWidth() || pos.y() < 0 || pos.y() > visibleHeight() )
 | 
|---|
| 3844 |         autoScrollTimer->start( 100, TRUE );
 | 
|---|
| 3845 | }
 | 
|---|
| 3846 | 
 | 
|---|
| 3847 | /*! \reimp
 | 
|---|
| 3848 | */
 | 
|---|
| 3849 | 
 | 
|---|
| 3850 | void QTable::contentsMouseReleaseEvent( QMouseEvent *e )
 | 
|---|
| 3851 | {
 | 
|---|
| 3852 |     if ( pressedRow == curRow && pressedCol == curCol )
 | 
|---|
| 3853 |         emit clicked( curRow, curCol, e->button(), e->pos() );
 | 
|---|
| 3854 | 
 | 
|---|
| 3855 |     if ( e->button() != LeftButton )
 | 
|---|
| 3856 |         return;
 | 
|---|
| 3857 |     if ( shouldClearSelection ) {
 | 
|---|
| 3858 |         int tmpRow = rowAt( e->pos().y() );
 | 
|---|
| 3859 |         int tmpCol = columnAt( e->pos().x() );
 | 
|---|
| 3860 |         fixRow( tmpRow, e->pos().y() );
 | 
|---|
| 3861 |         fixCol( tmpCol, e->pos().x() );
 | 
|---|
| 3862 |         clearSelection();
 | 
|---|
| 3863 |         if ( selMode != NoSelection ) {
 | 
|---|
| 3864 |             currentSel = new QTableSelection();
 | 
|---|
| 3865 |             selections.append( currentSel );
 | 
|---|
| 3866 |             if ( !isRowSelection( selectionMode() ) ) {
 | 
|---|
| 3867 |                 currentSel->init( tmpRow, tmpCol );
 | 
|---|
| 3868 |             } else {
 | 
|---|
| 3869 |                 currentSel->init( tmpRow, 0 );
 | 
|---|
| 3870 |                 currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 3871 |                 repaintSelections( 0, currentSel );
 | 
|---|
| 3872 |             }
 | 
|---|
| 3873 |             emit selectionChanged();
 | 
|---|
| 3874 |         }
 | 
|---|
| 3875 |         shouldClearSelection = FALSE;
 | 
|---|
| 3876 |     }
 | 
|---|
| 3877 |     autoScrollTimer->stop();
 | 
|---|
| 3878 | 
 | 
|---|
| 3879 |     if ( d->redirectMouseEvent && pressedRow == curRow && pressedCol == curCol &&
 | 
|---|
| 3880 |          item( pressedRow, pressedCol ) && item( pressedRow, pressedCol )->editType() ==
 | 
|---|
| 3881 |          QTableItem::WhenCurrent ) {
 | 
|---|
| 3882 |         QWidget *w = cellWidget( pressedRow, pressedCol );
 | 
|---|
| 3883 |         if ( w ) {
 | 
|---|
| 3884 |             QMouseEvent ev( e->type(), w->mapFromGlobal( e->globalPos() ),
 | 
|---|
| 3885 |                             e->globalPos(), e->button(), e->state() );
 | 
|---|
| 3886 |             QApplication::sendPostedEvents( w, 0 );
 | 
|---|
| 3887 |             QApplication::sendEvent( w, &ev );
 | 
|---|
| 3888 |         }
 | 
|---|
| 3889 |     }
 | 
|---|
| 3890 | }
 | 
|---|
| 3891 | 
 | 
|---|
| 3892 | /*!
 | 
|---|
| 3893 |   \reimp
 | 
|---|
| 3894 | */
 | 
|---|
| 3895 | 
 | 
|---|
| 3896 | void QTable::contentsContextMenuEvent( QContextMenuEvent *e )
 | 
|---|
| 3897 | {
 | 
|---|
| 3898 |     if ( !receivers( SIGNAL(contextMenuRequested(int,int,const QPoint&)) ) ) {
 | 
|---|
| 3899 |         e->ignore();
 | 
|---|
| 3900 |         return;
 | 
|---|
| 3901 |     }
 | 
|---|
| 3902 |     if ( e->reason() == QContextMenuEvent::Keyboard ) {
 | 
|---|
| 3903 |         QRect r = cellGeometry( curRow, curCol );
 | 
|---|
| 3904 |         emit contextMenuRequested( curRow, curCol, viewport()->mapToGlobal( contentsToViewport( r.center() ) ) );
 | 
|---|
| 3905 |     } else {
 | 
|---|
| 3906 |         int tmpRow = rowAt( e->pos().y() );
 | 
|---|
| 3907 |         int tmpCol = columnAt( e->pos().x() );
 | 
|---|
| 3908 |         emit contextMenuRequested( tmpRow, tmpCol, e->globalPos() );
 | 
|---|
| 3909 |     }
 | 
|---|
| 3910 | }
 | 
|---|
| 3911 | 
 | 
|---|
| 3912 | 
 | 
|---|
| 3913 | /*! \reimp
 | 
|---|
| 3914 | */
 | 
|---|
| 3915 | 
 | 
|---|
| 3916 | bool QTable::eventFilter( QObject *o, QEvent *e )
 | 
|---|
| 3917 | {
 | 
|---|
| 3918 |     QWidget *editorWidget = cellWidget( editRow, editCol );
 | 
|---|
| 3919 |     switch ( e->type() ) {
 | 
|---|
| 3920 |     case QEvent::KeyPress: {
 | 
|---|
| 3921 |         QTableItem *itm = item( curRow, curCol );
 | 
|---|
| 3922 | 
 | 
|---|
| 3923 |         if ( isEditing() && editorWidget && o == editorWidget ) {
 | 
|---|
| 3924 |             itm = item( editRow, editCol );
 | 
|---|
| 3925 |             QKeyEvent *ke = (QKeyEvent*)e;
 | 
|---|
| 3926 |             if ( ke->key() == Key_Escape ) {
 | 
|---|
| 3927 |                 if ( !itm || itm->editType() == QTableItem::OnTyping )
 | 
|---|
| 3928 |                     endEdit( editRow, editCol, FALSE, edMode != Editing );
 | 
|---|
| 3929 |                 return TRUE;
 | 
|---|
| 3930 |             }
 | 
|---|
| 3931 | 
 | 
|---|
| 3932 |             if ( ( ke->state() == NoButton || ke->state() == Keypad )
 | 
|---|
| 3933 |                 && ( ke->key() == Key_Return || ke->key() == Key_Enter ) ) {
 | 
|---|
| 3934 |                 if ( !itm || itm->editType() == QTableItem::OnTyping )
 | 
|---|
| 3935 |                     endEdit( editRow, editCol, TRUE, edMode != Editing );
 | 
|---|
| 3936 |                 activateNextCell();
 | 
|---|
| 3937 |                 return TRUE;
 | 
|---|
| 3938 |             }
 | 
|---|
| 3939 | 
 | 
|---|
| 3940 |             if ( ke->key() == Key_Tab || ke->key() == Key_BackTab ) {
 | 
|---|
| 3941 |                 if ( ke->state() & Qt::ControlButton )
 | 
|---|
| 3942 |                     return FALSE;
 | 
|---|
| 3943 |                 if ( !itm || itm->editType() == QTableItem::OnTyping )
 | 
|---|
| 3944 |                     endEdit( editRow, editCol, TRUE, edMode != Editing );
 | 
|---|
| 3945 |                 if ( (ke->key() == Key_Tab) && !(ke->state() & ShiftButton) ) {
 | 
|---|
| 3946 |                     if ( currentColumn() >= numCols() - 1 )
 | 
|---|
| 3947 |                         return TRUE;
 | 
|---|
| 3948 |                     int cc  = QMIN( numCols() - 1, currentColumn() + 1 );
 | 
|---|
| 3949 |                     while ( cc < numCols() ) {
 | 
|---|
| 3950 |                         QTableItem *i = item( currentRow(), cc );
 | 
|---|
| 3951 |                         if ( !d->hiddenCols.find( cc ) && !isColumnReadOnly( cc ) && (!i || i->isEnabled()) )
 | 
|---|
| 3952 |                             break;
 | 
|---|
| 3953 |                         ++cc;
 | 
|---|
| 3954 |                     }
 | 
|---|
| 3955 |                     setCurrentCell( currentRow(), cc );
 | 
|---|
| 3956 |                 } else { // Key_BackTab
 | 
|---|
| 3957 |                     if ( currentColumn() == 0 )
 | 
|---|
| 3958 |                         return TRUE;
 | 
|---|
| 3959 |                     int cc  = QMAX( 0, currentColumn() - 1 );
 | 
|---|
| 3960 |                     while ( cc >= 0 ) {
 | 
|---|
| 3961 |                         QTableItem *i = item( currentRow(), cc );
 | 
|---|
| 3962 |                         if ( !d->hiddenCols.find( cc ) && !isColumnReadOnly( cc ) && (!i || i->isEnabled()) )
 | 
|---|
| 3963 |                             break;
 | 
|---|
| 3964 |                         --cc;
 | 
|---|
| 3965 |                     }
 | 
|---|
| 3966 |                     setCurrentCell( currentRow(), cc );
 | 
|---|
| 3967 |                 }
 | 
|---|
| 3968 |                 itm = item( curRow, curCol );
 | 
|---|
| 3969 |                 if ( beginEdit( curRow, curCol, FALSE ) )
 | 
|---|
| 3970 |                     setEditMode( Editing, curRow, curCol );
 | 
|---|
| 3971 |                 return TRUE;
 | 
|---|
| 3972 |             }
 | 
|---|
| 3973 | 
 | 
|---|
| 3974 |             if ( ( edMode == Replacing ||
 | 
|---|
| 3975 |                    itm && itm->editType() == QTableItem::WhenCurrent ) &&
 | 
|---|
| 3976 |                  ( ke->key() == Key_Up || ke->key() == Key_Prior ||
 | 
|---|
| 3977 |                    ke->key() == Key_Home || ke->key() == Key_Down ||
 | 
|---|
| 3978 |                    ke->key() == Key_Next || ke->key() == Key_End ||
 | 
|---|
| 3979 |                    ke->key() == Key_Left || ke->key() == Key_Right ) ) {
 | 
|---|
| 3980 |                 if ( !itm || itm->editType() == QTableItem::OnTyping ) {
 | 
|---|
| 3981 |                     endEdit( editRow, editCol, TRUE, edMode != Editing );
 | 
|---|
| 3982 |                 }
 | 
|---|
| 3983 |                 keyPressEvent( ke );
 | 
|---|
| 3984 |                 return TRUE;
 | 
|---|
| 3985 |             }
 | 
|---|
| 3986 |         } else {
 | 
|---|
| 3987 |             QObjectList *l = viewport()->queryList( "QWidget" );
 | 
|---|
| 3988 |             if ( l && l->find( o ) != -1 ) {
 | 
|---|
| 3989 |                 QKeyEvent *ke = (QKeyEvent*)e;
 | 
|---|
| 3990 |                 if ( ( ke->state() & ControlButton ) == ControlButton ||
 | 
|---|
| 3991 |                      ( ke->key() != Key_Left && ke->key() != Key_Right &&
 | 
|---|
| 3992 |                        ke->key() != Key_Up && ke->key() != Key_Down &&
 | 
|---|
| 3993 |                        ke->key() != Key_Prior && ke->key() != Key_Next &&
 | 
|---|
| 3994 |                        ke->key() != Key_Home && ke->key() != Key_End ) )
 | 
|---|
| 3995 |                     return FALSE;
 | 
|---|
| 3996 |                 keyPressEvent( (QKeyEvent*)e );
 | 
|---|
| 3997 |                 return TRUE;
 | 
|---|
| 3998 |             }
 | 
|---|
| 3999 |             delete l;
 | 
|---|
| 4000 |         }
 | 
|---|
| 4001 | 
 | 
|---|
| 4002 |         } break;
 | 
|---|
| 4003 |     case QEvent::FocusOut:
 | 
|---|
| 4004 |         if ( isEditing() && editorWidget && o == editorWidget && ( (QFocusEvent*)e )->reason() != QFocusEvent::Popup ) {
 | 
|---|
| 4005 |             QTableItem *itm = item( editRow, editCol );
 | 
|---|
| 4006 |             if ( !itm || itm->editType() == QTableItem::OnTyping ) {
 | 
|---|
| 4007 |                 endEdit( editRow, editCol, TRUE, edMode != Editing );
 | 
|---|
| 4008 |                 return TRUE;
 | 
|---|
| 4009 |             }
 | 
|---|
| 4010 |         }
 | 
|---|
| 4011 |         break;
 | 
|---|
| 4012 | #ifndef QT_NO_WHEELEVENT
 | 
|---|
| 4013 |     case QEvent::Wheel:
 | 
|---|
| 4014 |         if ( o == this || o == viewport() ) {
 | 
|---|
| 4015 |             QWheelEvent* we = (QWheelEvent*)e;
 | 
|---|
| 4016 |             scrollBy( 0, -we->delta() );
 | 
|---|
| 4017 |             we->accept();
 | 
|---|
| 4018 |             return TRUE;
 | 
|---|
| 4019 |         }
 | 
|---|
| 4020 | #endif
 | 
|---|
| 4021 |     default:
 | 
|---|
| 4022 |         break;
 | 
|---|
| 4023 |     }
 | 
|---|
| 4024 | 
 | 
|---|
| 4025 |     return QScrollView::eventFilter( o, e );
 | 
|---|
| 4026 | }
 | 
|---|
| 4027 | 
 | 
|---|
| 4028 | void QTable::fixCell( int &row, int &col, int key )
 | 
|---|
| 4029 | {
 | 
|---|
| 4030 |     if ( rowHeight( row ) > 0 && columnWidth( col ) > 0 )
 | 
|---|
| 4031 |         return;
 | 
|---|
| 4032 |     if ( rowHeight( row ) <= 0 ) {
 | 
|---|
| 4033 |         if ( key == Key_Down ||
 | 
|---|
| 4034 |              key == Key_Next ||
 | 
|---|
| 4035 |              key == Key_End ) {
 | 
|---|
| 4036 |             while ( row < numRows() && rowHeight( row ) <= 0 )
 | 
|---|
| 4037 |                 row++;
 | 
|---|
| 4038 |             if ( rowHeight( row ) <= 0 )
 | 
|---|
| 4039 |                 row = curRow;
 | 
|---|
| 4040 |         } else if ( key == Key_Up ||
 | 
|---|
| 4041 |                     key == Key_Prior ||
 | 
|---|
| 4042 |                     key == Key_Home )
 | 
|---|
| 4043 |             while ( row >= 0 && rowHeight( row ) <= 0 )
 | 
|---|
| 4044 |                 row--;
 | 
|---|
| 4045 |             if ( rowHeight( row ) <= 0 )
 | 
|---|
| 4046 |                 row = curRow;
 | 
|---|
| 4047 |     } else if ( columnWidth( col ) <= 0 ) {
 | 
|---|
| 4048 |         if ( key == Key_Left ) {
 | 
|---|
| 4049 |             while ( col >= 0 && columnWidth( col ) <= 0 )
 | 
|---|
| 4050 |                 col--;
 | 
|---|
| 4051 |             if ( columnWidth( col ) <= 0 )
 | 
|---|
| 4052 |                 col = curCol;
 | 
|---|
| 4053 |         } else if ( key == Key_Right ) {
 | 
|---|
| 4054 |             while ( col < numCols() && columnWidth( col ) <= 0 )
 | 
|---|
| 4055 |                 col++;
 | 
|---|
| 4056 |             if ( columnWidth( col ) <= 0 )
 | 
|---|
| 4057 |                 col = curCol;
 | 
|---|
| 4058 |         }
 | 
|---|
| 4059 |     }
 | 
|---|
| 4060 | }
 | 
|---|
| 4061 | 
 | 
|---|
| 4062 | /*! \reimp
 | 
|---|
| 4063 | */
 | 
|---|
| 4064 | 
 | 
|---|
| 4065 | void QTable::keyPressEvent( QKeyEvent* e )
 | 
|---|
| 4066 | {
 | 
|---|
| 4067 |     if ( isEditing() && item( editRow, editCol ) &&
 | 
|---|
| 4068 |          item( editRow, editCol )->editType() == QTableItem::OnTyping )
 | 
|---|
| 4069 |         return;
 | 
|---|
| 4070 | 
 | 
|---|
| 4071 |     int tmpRow = curRow;
 | 
|---|
| 4072 |     int tmpCol = curCol;
 | 
|---|
| 4073 |     int oldRow = tmpRow;
 | 
|---|
| 4074 |     int oldCol = tmpCol;
 | 
|---|
| 4075 | 
 | 
|---|
| 4076 |     bool navigationKey = FALSE;
 | 
|---|
| 4077 |     int r;
 | 
|---|
| 4078 |     switch ( e->key() ) {
 | 
|---|
| 4079 |     case Key_Left:
 | 
|---|
| 4080 |         tmpCol = QMAX( 0, tmpCol - 1 );
 | 
|---|
| 4081 |         navigationKey = TRUE;
 | 
|---|
| 4082 |         break;
 | 
|---|
| 4083 |     case Key_Right:
 | 
|---|
| 4084 |         tmpCol = QMIN( numCols() - 1, tmpCol + 1 );
 | 
|---|
| 4085 |         navigationKey = TRUE;
 | 
|---|
| 4086 |         break;
 | 
|---|
| 4087 |     case Key_Up:
 | 
|---|
| 4088 |         tmpRow = QMAX( 0, tmpRow - 1 );
 | 
|---|
| 4089 |         navigationKey = TRUE;
 | 
|---|
| 4090 |         break;
 | 
|---|
| 4091 |     case Key_Down:
 | 
|---|
| 4092 |         tmpRow = QMIN( numRows() - 1, tmpRow + 1 );
 | 
|---|
| 4093 |         navigationKey = TRUE;
 | 
|---|
| 4094 |         break;
 | 
|---|
| 4095 |     case Key_Prior:
 | 
|---|
| 4096 |         r = QMAX( 0, rowAt( rowPos( tmpRow ) - visibleHeight() ) );
 | 
|---|
| 4097 |         if ( r < tmpRow || tmpRow < 0 )
 | 
|---|
| 4098 |             tmpRow = r;
 | 
|---|
| 4099 |         navigationKey = TRUE;
 | 
|---|
| 4100 |         break;
 | 
|---|
| 4101 |     case Key_Next:
 | 
|---|
| 4102 |         r = QMIN( numRows() - 1, rowAt( rowPos( tmpRow ) + visibleHeight() ) );
 | 
|---|
| 4103 |         if ( r > tmpRow )
 | 
|---|
| 4104 |             tmpRow = r;
 | 
|---|
| 4105 |         else
 | 
|---|
| 4106 |             tmpRow = numRows() - 1;
 | 
|---|
| 4107 |         navigationKey = TRUE;
 | 
|---|
| 4108 |         break;
 | 
|---|
| 4109 |     case Key_Home:
 | 
|---|
| 4110 |         tmpRow = 0;
 | 
|---|
| 4111 |         navigationKey = TRUE;
 | 
|---|
| 4112 |         break;
 | 
|---|
| 4113 |     case Key_End:
 | 
|---|
| 4114 |         tmpRow = numRows() - 1;
 | 
|---|
| 4115 |         navigationKey = TRUE;
 | 
|---|
| 4116 |         break;
 | 
|---|
| 4117 |     case Key_F2:
 | 
|---|
| 4118 |         if ( beginEdit( tmpRow, tmpCol, FALSE ) )
 | 
|---|
| 4119 |             setEditMode( Editing, tmpRow, tmpCol );
 | 
|---|
| 4120 |         break;
 | 
|---|
| 4121 |     case Key_Enter: case Key_Return:
 | 
|---|
| 4122 |         activateNextCell();
 | 
|---|
| 4123 |         return;
 | 
|---|
| 4124 |     case Key_Tab: case Key_BackTab:
 | 
|---|
| 4125 |         if ( (e->key() == Key_Tab) && !(e->state() & ShiftButton) ) {
 | 
|---|
| 4126 |             if ( currentColumn() >= numCols() - 1 )
 | 
|---|
| 4127 |                 return;
 | 
|---|
| 4128 |             int cc  = QMIN( numCols() - 1, currentColumn() + 1 );
 | 
|---|
| 4129 |             while ( cc < numCols() ) {
 | 
|---|
| 4130 |                 QTableItem *i = item( currentRow(), cc );
 | 
|---|
| 4131 |                 if ( !d->hiddenCols.find( cc ) && !isColumnReadOnly( cc ) && (!i || i->isEnabled()) )
 | 
|---|
| 4132 |                     break;
 | 
|---|
| 4133 |                 ++cc;
 | 
|---|
| 4134 |             }
 | 
|---|
| 4135 |             setCurrentCell( currentRow(), cc );
 | 
|---|
| 4136 |         } else { // Key_BackTab
 | 
|---|
| 4137 |             if ( currentColumn() == 0 )
 | 
|---|
| 4138 |                 return;
 | 
|---|
| 4139 |             int cc  = QMAX( 0, currentColumn() - 1 );
 | 
|---|
| 4140 |             while ( cc >= 0 ) {
 | 
|---|
| 4141 |                 QTableItem *i = item( currentRow(), cc );
 | 
|---|
| 4142 |                 if ( !d->hiddenCols.find( cc ) && !isColumnReadOnly( cc ) && (!i || i->isEnabled()) )
 | 
|---|
| 4143 |                     break;
 | 
|---|
| 4144 |                 --cc;
 | 
|---|
| 4145 |             }
 | 
|---|
| 4146 |             setCurrentCell( currentRow(), cc );
 | 
|---|
| 4147 |         }
 | 
|---|
| 4148 |         return;
 | 
|---|
| 4149 |     case Key_Escape:
 | 
|---|
| 4150 |         e->ignore();
 | 
|---|
| 4151 |         return;
 | 
|---|
| 4152 |     default: // ... or start in-place editing
 | 
|---|
| 4153 |         if ( e->text()[ 0 ].isPrint() ) {
 | 
|---|
| 4154 |             QTableItem *itm = item( tmpRow, tmpCol );
 | 
|---|
| 4155 |             if ( !itm || itm->editType() == QTableItem::OnTyping ) {
 | 
|---|
| 4156 |                 QWidget *w = beginEdit( tmpRow, tmpCol,
 | 
|---|
| 4157 |                                         itm ? itm->isReplaceable() : TRUE );
 | 
|---|
| 4158 |                 if ( w ) {
 | 
|---|
| 4159 |                     setEditMode( ( !itm || itm && itm->isReplaceable()
 | 
|---|
| 4160 |                                    ? Replacing : Editing ), tmpRow, tmpCol );
 | 
|---|
| 4161 |                     QApplication::sendEvent( w, e );
 | 
|---|
| 4162 |                     return;
 | 
|---|
| 4163 |                 }
 | 
|---|
| 4164 |             }
 | 
|---|
| 4165 |         }
 | 
|---|
| 4166 |         e->ignore();
 | 
|---|
| 4167 |         return;
 | 
|---|
| 4168 |     }
 | 
|---|
| 4169 | 
 | 
|---|
| 4170 |     if ( navigationKey ) {
 | 
|---|
| 4171 |         fixCell( tmpRow, tmpCol, e->key() );
 | 
|---|
| 4172 |         if ( ( e->state() & ShiftButton ) == ShiftButton &&
 | 
|---|
| 4173 |              selMode != NoSelection && selMode != SingleRow ) {
 | 
|---|
| 4174 |             bool justCreated = FALSE;
 | 
|---|
| 4175 |             setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 4176 |             if ( !currentSel ) {
 | 
|---|
| 4177 |                 justCreated = TRUE;
 | 
|---|
| 4178 |                 currentSel = new QTableSelection();
 | 
|---|
| 4179 |                 selections.append( currentSel );
 | 
|---|
| 4180 |                 if ( !isRowSelection( selectionMode() ) )
 | 
|---|
| 4181 |                     currentSel->init( oldRow, oldCol );
 | 
|---|
| 4182 |                 else
 | 
|---|
| 4183 |                     currentSel->init( oldRow < 0 ? 0 : oldRow, 0 );
 | 
|---|
| 4184 |             }
 | 
|---|
| 4185 |             QTableSelection oldSelection = *currentSel;
 | 
|---|
| 4186 |             if ( !isRowSelection( selectionMode() ) )
 | 
|---|
| 4187 |                 currentSel->expandTo( tmpRow, tmpCol );
 | 
|---|
| 4188 |             else
 | 
|---|
| 4189 |                 currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 4190 |             repaintSelections( justCreated ? 0 : &oldSelection, currentSel );
 | 
|---|
| 4191 |             emit selectionChanged();
 | 
|---|
| 4192 |         } else {
 | 
|---|
| 4193 |             setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 4194 |             if ( !isRowSelection( selectionMode() ) ) {
 | 
|---|
| 4195 |                 clearSelection();
 | 
|---|
| 4196 |             } else {
 | 
|---|
| 4197 |                 bool currentInSelection = tmpRow == oldRow && isSelected( tmpRow, tmpCol, FALSE );
 | 
|---|
| 4198 |                 if ( !currentInSelection ) {
 | 
|---|
| 4199 |                     bool hasOldSel = FALSE;
 | 
|---|
| 4200 |                     QTableSelection oldSelection;
 | 
|---|
| 4201 |                     if ( selectionMode() == MultiRow ) {
 | 
|---|
| 4202 |                         bool b = signalsBlocked();
 | 
|---|
| 4203 |                         blockSignals( TRUE );
 | 
|---|
| 4204 |                         clearSelection();
 | 
|---|
| 4205 |                         blockSignals( b );
 | 
|---|
| 4206 |                     } else {
 | 
|---|
| 4207 |                         if ( currentSel ) {
 | 
|---|
| 4208 |                             oldSelection = *currentSel;
 | 
|---|
| 4209 |                             hasOldSel = TRUE;
 | 
|---|
| 4210 |                             selections.removeRef( currentSel );
 | 
|---|
| 4211 |                             leftHeader->setSectionState( oldSelection.topRow(), QTableHeader::Normal );
 | 
|---|
| 4212 |                         }
 | 
|---|
| 4213 |                     }
 | 
|---|
| 4214 |                     currentSel = new QTableSelection();
 | 
|---|
| 4215 |                     selections.append( currentSel );
 | 
|---|
| 4216 |                     currentSel->init( tmpRow, 0 );
 | 
|---|
| 4217 |                     currentSel->expandTo( tmpRow, numCols() - 1 );
 | 
|---|
| 4218 |                     repaintSelections( hasOldSel ? &oldSelection : 0, currentSel, !hasOldSel );
 | 
|---|
| 4219 |                     emit selectionChanged();
 | 
|---|
| 4220 |                 }
 | 
|---|
| 4221 |             }
 | 
|---|
| 4222 |         }
 | 
|---|
| 4223 |     } else {
 | 
|---|
| 4224 |         setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 4225 |     }
 | 
|---|
| 4226 | }
 | 
|---|
| 4227 | 
 | 
|---|
| 4228 | /*! \reimp
 | 
|---|
| 4229 | */
 | 
|---|
| 4230 | 
 | 
|---|
| 4231 | void QTable::focusInEvent( QFocusEvent* )
 | 
|---|
| 4232 | {
 | 
|---|
| 4233 |     d->inMenuMode = FALSE;
 | 
|---|
| 4234 |     QWidget *editorWidget = cellWidget( editRow, editCol );
 | 
|---|
| 4235 |     updateCell( curRow, curCol );
 | 
|---|
| 4236 |     if ( style().styleHint( QStyle::SH_ItemView_ChangeHighlightOnFocus, this ) )
 | 
|---|
| 4237 |         repaintSelections();
 | 
|---|
| 4238 |     if ( isEditing() && editorWidget )
 | 
|---|
| 4239 |         editorWidget->setFocus();
 | 
|---|
| 4240 | 
 | 
|---|
| 4241 |     QPoint cellPos( columnPos( curCol ) + leftMargin() - contentsX(), rowPos( curRow ) + topMargin() - contentsY() );
 | 
|---|
| 4242 |     QTableItem *itm = item( curRow, curCol );
 | 
|---|
| 4243 |     setMicroFocusHint( cellPos.x(), cellPos.y(), columnWidth( curCol ), rowHeight( curRow ), ( itm && itm->editType() != QTableItem::Never ) );
 | 
|---|
| 4244 | }
 | 
|---|
| 4245 | 
 | 
|---|
| 4246 | 
 | 
|---|
| 4247 | /*! \reimp
 | 
|---|
| 4248 | */
 | 
|---|
| 4249 | 
 | 
|---|
| 4250 | void QTable::focusOutEvent( QFocusEvent* )
 | 
|---|
| 4251 | {
 | 
|---|
| 4252 |     updateCell( curRow, curCol );
 | 
|---|
| 4253 |     if (style().styleHint( QStyle::SH_ItemView_ChangeHighlightOnFocus, this )) {
 | 
|---|
| 4254 |         d->inMenuMode =
 | 
|---|
| 4255 |             QFocusEvent::reason() == QFocusEvent::Popup ||
 | 
|---|
| 4256 |             (qApp->focusWidget() && qApp->focusWidget()->inherits("QMenuBar"));
 | 
|---|
| 4257 |         if ( !d->inMenuMode )
 | 
|---|
| 4258 |             repaintSelections();
 | 
|---|
| 4259 |     }
 | 
|---|
| 4260 | }
 | 
|---|
| 4261 | 
 | 
|---|
| 4262 | /*! \reimp
 | 
|---|
| 4263 | */
 | 
|---|
| 4264 | 
 | 
|---|
| 4265 | QSize QTable::sizeHint() const
 | 
|---|
| 4266 | {
 | 
|---|
| 4267 |     if ( cachedSizeHint().isValid() )
 | 
|---|
| 4268 |         return cachedSizeHint();
 | 
|---|
| 4269 | 
 | 
|---|
| 4270 |     constPolish();
 | 
|---|
| 4271 | 
 | 
|---|
| 4272 |     QSize s = tableSize();
 | 
|---|
| 4273 |     QSize sh;
 | 
|---|
| 4274 |     if ( s.width() < 500 && s.height() < 500 ) {
 | 
|---|
| 4275 |         sh = QSize( tableSize().width() + VERTICALMARGIN + 5,
 | 
|---|
| 4276 |                     tableSize().height() + topMargin() + 5 );
 | 
|---|
| 4277 |     } else {
 | 
|---|
| 4278 |         sh = QScrollView::sizeHint();
 | 
|---|
| 4279 |         if ( !topHeader->isHidden() )
 | 
|---|
| 4280 |                 sh.setHeight( sh.height() + topHeader->height() );
 | 
|---|
| 4281 |         if ( !leftHeader->isHidden() )
 | 
|---|
| 4282 |                 sh.setWidth( sh.width() + leftHeader->width() );
 | 
|---|
| 4283 |     }
 | 
|---|
| 4284 |     setCachedSizeHint( sh );
 | 
|---|
| 4285 |     return sh;
 | 
|---|
| 4286 | }
 | 
|---|
| 4287 | 
 | 
|---|
| 4288 | /*! \reimp
 | 
|---|
| 4289 | */
 | 
|---|
| 4290 | 
 | 
|---|
| 4291 | void QTable::viewportResizeEvent( QResizeEvent *e )
 | 
|---|
| 4292 | {
 | 
|---|
| 4293 |     QScrollView::viewportResizeEvent( e );
 | 
|---|
| 4294 |     updateGeometries();
 | 
|---|
| 4295 | }
 | 
|---|
| 4296 | 
 | 
|---|
| 4297 | /*! \reimp
 | 
|---|
| 4298 | */
 | 
|---|
| 4299 | 
 | 
|---|
| 4300 | void QTable::showEvent( QShowEvent *e )
 | 
|---|
| 4301 | {
 | 
|---|
| 4302 |     QScrollView::showEvent( e );
 | 
|---|
| 4303 |     QRect r( cellGeometry( numRows() - 1, numCols() - 1 ) );
 | 
|---|
| 4304 |     resizeContents( r.right() + 1, r.bottom() + 1 );
 | 
|---|
| 4305 |     updateGeometries();
 | 
|---|
| 4306 | }
 | 
|---|
| 4307 | 
 | 
|---|
| 4308 | /*! \reimp
 | 
|---|
| 4309 | */
 | 
|---|
| 4310 | 
 | 
|---|
| 4311 | void QTable::paintEvent( QPaintEvent *e )
 | 
|---|
| 4312 | {
 | 
|---|
| 4313 |     QRect topLeftCorner = QStyle::visualRect( QRect(frameWidth(), frameWidth(), VERTICALMARGIN, topMargin() ), rect() );
 | 
|---|
| 4314 |     erase( topLeftCorner ); // erase instead of widget on top
 | 
|---|
| 4315 |     QScrollView::paintEvent( e );
 | 
|---|
| 4316 | 
 | 
|---|
| 4317 | #ifdef Q_OS_TEMP
 | 
|---|
| 4318 |     QPainter p( this );
 | 
|---|
| 4319 |     p.drawLine( topLeftCorner.bottomLeft(), topLeftCorner.bottomRight() );
 | 
|---|
| 4320 |     p.drawLine( topLeftCorner.bottomRight(), topLeftCorner.topRight() );
 | 
|---|
| 4321 | #endif
 | 
|---|
| 4322 | }
 | 
|---|
| 4323 | 
 | 
|---|
| 4324 | static bool inUpdateCell = FALSE;
 | 
|---|
| 4325 | 
 | 
|---|
| 4326 | /*!
 | 
|---|
| 4327 |     Repaints the cell at \a row, \a col.
 | 
|---|
| 4328 | */
 | 
|---|
| 4329 | 
 | 
|---|
| 4330 | void QTable::updateCell( int row, int col )
 | 
|---|
| 4331 | {
 | 
|---|
| 4332 |     if ( inUpdateCell || row < 0 || col < 0 )
 | 
|---|
| 4333 |         return;
 | 
|---|
| 4334 |     inUpdateCell = TRUE;
 | 
|---|
| 4335 |     QRect cg = cellGeometry( row, col );
 | 
|---|
| 4336 |     QRect r( contentsToViewport( QPoint( cg.x() - 2, cg.y() - 2 ) ),
 | 
|---|
| 4337 |              QSize( cg.width() + 4, cg.height() + 4 ) );
 | 
|---|
| 4338 |     QApplication::postEvent( viewport(), new QPaintEvent( r, FALSE ) );
 | 
|---|
| 4339 |     inUpdateCell = FALSE;
 | 
|---|
| 4340 | }
 | 
|---|
| 4341 | 
 | 
|---|
| 4342 | void QTable::repaintCell( int row, int col )
 | 
|---|
| 4343 | {
 | 
|---|
| 4344 |     if ( row == -1 || col == -1 )
 | 
|---|
| 4345 |         return;
 | 
|---|
| 4346 |     QRect cg = cellGeometry( row, col );
 | 
|---|
| 4347 |     QRect r( QPoint( cg.x() - 2, cg.y() - 2 ),
 | 
|---|
| 4348 |              QSize( cg.width() + 4, cg.height() + 4 ) );
 | 
|---|
| 4349 |     repaintContents( r, FALSE );
 | 
|---|
| 4350 | }
 | 
|---|
| 4351 | 
 | 
|---|
| 4352 | void QTable::contentsToViewport2( int x, int y, int& vx, int& vy )
 | 
|---|
| 4353 | {
 | 
|---|
| 4354 |     const QPoint v = contentsToViewport2( QPoint( x, y ) );
 | 
|---|
| 4355 |     vx = v.x();
 | 
|---|
| 4356 |     vy = v.y();
 | 
|---|
| 4357 | }
 | 
|---|
| 4358 | 
 | 
|---|
| 4359 | QPoint QTable::contentsToViewport2( const QPoint &p )
 | 
|---|
| 4360 | {
 | 
|---|
| 4361 |     return QPoint( p.x() - contentsX(),
 | 
|---|
| 4362 |                    p.y() - contentsY() );
 | 
|---|
| 4363 | }
 | 
|---|
| 4364 | 
 | 
|---|
| 4365 | QPoint QTable::viewportToContents2( const QPoint& vp )
 | 
|---|
| 4366 | {
 | 
|---|
| 4367 |     return QPoint( vp.x() + contentsX(),
 | 
|---|
| 4368 |                    vp.y() + contentsY() );
 | 
|---|
| 4369 | }
 | 
|---|
| 4370 | 
 | 
|---|
| 4371 | void QTable::viewportToContents2( int vx, int vy, int& x, int& y )
 | 
|---|
| 4372 | {
 | 
|---|
| 4373 |     const QPoint c = viewportToContents2( QPoint( vx, vy ) );
 | 
|---|
| 4374 |     x = c.x();
 | 
|---|
| 4375 |     y = c.y();
 | 
|---|
| 4376 | }
 | 
|---|
| 4377 | 
 | 
|---|
| 4378 | /*!
 | 
|---|
| 4379 |     This function should be called whenever the column width of \a col
 | 
|---|
| 4380 |     has been changed. It updates the geometry of any affected columns
 | 
|---|
| 4381 |     and repaints the table to reflect the changes it has made.
 | 
|---|
| 4382 | */
 | 
|---|
| 4383 | 
 | 
|---|
| 4384 | void QTable::columnWidthChanged( int col )
 | 
|---|
| 4385 | {
 | 
|---|
| 4386 |     int p = columnPos( col );
 | 
|---|
| 4387 |     if ( d->hasColSpan )
 | 
|---|
| 4388 |         p = contentsX();
 | 
|---|
| 4389 |     updateContents( p, contentsY(), contentsWidth(), visibleHeight() );
 | 
|---|
| 4390 |     QSize s( tableSize() );
 | 
|---|
| 4391 |     int w = contentsWidth();
 | 
|---|
| 4392 |     resizeContents( s.width(), s.height() );
 | 
|---|
| 4393 |     if ( contentsWidth() < w )
 | 
|---|
| 4394 |         repaintContents( s.width(), contentsY(),
 | 
|---|
| 4395 |                          w - s.width() + 1, visibleHeight(), TRUE );
 | 
|---|
| 4396 |     else
 | 
|---|
| 4397 |         repaintContents( w, contentsY(),
 | 
|---|
| 4398 |                          s.width() - w + 1, visibleHeight(), FALSE );
 | 
|---|
| 4399 | 
 | 
|---|
| 4400 |     // update widgets that are affected by this change
 | 
|---|
| 4401 |     if ( widgets.size() )
 | 
|---|
| 4402 |         for ( int c = col; c <= d->lastVisCol; ++c )
 | 
|---|
| 4403 |             updateColWidgets( c );
 | 
|---|
| 4404 |     delayedUpdateGeometries();
 | 
|---|
| 4405 | }
 | 
|---|
| 4406 | 
 | 
|---|
| 4407 | /*!
 | 
|---|
| 4408 |     This function should be called whenever the row height of \a row
 | 
|---|
| 4409 |     has been changed. It updates the geometry of any affected rows and
 | 
|---|
| 4410 |     repaints the table to reflect the changes it has made.
 | 
|---|
| 4411 | */
 | 
|---|
| 4412 | 
 | 
|---|
| 4413 | void QTable::rowHeightChanged( int row )
 | 
|---|
| 4414 | {
 | 
|---|
| 4415 |     int p = rowPos( row );
 | 
|---|
| 4416 |     if ( d->hasRowSpan )
 | 
|---|
| 4417 |         p = contentsY();
 | 
|---|
| 4418 |     updateContents( contentsX(), p, visibleWidth(), contentsHeight() );
 | 
|---|
| 4419 |     QSize s( tableSize() );
 | 
|---|
| 4420 |     int h = contentsHeight();
 | 
|---|
| 4421 |     resizeContents( s.width(), s.height() );
 | 
|---|
| 4422 |     if ( contentsHeight() < h ) {
 | 
|---|
| 4423 |         repaintContents( contentsX(), contentsHeight(),
 | 
|---|
| 4424 |                          visibleWidth(), h - s.height() + 1, TRUE );
 | 
|---|
| 4425 |     } else {
 | 
|---|
| 4426 |         repaintContents( contentsX(), h,
 | 
|---|
| 4427 |                          visibleWidth(), s.height() - h + 1, FALSE );
 | 
|---|
| 4428 |     }
 | 
|---|
| 4429 | 
 | 
|---|
| 4430 |     // update widgets that are affected by this change
 | 
|---|
| 4431 |     if ( widgets.size() ) {
 | 
|---|
| 4432 |         d->lastVisRow = rowAt( contentsY() + visibleHeight() + ( s.height() - h + 1 ) );
 | 
|---|
| 4433 |         for ( int r = row; r <= d->lastVisRow; ++r )
 | 
|---|
| 4434 |             updateRowWidgets( r );
 | 
|---|
| 4435 |     }
 | 
|---|
| 4436 |     delayedUpdateGeometries();
 | 
|---|
| 4437 | }
 | 
|---|
| 4438 | 
 | 
|---|
| 4439 | /*! \internal */
 | 
|---|
| 4440 | 
 | 
|---|
| 4441 | void QTable::updateRowWidgets( int row )
 | 
|---|
| 4442 | {
 | 
|---|
| 4443 |     for ( int i = 0; i < numCols(); ++i ) {
 | 
|---|
| 4444 |         QWidget *w = cellWidget( row, i );
 | 
|---|
| 4445 |         if ( !w )
 | 
|---|
| 4446 |             continue;
 | 
|---|
| 4447 |         moveChild( w, columnPos( i ), rowPos( row ) );
 | 
|---|
| 4448 |         w->resize( columnWidth( i ) - 1, rowHeight( row ) - 1 );
 | 
|---|
| 4449 |     }
 | 
|---|
| 4450 | }
 | 
|---|
| 4451 | 
 | 
|---|
| 4452 | /*! \internal */
 | 
|---|
| 4453 | 
 | 
|---|
| 4454 | void QTable::updateColWidgets( int col )
 | 
|---|
| 4455 | {
 | 
|---|
| 4456 |     for ( int i = 0; i < numRows(); ++i ) {
 | 
|---|
| 4457 |         QWidget *w = cellWidget( i, col );
 | 
|---|
| 4458 |         if ( !w )
 | 
|---|
| 4459 |             continue;
 | 
|---|
| 4460 |         moveChild( w, columnPos( col ), rowPos( i ) );
 | 
|---|
| 4461 |         w->resize( columnWidth( col ) - 1, rowHeight( i ) - 1 );
 | 
|---|
| 4462 |     }
 | 
|---|
| 4463 | }
 | 
|---|
| 4464 | 
 | 
|---|
| 4465 | /*!
 | 
|---|
| 4466 |     This function is called when column order is to be changed, i.e.
 | 
|---|
| 4467 |     when the user moved the column header \a section from \a fromIndex
 | 
|---|
| 4468 |     to \a toIndex.
 | 
|---|
| 4469 | 
 | 
|---|
| 4470 |     If you want to change the column order programmatically, call
 | 
|---|
| 4471 |     swapRows() or swapColumns();
 | 
|---|
| 4472 | 
 | 
|---|
| 4473 |     \sa QHeader::indexChange() rowIndexChanged()
 | 
|---|
| 4474 | */
 | 
|---|
| 4475 | 
 | 
|---|
| 4476 | void QTable::columnIndexChanged( int, int fromIndex, int toIndex )
 | 
|---|
| 4477 | {
 | 
|---|
| 4478 |     if ( doSort && lastSortCol == fromIndex && topHeader )
 | 
|---|
| 4479 |         topHeader->setSortIndicator( toIndex, topHeader->sortIndicatorOrder() );
 | 
|---|
| 4480 |     repaintContents( contentsX(), contentsY(),
 | 
|---|
| 4481 |                      visibleWidth(), visibleHeight(), FALSE );
 | 
|---|
| 4482 | }
 | 
|---|
| 4483 | 
 | 
|---|
| 4484 | /*!
 | 
|---|
| 4485 |     This function is called when the order of the rows is to be
 | 
|---|
| 4486 |     changed, i.e. the user moved the row header section \a section
 | 
|---|
| 4487 |     from \a fromIndex to \a toIndex.
 | 
|---|
| 4488 | 
 | 
|---|
| 4489 |     If you want to change the order programmatically, call swapRows()
 | 
|---|
| 4490 |     or swapColumns();
 | 
|---|
| 4491 | 
 | 
|---|
| 4492 |     \sa QHeader::indexChange() columnIndexChanged()
 | 
|---|
| 4493 | */
 | 
|---|
| 4494 | 
 | 
|---|
| 4495 | void QTable::rowIndexChanged( int, int, int )
 | 
|---|
| 4496 | {
 | 
|---|
| 4497 |     repaintContents( contentsX(), contentsY(),
 | 
|---|
| 4498 |                      visibleWidth(), visibleHeight(), FALSE );
 | 
|---|
| 4499 | }
 | 
|---|
| 4500 | 
 | 
|---|
| 4501 | /*!
 | 
|---|
| 4502 |     This function is called when the column \a col has been clicked.
 | 
|---|
| 4503 |     The default implementation sorts this column if sorting() is TRUE.
 | 
|---|
| 4504 | */
 | 
|---|
| 4505 | 
 | 
|---|
| 4506 | void QTable::columnClicked( int col )
 | 
|---|
| 4507 | {
 | 
|---|
| 4508 |     if ( !sorting() )
 | 
|---|
| 4509 |         return;
 | 
|---|
| 4510 | 
 | 
|---|
| 4511 |     if ( col == lastSortCol ) {
 | 
|---|
| 4512 |         asc = !asc;
 | 
|---|
| 4513 |     } else {
 | 
|---|
| 4514 |         lastSortCol = col;
 | 
|---|
| 4515 |         asc = TRUE;
 | 
|---|
| 4516 |     }
 | 
|---|
| 4517 |     sortColumn( lastSortCol, asc );
 | 
|---|
| 4518 | }
 | 
|---|
| 4519 | 
 | 
|---|
| 4520 | /*!
 | 
|---|
| 4521 |     \property QTable::sorting
 | 
|---|
| 4522 |     \brief whether a click on the header of a column sorts that column
 | 
|---|
| 4523 | 
 | 
|---|
| 4524 |     \sa sortColumn()
 | 
|---|
| 4525 | */
 | 
|---|
| 4526 | 
 | 
|---|
| 4527 | void QTable::setSorting( bool b )
 | 
|---|
| 4528 | {
 | 
|---|
| 4529 |     doSort = b;
 | 
|---|
| 4530 |     if ( topHeader )
 | 
|---|
| 4531 |         topHeader->setSortIndicator( b ? lastSortCol : -1 );
 | 
|---|
| 4532 | }
 | 
|---|
| 4533 | 
 | 
|---|
| 4534 | bool QTable::sorting() const
 | 
|---|
| 4535 | {
 | 
|---|
| 4536 |     return doSort;
 | 
|---|
| 4537 | }
 | 
|---|
| 4538 | 
 | 
|---|
| 4539 | static bool inUpdateGeometries = FALSE;
 | 
|---|
| 4540 | 
 | 
|---|
| 4541 | void QTable::delayedUpdateGeometries()
 | 
|---|
| 4542 | {
 | 
|---|
| 4543 |     d->geomTimer->start( 0, TRUE );
 | 
|---|
| 4544 | }
 | 
|---|
| 4545 | 
 | 
|---|
| 4546 | void QTable::updateGeometriesSlot()
 | 
|---|
| 4547 | {
 | 
|---|
| 4548 |     updateGeometries();
 | 
|---|
| 4549 | }
 | 
|---|
| 4550 | 
 | 
|---|
| 4551 | /*!
 | 
|---|
| 4552 |     This function updates the geometries of the left and top header.
 | 
|---|
| 4553 |     You do not normally need to call this function.
 | 
|---|
| 4554 | */
 | 
|---|
| 4555 | 
 | 
|---|
| 4556 | void QTable::updateGeometries()
 | 
|---|
| 4557 | {
 | 
|---|
| 4558 |     if ( inUpdateGeometries )
 | 
|---|
| 4559 |         return;
 | 
|---|
| 4560 |     inUpdateGeometries = TRUE;
 | 
|---|
| 4561 |     QSize ts = tableSize();
 | 
|---|
| 4562 |     if ( topHeader->offset() &&
 | 
|---|
| 4563 |          ts.width() < topHeader->offset() + topHeader->width() )
 | 
|---|
| 4564 |         horizontalScrollBar()->setValue( ts.width() - topHeader->width() );
 | 
|---|
| 4565 |     if ( leftHeader->offset() &&
 | 
|---|
| 4566 |          ts.height() < leftHeader->offset() + leftHeader->height() )
 | 
|---|
| 4567 |         verticalScrollBar()->setValue( ts.height() - leftHeader->height() );
 | 
|---|
| 4568 | 
 | 
|---|
| 4569 |     leftHeader->setGeometry( QStyle::visualRect( QRect( frameWidth(), topMargin() + frameWidth(),
 | 
|---|
| 4570 |                              VERTICALMARGIN, visibleHeight() ), rect() ) );
 | 
|---|
| 4571 |     topHeader->setGeometry( QStyle::visualRect( QRect(VERTICALMARGIN + frameWidth(), frameWidth(),
 | 
|---|
| 4572 |                                                       visibleWidth(), topMargin() ), rect() ) );
 | 
|---|
| 4573 |     horizontalScrollBar()->raise();
 | 
|---|
| 4574 |     verticalScrollBar()->raise();
 | 
|---|
| 4575 |     topHeader->updateStretches();
 | 
|---|
| 4576 |     leftHeader->updateStretches();
 | 
|---|
| 4577 |     inUpdateGeometries = FALSE;
 | 
|---|
| 4578 | }
 | 
|---|
| 4579 | 
 | 
|---|
| 4580 | /*!
 | 
|---|
| 4581 |     Returns the width of column \a col.
 | 
|---|
| 4582 | 
 | 
|---|
| 4583 |     \sa setColumnWidth() rowHeight()
 | 
|---|
| 4584 | */
 | 
|---|
| 4585 | 
 | 
|---|
| 4586 | int QTable::columnWidth( int col ) const
 | 
|---|
| 4587 | {
 | 
|---|
| 4588 |     return topHeader->sectionSize( col );
 | 
|---|
| 4589 | }
 | 
|---|
| 4590 | 
 | 
|---|
| 4591 | /*!
 | 
|---|
| 4592 |     Returns the height of row \a row.
 | 
|---|
| 4593 | 
 | 
|---|
| 4594 |     \sa setRowHeight() columnWidth()
 | 
|---|
| 4595 | */
 | 
|---|
| 4596 | 
 | 
|---|
| 4597 | int QTable::rowHeight( int row ) const
 | 
|---|
| 4598 | {
 | 
|---|
| 4599 |     return leftHeader->sectionSize( row );
 | 
|---|
| 4600 | }
 | 
|---|
| 4601 | 
 | 
|---|
| 4602 | /*!
 | 
|---|
| 4603 |     Returns the x-coordinate of the column \a col in content
 | 
|---|
| 4604 |     coordinates.
 | 
|---|
| 4605 | 
 | 
|---|
| 4606 |     \sa columnAt() rowPos()
 | 
|---|
| 4607 | */
 | 
|---|
| 4608 | 
 | 
|---|
| 4609 | int QTable::columnPos( int col ) const
 | 
|---|
| 4610 | {
 | 
|---|
| 4611 |     return topHeader->sectionPos( col );
 | 
|---|
| 4612 | }
 | 
|---|
| 4613 | 
 | 
|---|
| 4614 | /*!
 | 
|---|
| 4615 |     Returns the y-coordinate of the row \a row in content coordinates.
 | 
|---|
| 4616 | 
 | 
|---|
| 4617 |     \sa rowAt() columnPos()
 | 
|---|
| 4618 | */
 | 
|---|
| 4619 | 
 | 
|---|
| 4620 | int QTable::rowPos( int row ) const
 | 
|---|
| 4621 | {
 | 
|---|
| 4622 |     return leftHeader->sectionPos( row );
 | 
|---|
| 4623 | }
 | 
|---|
| 4624 | 
 | 
|---|
| 4625 | /*!
 | 
|---|
| 4626 |     Returns the number of the column at position \a x. \a x must be
 | 
|---|
| 4627 |     given in content coordinates.
 | 
|---|
| 4628 | 
 | 
|---|
| 4629 |     \sa columnPos() rowAt()
 | 
|---|
| 4630 | */
 | 
|---|
| 4631 | 
 | 
|---|
| 4632 | int QTable::columnAt( int x ) const
 | 
|---|
| 4633 | {
 | 
|---|
| 4634 |     return topHeader->sectionAt( x );
 | 
|---|
| 4635 | }
 | 
|---|
| 4636 | 
 | 
|---|
| 4637 | /*!
 | 
|---|
| 4638 |     Returns the number of the row at position \a y. \a y must be given
 | 
|---|
| 4639 |     in content coordinates.
 | 
|---|
| 4640 | 
 | 
|---|
| 4641 |     \sa rowPos() columnAt()
 | 
|---|
| 4642 | */
 | 
|---|
| 4643 | 
 | 
|---|
| 4644 | int QTable::rowAt( int y ) const
 | 
|---|
| 4645 | {
 | 
|---|
| 4646 |     return leftHeader->sectionAt( y );
 | 
|---|
| 4647 | }
 | 
|---|
| 4648 | 
 | 
|---|
| 4649 | /*!
 | 
|---|
| 4650 |     Returns the bounding rectangle of the cell at \a row, \a col in
 | 
|---|
| 4651 |     content coordinates.
 | 
|---|
| 4652 | */
 | 
|---|
| 4653 | 
 | 
|---|
| 4654 | QRect QTable::cellGeometry( int row, int col ) const
 | 
|---|
| 4655 | {
 | 
|---|
| 4656 |     QTableItem *itm = item( row, col );
 | 
|---|
| 4657 | 
 | 
|---|
| 4658 |     if ( !itm || itm->rowSpan() == 1 && itm->colSpan() == 1 )
 | 
|---|
| 4659 |         return QRect( columnPos( col ), rowPos( row ),
 | 
|---|
| 4660 |                       columnWidth( col ), rowHeight( row ) );
 | 
|---|
| 4661 | 
 | 
|---|
| 4662 |     while ( row != itm->row() )
 | 
|---|
| 4663 |         row--;
 | 
|---|
| 4664 |     while ( col != itm->col() )
 | 
|---|
| 4665 |         col--;
 | 
|---|
| 4666 | 
 | 
|---|
| 4667 |     QRect rect( columnPos( col ), rowPos( row ),
 | 
|---|
| 4668 |                 columnWidth( col ), rowHeight( row ) );
 | 
|---|
| 4669 | 
 | 
|---|
| 4670 |     for ( int r = 1; r < itm->rowSpan(); ++r )
 | 
|---|
| 4671 |         rect.setHeight( rect.height() + rowHeight( r + row ) );
 | 
|---|
| 4672 | 
 | 
|---|
| 4673 |     for ( int c = 1; c < itm->colSpan(); ++c )
 | 
|---|
| 4674 |         rect.setWidth( rect.width() + columnWidth( c + col ) );
 | 
|---|
| 4675 | 
 | 
|---|
| 4676 |     return rect;
 | 
|---|
| 4677 | }
 | 
|---|
| 4678 | 
 | 
|---|
| 4679 | /*!
 | 
|---|
| 4680 |     Returns the size of the table.
 | 
|---|
| 4681 | 
 | 
|---|
| 4682 |     This is the same as the coordinates of the bottom-right edge of
 | 
|---|
| 4683 |     the last table cell.
 | 
|---|
| 4684 | */
 | 
|---|
| 4685 | 
 | 
|---|
| 4686 | QSize QTable::tableSize() const
 | 
|---|
| 4687 | {
 | 
|---|
| 4688 |     return QSize( columnPos( numCols() - 1 ) + columnWidth( numCols() - 1 ),
 | 
|---|
| 4689 |                   rowPos( numRows() - 1 ) + rowHeight( numRows() - 1 ) );
 | 
|---|
| 4690 | }
 | 
|---|
| 4691 | 
 | 
|---|
| 4692 | /*!
 | 
|---|
| 4693 |     \property QTable::numRows
 | 
|---|
| 4694 |     \brief The number of rows in the table
 | 
|---|
| 4695 | 
 | 
|---|
| 4696 |     \sa numCols
 | 
|---|
| 4697 | */
 | 
|---|
| 4698 | 
 | 
|---|
| 4699 | int QTable::numRows() const
 | 
|---|
| 4700 | {
 | 
|---|
| 4701 |     return leftHeader->count();
 | 
|---|
| 4702 | }
 | 
|---|
| 4703 | 
 | 
|---|
| 4704 | /*!
 | 
|---|
| 4705 |     \property QTable::numCols
 | 
|---|
| 4706 |     \brief The number of columns in the table
 | 
|---|
| 4707 | 
 | 
|---|
| 4708 |     \sa numRows
 | 
|---|
| 4709 | */
 | 
|---|
| 4710 | 
 | 
|---|
| 4711 | int QTable::numCols() const
 | 
|---|
| 4712 | {
 | 
|---|
| 4713 |     return topHeader->count();
 | 
|---|
| 4714 | }
 | 
|---|
| 4715 | 
 | 
|---|
| 4716 | void QTable::saveContents( QPtrVector<QTableItem> &tmp,
 | 
|---|
| 4717 |                            QPtrVector<QTable::TableWidget> &tmp2)
 | 
|---|
| 4718 | {
 | 
|---|
| 4719 |     int nCols = numCols();
 | 
|---|
| 4720 |     if ( editRow != -1 && editCol != -1 )
 | 
|---|
| 4721 |         endEdit( editRow, editCol, FALSE, edMode != Editing );
 | 
|---|
| 4722 |     tmp.resize( contents.size() );
 | 
|---|
| 4723 |     tmp2.resize( widgets.size() );
 | 
|---|
| 4724 |     int i;
 | 
|---|
| 4725 |     for ( i = 0; i < (int)tmp.size(); ++i ) {
 | 
|---|
| 4726 |         QTableItem *item = contents[ i ];
 | 
|---|
| 4727 |         if ( item && ( item->row() * nCols) + item->col() == i )
 | 
|---|
| 4728 |             tmp.insert( i, item );
 | 
|---|
| 4729 |         else
 | 
|---|
| 4730 |             tmp.insert( i, 0 );
 | 
|---|
| 4731 |     }
 | 
|---|
| 4732 |     for ( i = 0; i < (int)tmp2.size(); ++i ) {
 | 
|---|
| 4733 |         QWidget *w = widgets[ i ];
 | 
|---|
| 4734 |         if ( w )
 | 
|---|
| 4735 |             tmp2.insert( i, new TableWidget( w, i / nCols, i % nCols ) );
 | 
|---|
| 4736 |         else
 | 
|---|
| 4737 |             tmp2.insert( i, 0 );
 | 
|---|
| 4738 |     }
 | 
|---|
| 4739 | }
 | 
|---|
| 4740 | 
 | 
|---|
| 4741 | void QTable::updateHeaderAndResizeContents( QTableHeader *header,
 | 
|---|
| 4742 |                                             int num, int rowCol,
 | 
|---|
| 4743 |                                             int width, bool &updateBefore )
 | 
|---|
| 4744 | {
 | 
|---|
| 4745 |     updateBefore = rowCol < num;
 | 
|---|
| 4746 |     if ( rowCol > num ) {
 | 
|---|
| 4747 |         header->QHeader::resizeArrays( rowCol );
 | 
|---|
| 4748 |         header->QTableHeader::resizeArrays( rowCol );
 | 
|---|
| 4749 |         int old = num;
 | 
|---|
| 4750 |         clearSelection( FALSE );
 | 
|---|
| 4751 |         int i = 0;
 | 
|---|
| 4752 |         for ( i = old; i < rowCol; ++i )
 | 
|---|
| 4753 |             header->addLabel( QString::null, width );
 | 
|---|
| 4754 |     } else {
 | 
|---|
| 4755 |         clearSelection( FALSE );
 | 
|---|
| 4756 |         if ( header == leftHeader ) {
 | 
|---|
| 4757 |             while ( numRows() > rowCol )
 | 
|---|
| 4758 |                 header->removeLabel( numRows() - 1 );
 | 
|---|
| 4759 |         } else {
 | 
|---|
| 4760 |             while ( numCols() > rowCol )
 | 
|---|
| 4761 |                 header->removeLabel( numCols() - 1 );
 | 
|---|
| 4762 |         }
 | 
|---|
| 4763 |     }
 | 
|---|
| 4764 | 
 | 
|---|
| 4765 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 4766 |     contents.clear();
 | 
|---|
| 4767 |     contents.setAutoDelete( TRUE );
 | 
|---|
| 4768 |     widgets.setAutoDelete( FALSE );
 | 
|---|
| 4769 |     widgets.clear();
 | 
|---|
| 4770 |     widgets.setAutoDelete( TRUE );
 | 
|---|
| 4771 |     resizeData( numRows() * numCols() );
 | 
|---|
| 4772 | 
 | 
|---|
| 4773 |     // keep numStretches in sync
 | 
|---|
| 4774 |     int n = 0;
 | 
|---|
| 4775 |     for ( uint i = 0; i < header->stretchable.size(); i++ )
 | 
|---|
| 4776 |         n += ( header->stretchable.at(i) & 1 ); // avoid cmp
 | 
|---|
| 4777 |      header->numStretches = n;
 | 
|---|
| 4778 | }
 | 
|---|
| 4779 | 
 | 
|---|
| 4780 | void QTable::restoreContents( QPtrVector<QTableItem> &tmp,
 | 
|---|
| 4781 |                               QPtrVector<QTable::TableWidget> &tmp2 )
 | 
|---|
| 4782 | {
 | 
|---|
| 4783 |     int i;
 | 
|---|
| 4784 |     int nCols = numCols();
 | 
|---|
| 4785 |     for ( i = 0; i < (int)tmp.size(); ++i ) {
 | 
|---|
| 4786 |         QTableItem *it = tmp[ i ];
 | 
|---|
| 4787 |         if ( it ) {
 | 
|---|
| 4788 |             int idx = ( it->row() * nCols ) + it->col();
 | 
|---|
| 4789 |             if ( (uint)idx < contents.size() &&
 | 
|---|
| 4790 |                  it->row() == idx /  nCols && it->col() == idx % nCols ) {
 | 
|---|
| 4791 |                 contents.insert( idx, it );
 | 
|---|
| 4792 |                 if ( it->rowSpan() > 1 || it->colSpan() > 1 ) {
 | 
|---|
| 4793 |                     int ridx, iidx;
 | 
|---|
| 4794 |                     for ( int irow = 0; irow < it->rowSpan(); irow++ ) {
 | 
|---|
| 4795 |                         ridx = idx + irow * nCols;
 | 
|---|
| 4796 |                         for ( int icol = 0; icol < it->colSpan(); icol++ ) {
 | 
|---|
| 4797 |                             iidx = ridx + icol;
 | 
|---|
| 4798 |                             if ( idx != iidx && (uint)iidx < contents.size() )
 | 
|---|
| 4799 |                                 contents.insert( iidx, it );
 | 
|---|
| 4800 |                         }
 | 
|---|
| 4801 |                     }
 | 
|---|
| 4802 | 
 | 
|---|
| 4803 |                 }
 | 
|---|
| 4804 |             } else {
 | 
|---|
| 4805 |                 delete it;
 | 
|---|
| 4806 |             }
 | 
|---|
| 4807 |         }
 | 
|---|
| 4808 |     }
 | 
|---|
| 4809 |     for ( i = 0; i < (int)tmp2.size(); ++i ) {
 | 
|---|
| 4810 |         TableWidget *w = tmp2[ i ];
 | 
|---|
| 4811 |         if ( w ) {
 | 
|---|
| 4812 |             int idx = ( w->row * nCols ) + w->col;
 | 
|---|
| 4813 |             if ( (uint)idx < widgets.size() &&
 | 
|---|
| 4814 |                  w->row == idx / nCols && w->col == idx % nCols )
 | 
|---|
| 4815 |                 widgets.insert( idx, w->wid );
 | 
|---|
| 4816 |             else
 | 
|---|
| 4817 |                 delete w->wid;
 | 
|---|
| 4818 |             delete w;
 | 
|---|
| 4819 |         }
 | 
|---|
| 4820 |     }
 | 
|---|
| 4821 | }
 | 
|---|
| 4822 | 
 | 
|---|
| 4823 | void QTable::finishContentsResze( bool updateBefore )
 | 
|---|
| 4824 | {
 | 
|---|
| 4825 |     QRect r( cellGeometry( numRows() - 1, numCols() - 1 ) );
 | 
|---|
| 4826 |     resizeContents( r.right() + 1, r.bottom() + 1 );
 | 
|---|
| 4827 |     updateGeometries();
 | 
|---|
| 4828 |     if ( updateBefore )
 | 
|---|
| 4829 |         repaintContents( contentsX(), contentsY(),
 | 
|---|
| 4830 |                          visibleWidth(), visibleHeight(), TRUE );
 | 
|---|
| 4831 |     else
 | 
|---|
| 4832 |         repaintContents( contentsX(), contentsY(),
 | 
|---|
| 4833 |                          visibleWidth(), visibleHeight(), FALSE );
 | 
|---|
| 4834 | 
 | 
|---|
| 4835 |     if ( isRowSelection( selectionMode() ) ) {
 | 
|---|
| 4836 |         int r = curRow;
 | 
|---|
| 4837 |         curRow = -1;
 | 
|---|
| 4838 |         setCurrentCell( r, curCol );
 | 
|---|
| 4839 |     }
 | 
|---|
| 4840 | }
 | 
|---|
| 4841 | 
 | 
|---|
| 4842 | void QTable::setNumRows( int r )
 | 
|---|
| 4843 | {
 | 
|---|
| 4844 |     if ( r < 0 )
 | 
|---|
| 4845 |         return;
 | 
|---|
| 4846 | 
 | 
|---|
| 4847 |     if (r < numRows()) {
 | 
|---|
| 4848 |         // Removed rows are no longer hidden, and should thus be removed from "hiddenRows"
 | 
|---|
| 4849 |         for (int rr = numRows()-1; rr >= r; --rr) {
 | 
|---|
| 4850 |             if (d->hiddenRows.find(rr))
 | 
|---|
| 4851 |                 d->hiddenRows.remove(rr);
 | 
|---|
| 4852 |         }
 | 
|---|
| 4853 |     }
 | 
|---|
| 4854 | 
 | 
|---|
| 4855 |     QPtrVector<QTableItem> tmp;
 | 
|---|
| 4856 |     QPtrVector<TableWidget> tmp2;
 | 
|---|
| 4857 |     saveContents( tmp, tmp2 );
 | 
|---|
| 4858 | 
 | 
|---|
| 4859 |     bool isUpdatesEnabled = leftHeader->isUpdatesEnabled();
 | 
|---|
| 4860 |     leftHeader->setUpdatesEnabled( FALSE );
 | 
|---|
| 4861 | 
 | 
|---|
| 4862 |     bool updateBefore;
 | 
|---|
| 4863 |     updateHeaderAndResizeContents( leftHeader, numRows(), r, 20, updateBefore );
 | 
|---|
| 4864 | 
 | 
|---|
| 4865 |     int w = fontMetrics().width( QString::number( r ) + "W" );
 | 
|---|
| 4866 |     if ( VERTICALMARGIN > 0 && w > VERTICALMARGIN )
 | 
|---|
| 4867 |         setLeftMargin( w );
 | 
|---|
| 4868 | 
 | 
|---|
| 4869 |     restoreContents( tmp, tmp2 );
 | 
|---|
| 4870 | 
 | 
|---|
| 4871 |     leftHeader->calculatePositions();
 | 
|---|
| 4872 |     finishContentsResze( updateBefore );
 | 
|---|
| 4873 |     leftHeader->setUpdatesEnabled( isUpdatesEnabled );
 | 
|---|
| 4874 |     if ( isUpdatesEnabled )
 | 
|---|
| 4875 |         leftHeader->update();
 | 
|---|
| 4876 |     leftHeader->updateCache();
 | 
|---|
| 4877 |     if ( curRow >= numRows() ) {
 | 
|---|
| 4878 |         curRow = numRows() - 1;
 | 
|---|
| 4879 |         if ( curRow < 0 )
 | 
|---|
| 4880 |             curCol = -1;
 | 
|---|
| 4881 |         else
 | 
|---|
| 4882 |             repaintCell( curRow, curCol );
 | 
|---|
| 4883 |     }
 | 
|---|
| 4884 | 
 | 
|---|
| 4885 |     if ( curRow > numRows() )
 | 
|---|
| 4886 |         curRow = numRows();
 | 
|---|
| 4887 | }
 | 
|---|
| 4888 | 
 | 
|---|
| 4889 | void QTable::setNumCols( int c )
 | 
|---|
| 4890 | {
 | 
|---|
| 4891 |     if ( c < 0 )
 | 
|---|
| 4892 |         return;
 | 
|---|
| 4893 | 
 | 
|---|
| 4894 |     if (c < numCols()) {
 | 
|---|
| 4895 |         // Removed columns are no longer hidden, and should thus be removed from "hiddenCols"
 | 
|---|
| 4896 |         for (int cc = numCols()-1; cc >= c; --cc) {
 | 
|---|
| 4897 |             if (d->hiddenCols.find(cc))
 | 
|---|
| 4898 |                 d->hiddenCols.remove(cc);
 | 
|---|
| 4899 |         }
 | 
|---|
| 4900 |     }
 | 
|---|
| 4901 | 
 | 
|---|
| 4902 |     QPtrVector<QTableItem> tmp;
 | 
|---|
| 4903 |     QPtrVector<TableWidget> tmp2;
 | 
|---|
| 4904 |     saveContents( tmp, tmp2 );
 | 
|---|
| 4905 | 
 | 
|---|
| 4906 |     bool isUpdatesEnabled = topHeader->isUpdatesEnabled();
 | 
|---|
| 4907 |     topHeader->setUpdatesEnabled( FALSE );
 | 
|---|
| 4908 | 
 | 
|---|
| 4909 |     bool updateBefore;
 | 
|---|
| 4910 |     updateHeaderAndResizeContents( topHeader, numCols(), c, 100, updateBefore );
 | 
|---|
| 4911 | 
 | 
|---|
| 4912 |     restoreContents( tmp, tmp2 );
 | 
|---|
| 4913 | 
 | 
|---|
| 4914 |     topHeader->calculatePositions();
 | 
|---|
| 4915 |     finishContentsResze( updateBefore );
 | 
|---|
| 4916 |     topHeader->setUpdatesEnabled( isUpdatesEnabled );
 | 
|---|
| 4917 |     if ( isUpdatesEnabled )
 | 
|---|
| 4918 |         topHeader->update();
 | 
|---|
| 4919 |     topHeader->updateCache();
 | 
|---|
| 4920 |     if ( curCol >= numCols() ) {
 | 
|---|
| 4921 |         curCol = numCols() - 1;
 | 
|---|
| 4922 |         if ( curCol < 0 )
 | 
|---|
| 4923 |             curRow = -1;
 | 
|---|
| 4924 |         else
 | 
|---|
| 4925 |             repaintCell( curRow, curCol );
 | 
|---|
| 4926 |     }
 | 
|---|
| 4927 | }
 | 
|---|
| 4928 | 
 | 
|---|
| 4929 | /*! Sets the section labels of the verticalHeader() to \a labels */
 | 
|---|
| 4930 | 
 | 
|---|
| 4931 | void QTable::setRowLabels( const QStringList &labels )
 | 
|---|
| 4932 | {
 | 
|---|
| 4933 |     leftHeader->setLabels(labels);
 | 
|---|
| 4934 | }
 | 
|---|
| 4935 | 
 | 
|---|
| 4936 | /*! Sets the section labels of the horizontalHeader() to \a labels */
 | 
|---|
| 4937 | 
 | 
|---|
| 4938 | void QTable::setColumnLabels( const QStringList &labels )
 | 
|---|
| 4939 | {
 | 
|---|
| 4940 |    topHeader->setLabels(labels);
 | 
|---|
| 4941 | }
 | 
|---|
| 4942 | 
 | 
|---|
| 4943 | /*!
 | 
|---|
| 4944 |     This function returns the widget which should be used as an editor
 | 
|---|
| 4945 |     for the contents of the cell at \a row, \a col.
 | 
|---|
| 4946 | 
 | 
|---|
| 4947 |     If \a initFromCell is TRUE, the editor is used to edit the current
 | 
|---|
| 4948 |     contents of the cell (so the editor widget should be initialized
 | 
|---|
| 4949 |     with this content). If \a initFromCell is FALSE, the content of
 | 
|---|
| 4950 |     the cell is replaced with the new content which the user entered
 | 
|---|
| 4951 |     into the widget created by this function.
 | 
|---|
| 4952 | 
 | 
|---|
| 4953 |     The default functionality is as follows: if \a initFromCell is
 | 
|---|
| 4954 |     TRUE or the cell has a QTableItem and the table item's
 | 
|---|
| 4955 |     QTableItem::isReplaceable() is FALSE then the cell is asked to
 | 
|---|
| 4956 |     create an appropriate editor (using QTableItem::createEditor()).
 | 
|---|
| 4957 |     Otherwise a QLineEdit is used as the editor.
 | 
|---|
| 4958 | 
 | 
|---|
| 4959 |     If you want to create your own editor for certain cells, implement
 | 
|---|
| 4960 |     a custom QTableItem subclass and reimplement
 | 
|---|
| 4961 |     QTableItem::createEditor().
 | 
|---|
| 4962 | 
 | 
|---|
| 4963 |     If you are not using \l{QTableItem}s and you don't want to use a
 | 
|---|
| 4964 |     QLineEdit as the default editor, subclass QTable and reimplement
 | 
|---|
| 4965 |     this function with code like this:
 | 
|---|
| 4966 |     \code
 | 
|---|
| 4967 |     QTableItem *i = item( row, col );
 | 
|---|
| 4968 |     if ( initFromCell || ( i && !i->isReplaceable() ) )
 | 
|---|
| 4969 |         // If we had a QTableItem ask the base class to create the editor
 | 
|---|
| 4970 |         return QTable::createEditor( row, col, initFromCell );
 | 
|---|
| 4971 |     else
 | 
|---|
| 4972 |         return ...(create your own editor)
 | 
|---|
| 4973 |     \endcode
 | 
|---|
| 4974 |     Ownership of the editor widget is transferred to the caller.
 | 
|---|
| 4975 | 
 | 
|---|
| 4976 |     If you reimplement this function return 0 for read-only cells. You
 | 
|---|
| 4977 |     will need to reimplement setCellContentFromEditor() to retrieve
 | 
|---|
| 4978 |     the data the user entered.
 | 
|---|
| 4979 | 
 | 
|---|
| 4980 |     \sa QTableItem::createEditor()
 | 
|---|
| 4981 | */
 | 
|---|
| 4982 | 
 | 
|---|
| 4983 | QWidget *QTable::createEditor( int row, int col, bool initFromCell ) const
 | 
|---|
| 4984 | {
 | 
|---|
| 4985 |     if ( isReadOnly() || isRowReadOnly( row ) || isColumnReadOnly( col ) )
 | 
|---|
| 4986 |         return 0;
 | 
|---|
| 4987 | 
 | 
|---|
| 4988 |     QWidget *e = 0;
 | 
|---|
| 4989 | 
 | 
|---|
| 4990 |     // the current item in the cell should be edited if possible
 | 
|---|
| 4991 |     QTableItem *i = item( row, col );
 | 
|---|
| 4992 |     if ( initFromCell || ( i && !i->isReplaceable() ) ) {
 | 
|---|
| 4993 |         if ( i ) {
 | 
|---|
| 4994 |             if ( i->editType() == QTableItem::Never )
 | 
|---|
| 4995 |                 return 0;
 | 
|---|
| 4996 | 
 | 
|---|
| 4997 |             e = i->createEditor();
 | 
|---|
| 4998 |             if ( !e )
 | 
|---|
| 4999 |                 return 0;
 | 
|---|
| 5000 |         }
 | 
|---|
| 5001 |     }
 | 
|---|
| 5002 | 
 | 
|---|
| 5003 |     // no contents in the cell yet, so open the default editor
 | 
|---|
| 5004 |     if ( !e ) {
 | 
|---|
| 5005 |         e = new QLineEdit( viewport(), "qt_lineeditor" );
 | 
|---|
| 5006 |         ( (QLineEdit*)e )->setFrame( FALSE );
 | 
|---|
| 5007 |     }
 | 
|---|
| 5008 | 
 | 
|---|
| 5009 |     return e;
 | 
|---|
| 5010 | }
 | 
|---|
| 5011 | 
 | 
|---|
| 5012 | /*!
 | 
|---|
| 5013 |     This function is called to start in-place editing of the cell at
 | 
|---|
| 5014 |     \a row, \a col. Editing is achieved by creating an editor
 | 
|---|
| 5015 |     (createEditor() is called) and setting the cell's editor with
 | 
|---|
| 5016 |     setCellWidget() to the newly created editor. (After editing is
 | 
|---|
| 5017 |     complete endEdit() will be called to replace the cell's content
 | 
|---|
| 5018 |     with the editor's content.) If \a replace is TRUE the editor will
 | 
|---|
| 5019 |     start empty; otherwise it will be initialized with the cell's
 | 
|---|
| 5020 |     content (if any), i.e. the user will be modifying the original
 | 
|---|
| 5021 |     cell content.
 | 
|---|
| 5022 | 
 | 
|---|
| 5023 |     \sa endEdit()
 | 
|---|
| 5024 | */
 | 
|---|
| 5025 | 
 | 
|---|
| 5026 | QWidget *QTable::beginEdit( int row, int col, bool replace )
 | 
|---|
| 5027 | {
 | 
|---|
| 5028 |     if ( isReadOnly() || isRowReadOnly( row ) || isColumnReadOnly( col ) )
 | 
|---|
| 5029 |         return 0;
 | 
|---|
| 5030 |     QTableItem *itm = item( row, col );
 | 
|---|
| 5031 |     if ( itm && !itm->isEnabled() )
 | 
|---|
| 5032 |         return 0;
 | 
|---|
| 5033 |     if ( cellWidget( row, col ) )
 | 
|---|
| 5034 |         return 0;
 | 
|---|
| 5035 |     ensureCellVisible( row, col );
 | 
|---|
| 5036 |     QWidget *e = createEditor( row, col, !replace );
 | 
|---|
| 5037 |     if ( !e )
 | 
|---|
| 5038 |         return 0;
 | 
|---|
| 5039 |     setCellWidget( row, col, e );
 | 
|---|
| 5040 |     e->setActiveWindow();
 | 
|---|
| 5041 |     e->setFocus();
 | 
|---|
| 5042 |     updateCell( row, col );
 | 
|---|
| 5043 |     return e;
 | 
|---|
| 5044 | }
 | 
|---|
| 5045 | 
 | 
|---|
| 5046 | /*!
 | 
|---|
| 5047 |     This function is called when in-place editing of the cell at \a
 | 
|---|
| 5048 |     row, \a col is requested to stop.
 | 
|---|
| 5049 | 
 | 
|---|
| 5050 |     If the cell is not being edited or \a accept is FALSE the function
 | 
|---|
| 5051 |     returns and the cell's contents are left unchanged.
 | 
|---|
| 5052 | 
 | 
|---|
| 5053 |     If \a accept is TRUE the content of the editor must be transferred
 | 
|---|
| 5054 |     to the relevant cell. If \a replace is TRUE the current content of
 | 
|---|
| 5055 |     this cell should be replaced by the content of the editor (this
 | 
|---|
| 5056 |     means removing the current QTableItem of the cell and creating a
 | 
|---|
| 5057 |     new one for the cell). Otherwise (if possible) the content of the
 | 
|---|
| 5058 |     editor should just be set to the existing QTableItem of this cell.
 | 
|---|
| 5059 | 
 | 
|---|
| 5060 |     setCellContentFromEditor() is called to replace the contents of
 | 
|---|
| 5061 |     the cell with the contents of the cell's editor.
 | 
|---|
| 5062 | 
 | 
|---|
| 5063 |     Finally clearCellWidget() is called to remove the editor widget.
 | 
|---|
| 5064 | 
 | 
|---|
| 5065 |     \sa setCellContentFromEditor(), beginEdit()
 | 
|---|
| 5066 | */
 | 
|---|
| 5067 | 
 | 
|---|
| 5068 | void QTable::endEdit( int row, int col, bool accept, bool replace )
 | 
|---|
| 5069 | {
 | 
|---|
| 5070 |     QWidget *editor = cellWidget( row, col );
 | 
|---|
| 5071 |     if ( !editor )
 | 
|---|
| 5072 |         return;
 | 
|---|
| 5073 | 
 | 
|---|
| 5074 |     if ( !accept ) {
 | 
|---|
| 5075 |         if ( row == editRow && col == editCol )
 | 
|---|
| 5076 |             setEditMode( NotEditing, -1, -1 );
 | 
|---|
| 5077 |         clearCellWidget( row, col );
 | 
|---|
| 5078 |         updateCell( row, col );
 | 
|---|
| 5079 |         viewport()->setFocus();
 | 
|---|
| 5080 |         updateCell( row, col );
 | 
|---|
| 5081 |         return;
 | 
|---|
| 5082 |     }
 | 
|---|
| 5083 | 
 | 
|---|
| 5084 |     QTableItem *i = item( row, col );
 | 
|---|
| 5085 |     QString oldContent;
 | 
|---|
| 5086 |     if ( i )
 | 
|---|
| 5087 |         oldContent = i->text();
 | 
|---|
| 5088 | 
 | 
|---|
| 5089 |     if ( !i || replace ) {
 | 
|---|
| 5090 |         setCellContentFromEditor( row, col );
 | 
|---|
| 5091 |         i = item( row, col );
 | 
|---|
| 5092 |     } else {
 | 
|---|
| 5093 |         i->setContentFromEditor( editor );
 | 
|---|
| 5094 |     }
 | 
|---|
| 5095 | 
 | 
|---|
| 5096 |     if ( row == editRow && col == editCol )
 | 
|---|
| 5097 |         setEditMode( NotEditing, -1, -1 );
 | 
|---|
| 5098 | 
 | 
|---|
| 5099 |     viewport()->setFocus();
 | 
|---|
| 5100 |     updateCell( row, col );
 | 
|---|
| 5101 | 
 | 
|---|
| 5102 |     if (!i || (oldContent != i->text()))
 | 
|---|
| 5103 |         emit valueChanged( row, col );
 | 
|---|
| 5104 | 
 | 
|---|
| 5105 |     clearCellWidget( row, col );
 | 
|---|
| 5106 | }
 | 
|---|
| 5107 | 
 | 
|---|
| 5108 | /*!
 | 
|---|
| 5109 |     This function is called to replace the contents of the cell at \a
 | 
|---|
| 5110 |     row, \a col with the contents of the cell's editor.
 | 
|---|
| 5111 | 
 | 
|---|
| 5112 |     If there already exists a QTableItem for the cell,
 | 
|---|
| 5113 |     it calls QTableItem::setContentFromEditor() on this QTableItem.
 | 
|---|
| 5114 | 
 | 
|---|
| 5115 |     If, for example, you want to create different \l{QTableItem}s
 | 
|---|
| 5116 |     depending on the contents of the editor, you might reimplement
 | 
|---|
| 5117 |     this function.
 | 
|---|
| 5118 | 
 | 
|---|
| 5119 |     If you want to work without \l{QTableItem}s, you will need to
 | 
|---|
| 5120 |     reimplement this function to save the data the user entered into
 | 
|---|
| 5121 |     your data structure. (See the notes on large tables.)
 | 
|---|
| 5122 | 
 | 
|---|
| 5123 |     \sa QTableItem::setContentFromEditor() createEditor()
 | 
|---|
| 5124 | */
 | 
|---|
| 5125 | 
 | 
|---|
| 5126 | void QTable::setCellContentFromEditor( int row, int col )
 | 
|---|
| 5127 | {
 | 
|---|
| 5128 |     QWidget *editor = cellWidget( row, col );
 | 
|---|
| 5129 |     if ( !editor )
 | 
|---|
| 5130 |         return;
 | 
|---|
| 5131 | 
 | 
|---|
| 5132 |     QTableItem *i = item( row, col );
 | 
|---|
| 5133 |     if ( i ) {
 | 
|---|
| 5134 |         i->setContentFromEditor( editor );
 | 
|---|
| 5135 |     } else {
 | 
|---|
| 5136 |         QLineEdit *le = ::qt_cast<QLineEdit*>(editor);
 | 
|---|
| 5137 |         if ( le )
 | 
|---|
| 5138 |             setText( row, col, le->text() );
 | 
|---|
| 5139 |     }
 | 
|---|
| 5140 | }
 | 
|---|
| 5141 | 
 | 
|---|
| 5142 | /*!
 | 
|---|
| 5143 |     Returns TRUE if the \l EditMode is \c Editing or \c Replacing;
 | 
|---|
| 5144 |     otherwise (i.e. the \l EditMode is \c NotEditing) returns FALSE.
 | 
|---|
| 5145 | 
 | 
|---|
| 5146 |     \sa QTable::EditMode
 | 
|---|
| 5147 | */
 | 
|---|
| 5148 | 
 | 
|---|
| 5149 | bool QTable::isEditing() const
 | 
|---|
| 5150 | {
 | 
|---|
| 5151 |     return edMode != NotEditing;
 | 
|---|
| 5152 | }
 | 
|---|
| 5153 | 
 | 
|---|
| 5154 | /*!
 | 
|---|
| 5155 |     Returns the current edit mode
 | 
|---|
| 5156 | 
 | 
|---|
| 5157 |     \sa QTable::EditMode
 | 
|---|
| 5158 | */
 | 
|---|
| 5159 | 
 | 
|---|
| 5160 | QTable::EditMode QTable::editMode() const
 | 
|---|
| 5161 | {
 | 
|---|
| 5162 |     return edMode;
 | 
|---|
| 5163 | }
 | 
|---|
| 5164 | 
 | 
|---|
| 5165 | /*!
 | 
|---|
| 5166 |     Returns the current edited row
 | 
|---|
| 5167 | */
 | 
|---|
| 5168 | 
 | 
|---|
| 5169 | int QTable::currEditRow() const
 | 
|---|
| 5170 | {
 | 
|---|
| 5171 |     return editRow;
 | 
|---|
| 5172 | }
 | 
|---|
| 5173 | 
 | 
|---|
| 5174 | /*!
 | 
|---|
| 5175 |     Returns the current edited column
 | 
|---|
| 5176 | */
 | 
|---|
| 5177 | 
 | 
|---|
| 5178 | int QTable::currEditCol() const
 | 
|---|
| 5179 | {
 | 
|---|
| 5180 |     return editCol;
 | 
|---|
| 5181 | }
 | 
|---|
| 5182 | 
 | 
|---|
| 5183 | /*!
 | 
|---|
| 5184 |     Returns a single integer which identifies a particular \a row and \a
 | 
|---|
| 5185 |     col by mapping the 2D table to a 1D array.
 | 
|---|
| 5186 | 
 | 
|---|
| 5187 |     This is useful, for example, if you have a sparse table and want to
 | 
|---|
| 5188 |     use a QIntDict to map integers to the cells that are used.
 | 
|---|
| 5189 | */
 | 
|---|
| 5190 | 
 | 
|---|
| 5191 | int QTable::indexOf( int row, int col ) const
 | 
|---|
| 5192 | {
 | 
|---|
| 5193 |     return ( row * numCols() ) + col;
 | 
|---|
| 5194 | }
 | 
|---|
| 5195 | 
 | 
|---|
| 5196 | /*! \internal
 | 
|---|
| 5197 | */
 | 
|---|
| 5198 | 
 | 
|---|
| 5199 | void QTable::repaintSelections( QTableSelection *oldSelection,
 | 
|---|
| 5200 |                                 QTableSelection *newSelection,
 | 
|---|
| 5201 |                                 bool updateVertical, bool updateHorizontal )
 | 
|---|
| 5202 | {
 | 
|---|
| 5203 |     if ( !oldSelection && !newSelection )
 | 
|---|
| 5204 |         return;
 | 
|---|
| 5205 |     if ( oldSelection && newSelection && *oldSelection == *newSelection )
 | 
|---|
| 5206 |         return;
 | 
|---|
| 5207 |     if ( oldSelection && !oldSelection->isActive() )
 | 
|---|
| 5208 |         oldSelection = 0;
 | 
|---|
| 5209 | 
 | 
|---|
| 5210 |     bool optimizeOld = FALSE;
 | 
|---|
| 5211 |     bool optimizeNew = FALSE;
 | 
|---|
| 5212 | 
 | 
|---|
| 5213 |     QRect old;
 | 
|---|
| 5214 |     if ( oldSelection )
 | 
|---|
| 5215 |         old = rangeGeometry( oldSelection->topRow(),
 | 
|---|
| 5216 |                              oldSelection->leftCol(),
 | 
|---|
| 5217 |                              oldSelection->bottomRow(),
 | 
|---|
| 5218 |                              oldSelection->rightCol(),
 | 
|---|
| 5219 |                              optimizeOld );
 | 
|---|
| 5220 |     else
 | 
|---|
| 5221 |         old = QRect( 0, 0, 0, 0 );
 | 
|---|
| 5222 | 
 | 
|---|
| 5223 |     QRect cur;
 | 
|---|
| 5224 |     if ( newSelection )
 | 
|---|
| 5225 |         cur = rangeGeometry( newSelection->topRow(),
 | 
|---|
| 5226 |                              newSelection->leftCol(),
 | 
|---|
| 5227 |                              newSelection->bottomRow(),
 | 
|---|
| 5228 |                              newSelection->rightCol(),
 | 
|---|
| 5229 |                              optimizeNew );
 | 
|---|
| 5230 |     else
 | 
|---|
| 5231 |         cur = QRect( 0, 0, 0, 0 );
 | 
|---|
| 5232 |     int i;
 | 
|---|
| 5233 | 
 | 
|---|
| 5234 |     if ( !optimizeOld || !optimizeNew ||
 | 
|---|
| 5235 |          old.width() > SHRT_MAX || old.height() > SHRT_MAX ||
 | 
|---|
| 5236 |          cur.width() > SHRT_MAX || cur.height() > SHRT_MAX ) {
 | 
|---|
| 5237 |         QRect rr = cur.unite( old );
 | 
|---|
| 5238 |         repaintContents( rr, FALSE );
 | 
|---|
| 5239 |     } else {
 | 
|---|
| 5240 |         old = QRect( contentsToViewport2( old.topLeft() ), old.size() );
 | 
|---|
| 5241 |         cur = QRect( contentsToViewport2( cur.topLeft() ), cur.size() );
 | 
|---|
| 5242 |         QRegion r1( old );
 | 
|---|
| 5243 |         QRegion r2( cur );
 | 
|---|
| 5244 |         QRegion r3 = r1.subtract( r2 );
 | 
|---|
| 5245 |         QRegion r4 = r2.subtract( r1 );
 | 
|---|
| 5246 | 
 | 
|---|
| 5247 |         for ( i = 0; i < (int)r3.rects().count(); ++i ) {
 | 
|---|
| 5248 |             QRect r( r3.rects()[ i ] );
 | 
|---|
| 5249 |             r = QRect( viewportToContents2( r.topLeft() ), r.size() );
 | 
|---|
| 5250 |             repaintContents( r, FALSE );
 | 
|---|
| 5251 |         }
 | 
|---|
| 5252 |         for ( i = 0; i < (int)r4.rects().count(); ++i ) {
 | 
|---|
| 5253 |             QRect r( r4.rects()[ i ] );
 | 
|---|
| 5254 |             r = QRect( viewportToContents2( r.topLeft() ), r.size() );
 | 
|---|
| 5255 |             repaintContents( r, FALSE );
 | 
|---|
| 5256 |         }
 | 
|---|
| 5257 |     }
 | 
|---|
| 5258 | 
 | 
|---|
| 5259 |     int top, left, bottom, right;
 | 
|---|
| 5260 |     top = QMIN( oldSelection ? oldSelection->topRow() : newSelection->topRow(),
 | 
|---|
| 5261 |                 newSelection ? newSelection->topRow() :oldSelection->topRow() );
 | 
|---|
| 5262 |     left = QMIN( oldSelection ? oldSelection->leftCol() : newSelection->leftCol(),
 | 
|---|
| 5263 |                  newSelection ? newSelection->leftCol() : oldSelection->leftCol() );
 | 
|---|
| 5264 |     bottom = QMAX( oldSelection ? oldSelection->bottomRow() : newSelection->bottomRow(),
 | 
|---|
| 5265 |                    newSelection ? newSelection->bottomRow() : oldSelection->bottomRow() );
 | 
|---|
| 5266 |     right = QMAX( oldSelection ? oldSelection->rightCol() : newSelection->rightCol(),
 | 
|---|
| 5267 |                   newSelection ? newSelection->rightCol() : oldSelection->rightCol() );
 | 
|---|
| 5268 | 
 | 
|---|
| 5269 |     if ( updateHorizontal && numCols() > 0 && left >= 0 && !isRowSelection( selectionMode() ) ) {
 | 
|---|
| 5270 |         register int *s = &topHeader->states.data()[left];
 | 
|---|
| 5271 |         for ( i = left; i <= right; ++i ) {
 | 
|---|
| 5272 |             if ( !isColumnSelected( i ) )
 | 
|---|
| 5273 |                 *s = QTableHeader::Normal;
 | 
|---|
| 5274 |             else if ( isColumnSelected( i, TRUE ) )
 | 
|---|
| 5275 |                 *s = QTableHeader::Selected;
 | 
|---|
| 5276 |             else
 | 
|---|
| 5277 |                 *s = QTableHeader::Bold;
 | 
|---|
| 5278 |             ++s;
 | 
|---|
| 5279 |         }
 | 
|---|
| 5280 |         topHeader->repaint( FALSE );
 | 
|---|
| 5281 |     }
 | 
|---|
| 5282 | 
 | 
|---|
| 5283 |     if ( updateVertical && numRows() > 0 && top >= 0 ) {
 | 
|---|
| 5284 |         register int *s = &leftHeader->states.data()[top];
 | 
|---|
| 5285 |         for ( i = top; i <= bottom; ++i ) {
 | 
|---|
| 5286 |             if ( !isRowSelected( i ) )
 | 
|---|
| 5287 |                 *s = QTableHeader::Normal;
 | 
|---|
| 5288 |             else if ( isRowSelected( i, TRUE ) )
 | 
|---|
| 5289 |                 *s = QTableHeader::Selected;
 | 
|---|
| 5290 |             else
 | 
|---|
| 5291 |                 *s = QTableHeader::Bold;
 | 
|---|
| 5292 |             ++s;
 | 
|---|
| 5293 |         }
 | 
|---|
| 5294 |         leftHeader->repaint( FALSE );
 | 
|---|
| 5295 |     }
 | 
|---|
| 5296 | }
 | 
|---|
| 5297 | 
 | 
|---|
| 5298 | /*!
 | 
|---|
| 5299 |     Repaints all selections
 | 
|---|
| 5300 | */
 | 
|---|
| 5301 | 
 | 
|---|
| 5302 | void QTable::repaintSelections()
 | 
|---|
| 5303 | {
 | 
|---|
| 5304 |     if ( selections.isEmpty() )
 | 
|---|
| 5305 |         return;
 | 
|---|
| 5306 | 
 | 
|---|
| 5307 |     QRect r;
 | 
|---|
| 5308 |     for ( QTableSelection *s = selections.first(); s; s = selections.next() ) {
 | 
|---|
| 5309 |         bool b;
 | 
|---|
| 5310 |         r = r.unite( rangeGeometry( s->topRow(),
 | 
|---|
| 5311 |                                     s->leftCol(),
 | 
|---|
| 5312 |                                     s->bottomRow(),
 | 
|---|
| 5313 |                                     s->rightCol(), b ) );
 | 
|---|
| 5314 |     }
 | 
|---|
| 5315 | 
 | 
|---|
| 5316 |     repaintContents( r, FALSE );
 | 
|---|
| 5317 | }
 | 
|---|
| 5318 | 
 | 
|---|
| 5319 | /*!
 | 
|---|
| 5320 |     Clears all selections and repaints the appropriate regions if \a
 | 
|---|
| 5321 |     repaint is TRUE.
 | 
|---|
| 5322 | 
 | 
|---|
| 5323 |     \sa removeSelection()
 | 
|---|
| 5324 | */
 | 
|---|
| 5325 | 
 | 
|---|
| 5326 | void QTable::clearSelection( bool repaint )
 | 
|---|
| 5327 | {
 | 
|---|
| 5328 |     if ( selections.isEmpty() )
 | 
|---|
| 5329 |         return;
 | 
|---|
| 5330 |     bool needRepaint = !selections.isEmpty();
 | 
|---|
| 5331 | 
 | 
|---|
| 5332 |     QRect r;
 | 
|---|
| 5333 |     for ( QTableSelection *s = selections.first(); s; s = selections.next() ) {
 | 
|---|
| 5334 |         bool b;
 | 
|---|
| 5335 |         r = r.unite( rangeGeometry( s->topRow(),
 | 
|---|
| 5336 |                                     s->leftCol(),
 | 
|---|
| 5337 |                                     s->bottomRow(),
 | 
|---|
| 5338 |                                     s->rightCol(), b ) );
 | 
|---|
| 5339 |     }
 | 
|---|
| 5340 | 
 | 
|---|
| 5341 |     currentSel = 0;
 | 
|---|
| 5342 |     selections.clear();
 | 
|---|
| 5343 | 
 | 
|---|
| 5344 |     if ( needRepaint && repaint )
 | 
|---|
| 5345 |         repaintContents( r, FALSE );
 | 
|---|
| 5346 | 
 | 
|---|
| 5347 |     leftHeader->setSectionStateToAll( QTableHeader::Normal );
 | 
|---|
| 5348 |     leftHeader->repaint( FALSE );
 | 
|---|
| 5349 |     if ( !isRowSelection( selectionMode() ) ) {
 | 
|---|
| 5350 |         topHeader->setSectionStateToAll( QTableHeader::Normal );
 | 
|---|
| 5351 |         topHeader->repaint( FALSE );
 | 
|---|
| 5352 |     }
 | 
|---|
| 5353 |     topHeader->setSectionState( curCol, QTableHeader::Bold );
 | 
|---|
| 5354 |     leftHeader->setSectionState( curRow, QTableHeader::Bold );
 | 
|---|
| 5355 |     emit selectionChanged();
 | 
|---|
| 5356 | }
 | 
|---|
| 5357 | 
 | 
|---|
| 5358 | /*! \internal
 | 
|---|
| 5359 | */
 | 
|---|
| 5360 | 
 | 
|---|
| 5361 | QRect QTable::rangeGeometry( int topRow, int leftCol,
 | 
|---|
| 5362 |                              int bottomRow, int rightCol, bool &optimize )
 | 
|---|
| 5363 | {
 | 
|---|
| 5364 |     topRow = QMAX( topRow, rowAt( contentsY() ) );
 | 
|---|
| 5365 |     leftCol = QMAX( leftCol, columnAt( contentsX() ) );
 | 
|---|
| 5366 |     int ra = rowAt( contentsY() + visibleHeight() );
 | 
|---|
| 5367 |     if ( ra != -1 )
 | 
|---|
| 5368 |         bottomRow = QMIN( bottomRow, ra );
 | 
|---|
| 5369 |     int ca = columnAt( contentsX() + visibleWidth() );
 | 
|---|
| 5370 |     if ( ca != -1 )
 | 
|---|
| 5371 |         rightCol = QMIN( rightCol, ca );
 | 
|---|
| 5372 |     optimize = TRUE;
 | 
|---|
| 5373 |     QRect rect;
 | 
|---|
| 5374 |     for ( int r = topRow; r <= bottomRow; ++r ) {
 | 
|---|
| 5375 |         for ( int c = leftCol; c <= rightCol; ++c ) {
 | 
|---|
| 5376 |             rect = rect.unite( cellGeometry( r, c ) );
 | 
|---|
| 5377 |             QTableItem *i = item( r, c );
 | 
|---|
| 5378 |             if ( i && ( i->rowSpan() > 1 || i->colSpan() > 1 ) )
 | 
|---|
| 5379 |                 optimize = FALSE;
 | 
|---|
| 5380 |         }
 | 
|---|
| 5381 |     }
 | 
|---|
| 5382 |     return rect;
 | 
|---|
| 5383 | }
 | 
|---|
| 5384 | 
 | 
|---|
| 5385 | /*!
 | 
|---|
| 5386 |     This function is called to activate the next cell if in-place
 | 
|---|
| 5387 |     editing was finished by pressing the Enter key.
 | 
|---|
| 5388 | 
 | 
|---|
| 5389 |     The default behaviour is to move from top to bottom, i.e. move to
 | 
|---|
| 5390 |     the cell beneath the cell being edited. Reimplement this function
 | 
|---|
| 5391 |     if you want different behaviour, e.g. moving from left to right.
 | 
|---|
| 5392 | */
 | 
|---|
| 5393 | 
 | 
|---|
| 5394 | void QTable::activateNextCell()
 | 
|---|
| 5395 | {
 | 
|---|
| 5396 |     int firstRow = 0;
 | 
|---|
| 5397 |     while ( d->hiddenRows.find( firstRow ) )
 | 
|---|
| 5398 |         firstRow++;
 | 
|---|
| 5399 |     int firstCol = 0;
 | 
|---|
| 5400 |     while ( d->hiddenCols.find( firstCol ) )
 | 
|---|
| 5401 |         firstCol++;
 | 
|---|
| 5402 |     int nextRow = curRow;
 | 
|---|
| 5403 |     int nextCol = curCol;
 | 
|---|
| 5404 |     while ( d->hiddenRows.find( ++nextRow ) );
 | 
|---|
| 5405 |     if ( nextRow >= numRows() ) {
 | 
|---|
| 5406 |         nextRow = firstRow;
 | 
|---|
| 5407 |         while ( d->hiddenCols.find( ++nextCol ) );
 | 
|---|
| 5408 |         if ( nextCol >= numCols() )
 | 
|---|
| 5409 |             nextCol = firstCol;
 | 
|---|
| 5410 |     }
 | 
|---|
| 5411 | 
 | 
|---|
| 5412 |     if ( !currentSel || !currentSel->isActive() ||
 | 
|---|
| 5413 |          ( currentSel->leftCol() == currentSel->rightCol() &&
 | 
|---|
| 5414 |            currentSel->topRow() == currentSel->bottomRow() ) ) {
 | 
|---|
| 5415 |         clearSelection();
 | 
|---|
| 5416 |         setCurrentCell( nextRow, nextCol );
 | 
|---|
| 5417 |     } else {
 | 
|---|
| 5418 |         if ( curRow < currentSel->bottomRow() )
 | 
|---|
| 5419 |             setCurrentCell( nextRow, curCol );
 | 
|---|
| 5420 |         else if ( curCol < currentSel->rightCol() )
 | 
|---|
| 5421 |             setCurrentCell( currentSel->topRow(), nextCol );
 | 
|---|
| 5422 |         else
 | 
|---|
| 5423 |             setCurrentCell( currentSel->topRow(), currentSel->leftCol() );
 | 
|---|
| 5424 |     }
 | 
|---|
| 5425 | 
 | 
|---|
| 5426 | }
 | 
|---|
| 5427 | 
 | 
|---|
| 5428 | /*! \internal
 | 
|---|
| 5429 | */
 | 
|---|
| 5430 | 
 | 
|---|
| 5431 | void QTable::fixRow( int &row, int y )
 | 
|---|
| 5432 | {
 | 
|---|
| 5433 |     if ( row == -1 ) {
 | 
|---|
| 5434 |         if ( y < 0 )
 | 
|---|
| 5435 |             row = 0;
 | 
|---|
| 5436 |         else
 | 
|---|
| 5437 |             row = numRows() - 1;
 | 
|---|
| 5438 |     }
 | 
|---|
| 5439 | }
 | 
|---|
| 5440 | 
 | 
|---|
| 5441 | /*! \internal
 | 
|---|
| 5442 | */
 | 
|---|
| 5443 | 
 | 
|---|
| 5444 | void QTable::fixCol( int &col, int x )
 | 
|---|
| 5445 | {
 | 
|---|
| 5446 |     if ( col == -1 ) {
 | 
|---|
| 5447 |         if ( x < 0 )
 | 
|---|
| 5448 |             col = 0;
 | 
|---|
| 5449 |         else
 | 
|---|
| 5450 |             col = numCols() - 1;
 | 
|---|
| 5451 |     }
 | 
|---|
| 5452 | }
 | 
|---|
| 5453 | 
 | 
|---|
| 5454 | struct SortableTableItem
 | 
|---|
| 5455 | {
 | 
|---|
| 5456 |     QTableItem *item;
 | 
|---|
| 5457 | };
 | 
|---|
| 5458 | 
 | 
|---|
| 5459 | #if defined(Q_C_CALLBACKS)
 | 
|---|
| 5460 | extern "C" {
 | 
|---|
| 5461 | #endif
 | 
|---|
| 5462 | 
 | 
|---|
| 5463 | #ifdef Q_OS_TEMP
 | 
|---|
| 5464 | static int _cdecl cmpTableItems( const void *n1, const void *n2 )
 | 
|---|
| 5465 | #else
 | 
|---|
| 5466 | static int cmpTableItems( const void *n1, const void *n2 )
 | 
|---|
| 5467 | #endif
 | 
|---|
| 5468 | {
 | 
|---|
| 5469 |     if ( !n1 || !n2 )
 | 
|---|
| 5470 |         return 0;
 | 
|---|
| 5471 | 
 | 
|---|
| 5472 |     SortableTableItem *i1 = (SortableTableItem *)n1;
 | 
|---|
| 5473 |     SortableTableItem *i2 = (SortableTableItem *)n2;
 | 
|---|
| 5474 | 
 | 
|---|
| 5475 |     return i1->item->key().localeAwareCompare( i2->item->key() );
 | 
|---|
| 5476 | }
 | 
|---|
| 5477 | 
 | 
|---|
| 5478 | #if defined(Q_C_CALLBACKS)
 | 
|---|
| 5479 | }
 | 
|---|
| 5480 | #endif
 | 
|---|
| 5481 | 
 | 
|---|
| 5482 | /*!
 | 
|---|
| 5483 |     Sorts column \a col. If \a ascending is TRUE the sort is in
 | 
|---|
| 5484 |     ascending order, otherwise the sort is in descending order.
 | 
|---|
| 5485 | 
 | 
|---|
| 5486 |     If \a wholeRows is TRUE, entire rows are sorted using swapRows();
 | 
|---|
| 5487 |     otherwise only cells in the column are sorted using swapCells().
 | 
|---|
| 5488 | 
 | 
|---|
| 5489 |     Note that if you are not using QTableItems you will need to
 | 
|---|
| 5490 |     reimplement swapRows() and swapCells(). (See the notes on large
 | 
|---|
| 5491 |     tables.)
 | 
|---|
| 5492 | 
 | 
|---|
| 5493 |     \sa swapRows()
 | 
|---|
| 5494 | */
 | 
|---|
| 5495 | 
 | 
|---|
| 5496 | void QTable::sortColumn( int col, bool ascending, bool wholeRows )
 | 
|---|
| 5497 | {
 | 
|---|
| 5498 |     int filledRows = 0, i;
 | 
|---|
| 5499 |     for ( i = 0; i < numRows(); ++i ) {
 | 
|---|
| 5500 |         QTableItem *itm = item( i, col );
 | 
|---|
| 5501 |         if ( itm )
 | 
|---|
| 5502 |             filledRows++;
 | 
|---|
| 5503 |     }
 | 
|---|
| 5504 | 
 | 
|---|
| 5505 |     if ( !filledRows )
 | 
|---|
| 5506 |         return;
 | 
|---|
| 5507 | 
 | 
|---|
| 5508 |     SortableTableItem *items = new SortableTableItem[ filledRows ];
 | 
|---|
| 5509 |     int j = 0;
 | 
|---|
| 5510 |     for ( i = 0; i < numRows(); ++i ) {
 | 
|---|
| 5511 |         QTableItem *itm = item( i, col );
 | 
|---|
| 5512 |         if ( !itm )
 | 
|---|
| 5513 |             continue;
 | 
|---|
| 5514 |         items[ j++ ].item = itm;
 | 
|---|
| 5515 |     }
 | 
|---|
| 5516 | 
 | 
|---|
| 5517 |     qsort( items, filledRows, sizeof( SortableTableItem ), cmpTableItems );
 | 
|---|
| 5518 | 
 | 
|---|
| 5519 |     bool updatesEnabled = isUpdatesEnabled();
 | 
|---|
| 5520 |     setUpdatesEnabled( FALSE );
 | 
|---|
| 5521 |     for ( i = 0; i < numRows(); ++i ) {
 | 
|---|
| 5522 |         if ( i < filledRows ) {
 | 
|---|
| 5523 |             if ( ascending ) {
 | 
|---|
| 5524 |                 if ( items[ i ].item->row() == i )
 | 
|---|
| 5525 |                     continue;
 | 
|---|
| 5526 |                 if ( wholeRows )
 | 
|---|
| 5527 |                     swapRows( items[ i ].item->row(), i );
 | 
|---|
| 5528 |                 else
 | 
|---|
| 5529 |                     swapCells( items[ i ].item->row(), col, i, col );
 | 
|---|
| 5530 |             } else {
 | 
|---|
| 5531 |                 if ( items[ i ].item->row() == filledRows - i - 1 )
 | 
|---|
| 5532 |                     continue;
 | 
|---|
| 5533 |                 if ( wholeRows )
 | 
|---|
| 5534 |                     swapRows( items[ i ].item->row(), filledRows - i - 1 );
 | 
|---|
| 5535 |                 else
 | 
|---|
| 5536 |                     swapCells( items[ i ].item->row(), col,
 | 
|---|
| 5537 |                                filledRows - i - 1, col );
 | 
|---|
| 5538 |             }
 | 
|---|
| 5539 |         }
 | 
|---|
| 5540 |     }
 | 
|---|
| 5541 |     setUpdatesEnabled( updatesEnabled );
 | 
|---|
| 5542 |     if ( topHeader )
 | 
|---|
| 5543 |         topHeader->setSortIndicator( col, ascending ? Qt::Ascending : Qt::Descending );
 | 
|---|
| 5544 | 
 | 
|---|
| 5545 |     if ( !wholeRows )
 | 
|---|
| 5546 |         repaintContents( columnPos( col ), contentsY(),
 | 
|---|
| 5547 |                          columnWidth( col ), visibleHeight(), FALSE );
 | 
|---|
| 5548 |     else
 | 
|---|
| 5549 |         repaintContents( contentsX(), contentsY(),
 | 
|---|
| 5550 |                          visibleWidth(), visibleHeight(), FALSE );
 | 
|---|
| 5551 | 
 | 
|---|
| 5552 |     delete [] items;
 | 
|---|
| 5553 | }
 | 
|---|
| 5554 | 
 | 
|---|
| 5555 | /*!
 | 
|---|
| 5556 |     Hides row \a row.
 | 
|---|
| 5557 | 
 | 
|---|
| 5558 |     \sa showRow() hideColumn()
 | 
|---|
| 5559 | */
 | 
|---|
| 5560 | 
 | 
|---|
| 5561 | void QTable::hideRow( int row )
 | 
|---|
| 5562 | {
 | 
|---|
| 5563 |     if ( d->hiddenRows.find( row ) )
 | 
|---|
| 5564 |         return;
 | 
|---|
| 5565 |     d->hiddenRows.replace( row, new int( leftHeader->sectionSize( row ) ) );
 | 
|---|
| 5566 |     leftHeader->resizeSection( row, 0 );
 | 
|---|
| 5567 |     leftHeader->setResizeEnabled( FALSE, row );
 | 
|---|
| 5568 |     if ( isRowStretchable(row) )
 | 
|---|
| 5569 |         leftHeader->numStretches--;
 | 
|---|
| 5570 |     rowHeightChanged( row );
 | 
|---|
| 5571 |     if ( curRow == row ) {
 | 
|---|
| 5572 |         int r = curRow;
 | 
|---|
| 5573 |         int c = curCol;
 | 
|---|
| 5574 |         int k = ( r >= numRows() - 1 ? Key_Up : Key_Down );
 | 
|---|
| 5575 |         fixCell( r, c, k );
 | 
|---|
| 5576 |         if ( numRows() > 0 )
 | 
|---|
| 5577 |             setCurrentCell( r, c );
 | 
|---|
| 5578 |     }
 | 
|---|
| 5579 | }
 | 
|---|
| 5580 | 
 | 
|---|
| 5581 | /*!
 | 
|---|
| 5582 |     Hides column \a col.
 | 
|---|
| 5583 | 
 | 
|---|
| 5584 |     \sa showColumn() hideRow()
 | 
|---|
| 5585 | */
 | 
|---|
| 5586 | 
 | 
|---|
| 5587 | void QTable::hideColumn( int col )
 | 
|---|
| 5588 | {
 | 
|---|
| 5589 |     if ( !numCols() || d->hiddenCols.find( col ) )
 | 
|---|
| 5590 |         return;
 | 
|---|
| 5591 |     d->hiddenCols.replace( col, new int( topHeader->sectionSize( col ) ) );
 | 
|---|
| 5592 |     topHeader->resizeSection( col, 0 );
 | 
|---|
| 5593 |     topHeader->setResizeEnabled( FALSE, col );
 | 
|---|
| 5594 |     if ( isColumnStretchable(col) )
 | 
|---|
| 5595 |         topHeader->numStretches--;
 | 
|---|
| 5596 |     columnWidthChanged( col );
 | 
|---|
| 5597 |     if ( curCol == col ) {
 | 
|---|
| 5598 |         int r = curRow;
 | 
|---|
| 5599 |         int c = curCol;
 | 
|---|
| 5600 |         int k = ( c >= numCols() - 1 ? Key_Left : Key_Right );
 | 
|---|
| 5601 |         fixCell( r, c, k );
 | 
|---|
| 5602 |         if ( numCols() > 0 )
 | 
|---|
| 5603 |             setCurrentCell( r, c );
 | 
|---|
| 5604 |     }
 | 
|---|
| 5605 | }
 | 
|---|
| 5606 | 
 | 
|---|
| 5607 | /*!
 | 
|---|
| 5608 |     Shows row \a row.
 | 
|---|
| 5609 | 
 | 
|---|
| 5610 |     \sa hideRow() showColumn()
 | 
|---|
| 5611 | */
 | 
|---|
| 5612 | 
 | 
|---|
| 5613 | void QTable::showRow( int row )
 | 
|---|
| 5614 | {
 | 
|---|
| 5615 |     int *h = d->hiddenRows.find( row );
 | 
|---|
| 5616 |     if ( h ) {
 | 
|---|
| 5617 |         int rh = *h;
 | 
|---|
| 5618 |         d->hiddenRows.remove( row );
 | 
|---|
| 5619 |         setRowHeight( row, rh );
 | 
|---|
| 5620 |         if ( isRowStretchable(row) )
 | 
|---|
| 5621 |             leftHeader->numStretches++;
 | 
|---|
| 5622 |     } else if ( rowHeight( row ) == 0 ) {
 | 
|---|
| 5623 |         setRowHeight( row, 20 );
 | 
|---|
| 5624 |     }
 | 
|---|
| 5625 |     leftHeader->setResizeEnabled( TRUE, row );
 | 
|---|
| 5626 | }
 | 
|---|
| 5627 | 
 | 
|---|
| 5628 | /*!
 | 
|---|
| 5629 |     Shows column \a col.
 | 
|---|
| 5630 | 
 | 
|---|
| 5631 |     \sa hideColumn() showRow()
 | 
|---|
| 5632 | */
 | 
|---|
| 5633 | 
 | 
|---|
| 5634 | void QTable::showColumn( int col )
 | 
|---|
| 5635 | {
 | 
|---|
| 5636 |     int *w = d->hiddenCols.find( col );
 | 
|---|
| 5637 |     if ( w ) {
 | 
|---|
| 5638 |         int cw = *w;
 | 
|---|
| 5639 |         d->hiddenCols.remove( col );
 | 
|---|
| 5640 |         setColumnWidth( col, cw );
 | 
|---|
| 5641 |         if ( isColumnStretchable( col ) )
 | 
|---|
| 5642 |             topHeader->numStretches++;
 | 
|---|
| 5643 |     } else if ( columnWidth( col ) == 0 ) {
 | 
|---|
| 5644 |         setColumnWidth( col, 20 );
 | 
|---|
| 5645 |     }
 | 
|---|
| 5646 |     topHeader->setResizeEnabled( TRUE, col );
 | 
|---|
| 5647 | }
 | 
|---|
| 5648 | 
 | 
|---|
| 5649 | /*!
 | 
|---|
| 5650 |     Returns TRUE if row \a row is hidden; otherwise returns
 | 
|---|
| 5651 |     FALSE.
 | 
|---|
| 5652 | 
 | 
|---|
| 5653 |     \sa hideRow(), isColumnHidden()
 | 
|---|
| 5654 | */
 | 
|---|
| 5655 | bool QTable::isRowHidden( int row ) const
 | 
|---|
| 5656 | {
 | 
|---|
| 5657 |     return d->hiddenRows.find( row );
 | 
|---|
| 5658 | }
 | 
|---|
| 5659 | 
 | 
|---|
| 5660 | /*!
 | 
|---|
| 5661 |     Returns TRUE if column \a col is hidden; otherwise returns
 | 
|---|
| 5662 |     FALSE.
 | 
|---|
| 5663 | 
 | 
|---|
| 5664 |     \sa hideColumn(), isRowHidden()
 | 
|---|
| 5665 | */
 | 
|---|
| 5666 | bool QTable::isColumnHidden( int col ) const
 | 
|---|
| 5667 | {
 | 
|---|
| 5668 |     return d->hiddenCols.find( col );
 | 
|---|
| 5669 | }
 | 
|---|
| 5670 | 
 | 
|---|
| 5671 | /*!
 | 
|---|
| 5672 |     Resizes column \a col to be \a w pixels wide.
 | 
|---|
| 5673 | 
 | 
|---|
| 5674 |     \sa columnWidth() setRowHeight()
 | 
|---|
| 5675 | */
 | 
|---|
| 5676 | 
 | 
|---|
| 5677 | void QTable::setColumnWidth( int col, int w )
 | 
|---|
| 5678 | {
 | 
|---|
| 5679 |     int *ow = d->hiddenCols.find( col );
 | 
|---|
| 5680 |     if ( ow ) {
 | 
|---|
| 5681 |         d->hiddenCols.replace( col, new int( w ) );
 | 
|---|
| 5682 |     } else {
 | 
|---|
| 5683 |         topHeader->resizeSection( col, w );
 | 
|---|
| 5684 |         columnWidthChanged( col );
 | 
|---|
| 5685 |     }
 | 
|---|
| 5686 | }
 | 
|---|
| 5687 | 
 | 
|---|
| 5688 | /*!
 | 
|---|
| 5689 |     Resizes row \a row to be \a h pixels high.
 | 
|---|
| 5690 | 
 | 
|---|
| 5691 |     \sa rowHeight() setColumnWidth()
 | 
|---|
| 5692 | */
 | 
|---|
| 5693 | 
 | 
|---|
| 5694 | void QTable::setRowHeight( int row, int h )
 | 
|---|
| 5695 | {
 | 
|---|
| 5696 |     int *oh = d->hiddenRows.find( row );
 | 
|---|
| 5697 |     if ( oh ) {
 | 
|---|
| 5698 |         d->hiddenRows.replace( row, new int( h ) );
 | 
|---|
| 5699 |     } else {
 | 
|---|
| 5700 |         leftHeader->resizeSection( row, h );
 | 
|---|
| 5701 |         rowHeightChanged( row );
 | 
|---|
| 5702 |     }
 | 
|---|
| 5703 | }
 | 
|---|
| 5704 | 
 | 
|---|
| 5705 | /*!
 | 
|---|
| 5706 |     Resizes column \a col so that the column width is wide enough to
 | 
|---|
| 5707 |     display the widest item the column contains.
 | 
|---|
| 5708 | 
 | 
|---|
| 5709 |     \sa adjustRow()
 | 
|---|
| 5710 | */
 | 
|---|
| 5711 | 
 | 
|---|
| 5712 | void QTable::adjustColumn( int col )
 | 
|---|
| 5713 | {
 | 
|---|
| 5714 |     int w = topHeader->sectionSizeHint( col, fontMetrics() ).width();
 | 
|---|
| 5715 |     if ( topHeader->iconSet( col ) )
 | 
|---|
| 5716 |         w += topHeader->iconSet( col )->pixmap().width();
 | 
|---|
| 5717 |     w = QMAX( w, 20 );
 | 
|---|
| 5718 |     for ( int i = 0; i < numRows(); ++i ) {
 | 
|---|
| 5719 |         QTableItem *itm = item( i, col );
 | 
|---|
| 5720 |         if ( !itm ) {
 | 
|---|
| 5721 |             QWidget *widget = cellWidget( i, col );
 | 
|---|
| 5722 |             if ( widget )
 | 
|---|
| 5723 |                 w = QMAX( w, widget->sizeHint().width() );
 | 
|---|
| 5724 |         } else {
 | 
|---|
| 5725 |             if ( itm->colSpan() > 1 )
 | 
|---|
| 5726 |                 w = QMAX( w, itm->sizeHint().width() / itm->colSpan() );
 | 
|---|
| 5727 |             else
 | 
|---|
| 5728 |                 w = QMAX( w, itm->sizeHint().width() );
 | 
|---|
| 5729 |         }
 | 
|---|
| 5730 |     }
 | 
|---|
| 5731 |     w = QMAX( w, QApplication::globalStrut().width() );
 | 
|---|
| 5732 |     setColumnWidth( col, w );
 | 
|---|
| 5733 | }
 | 
|---|
| 5734 | 
 | 
|---|
| 5735 | /*!
 | 
|---|
| 5736 |     Resizes row \a row so that the row height is tall enough to
 | 
|---|
| 5737 |     display the tallest item the row contains.
 | 
|---|
| 5738 | 
 | 
|---|
| 5739 |     \sa adjustColumn()
 | 
|---|
| 5740 | */
 | 
|---|
| 5741 | 
 | 
|---|
| 5742 | void QTable::adjustRow( int row )
 | 
|---|
| 5743 | {
 | 
|---|
| 5744 |     int h = 20;
 | 
|---|
| 5745 |     h = QMAX( h, leftHeader->sectionSizeHint( row, leftHeader->fontMetrics() ).height() );
 | 
|---|
| 5746 |     if ( leftHeader->iconSet( row ) )
 | 
|---|
| 5747 |         h = QMAX( h, leftHeader->iconSet( row )->pixmap().height() );
 | 
|---|
| 5748 |     for ( int i = 0; i < numCols(); ++i ) {
 | 
|---|
| 5749 |         QTableItem *itm = item( row, i );
 | 
|---|
| 5750 |         if ( !itm ) {
 | 
|---|
| 5751 |             QWidget *widget = cellWidget( row, i );
 | 
|---|
| 5752 |             if ( widget )
 | 
|---|
| 5753 |                 h = QMAX( h, widget->sizeHint().height() );
 | 
|---|
| 5754 |         } else {
 | 
|---|
| 5755 |             if ( itm->rowSpan() > 1 )
 | 
|---|
| 5756 |                 h = QMAX( h, itm->sizeHint().height() / itm->rowSpan() );
 | 
|---|
| 5757 |             else
 | 
|---|
| 5758 |                 h = QMAX( h, itm->sizeHint().height() );
 | 
|---|
| 5759 |         }
 | 
|---|
| 5760 |     }
 | 
|---|
| 5761 |     h = QMAX( h, QApplication::globalStrut().height() );
 | 
|---|
| 5762 |     setRowHeight( row, h );
 | 
|---|
| 5763 | }
 | 
|---|
| 5764 | 
 | 
|---|
| 5765 | /*!
 | 
|---|
| 5766 |     If \a stretch is TRUE, column \a col is set to be stretchable;
 | 
|---|
| 5767 |     otherwise column \a col is set to be unstretchable.
 | 
|---|
| 5768 | 
 | 
|---|
| 5769 |     If the table widget's width decreases or increases stretchable
 | 
|---|
| 5770 |     columns will grow narrower or wider to fit the space available as
 | 
|---|
| 5771 |     completely as possible. The user cannot manually resize stretchable
 | 
|---|
| 5772 |     columns.
 | 
|---|
| 5773 | 
 | 
|---|
| 5774 |     \sa isColumnStretchable() setRowStretchable() adjustColumn()
 | 
|---|
| 5775 | */
 | 
|---|
| 5776 | 
 | 
|---|
| 5777 | void QTable::setColumnStretchable( int col, bool stretch )
 | 
|---|
| 5778 | {
 | 
|---|
| 5779 |     topHeader->setSectionStretchable( col, stretch );
 | 
|---|
| 5780 | 
 | 
|---|
| 5781 |     if ( stretch && d->hiddenCols.find(col) )
 | 
|---|
| 5782 |         topHeader->numStretches--;
 | 
|---|
| 5783 | }
 | 
|---|
| 5784 | 
 | 
|---|
| 5785 | /*!
 | 
|---|
| 5786 |     If \a stretch is TRUE, row \a row is set to be stretchable;
 | 
|---|
| 5787 |     otherwise row \a row is set to be unstretchable.
 | 
|---|
| 5788 | 
 | 
|---|
| 5789 |     If the table widget's height decreases or increases stretchable
 | 
|---|
| 5790 |     rows will grow shorter or taller to fit the space available as
 | 
|---|
| 5791 |     completely as possible. The user cannot manually resize
 | 
|---|
| 5792 |     stretchable rows.
 | 
|---|
| 5793 | 
 | 
|---|
| 5794 |     \sa isRowStretchable() setColumnStretchable()
 | 
|---|
| 5795 | */
 | 
|---|
| 5796 | 
 | 
|---|
| 5797 | void QTable::setRowStretchable( int row, bool stretch )
 | 
|---|
| 5798 | {
 | 
|---|
| 5799 |     leftHeader->setSectionStretchable( row, stretch );
 | 
|---|
| 5800 | 
 | 
|---|
| 5801 |     if ( stretch && d->hiddenRows.find(row) )
 | 
|---|
| 5802 |         leftHeader->numStretches--;
 | 
|---|
| 5803 | }
 | 
|---|
| 5804 | 
 | 
|---|
| 5805 | /*!
 | 
|---|
| 5806 |     Returns TRUE if column \a col is stretchable; otherwise returns
 | 
|---|
| 5807 |     FALSE.
 | 
|---|
| 5808 | 
 | 
|---|
| 5809 |     \sa setColumnStretchable() isRowStretchable()
 | 
|---|
| 5810 | */
 | 
|---|
| 5811 | 
 | 
|---|
| 5812 | bool QTable::isColumnStretchable( int col ) const
 | 
|---|
| 5813 | {
 | 
|---|
| 5814 |     return topHeader->isSectionStretchable( col );
 | 
|---|
| 5815 | }
 | 
|---|
| 5816 | 
 | 
|---|
| 5817 | /*!
 | 
|---|
| 5818 |     Returns TRUE if row \a row is stretchable; otherwise returns
 | 
|---|
| 5819 |     FALSE.
 | 
|---|
| 5820 | 
 | 
|---|
| 5821 |     \sa setRowStretchable() isColumnStretchable()
 | 
|---|
| 5822 | */
 | 
|---|
| 5823 | 
 | 
|---|
| 5824 | bool QTable::isRowStretchable( int row ) const
 | 
|---|
| 5825 | {
 | 
|---|
| 5826 |     return leftHeader->isSectionStretchable( row );
 | 
|---|
| 5827 | }
 | 
|---|
| 5828 | 
 | 
|---|
| 5829 | /*!
 | 
|---|
| 5830 |     Takes the table item \a i out of the table. This function does \e
 | 
|---|
| 5831 |     not delete the table item. You must either delete the table item
 | 
|---|
| 5832 |     yourself or put it into a table (using setItem()) which will then
 | 
|---|
| 5833 |     take ownership of it.
 | 
|---|
| 5834 | 
 | 
|---|
| 5835 |     Use this function if you want to move an item from one cell in a
 | 
|---|
| 5836 |     table to another, or to move an item from one table to another,
 | 
|---|
| 5837 |     reinserting the item with setItem().
 | 
|---|
| 5838 | 
 | 
|---|
| 5839 |     If you want to exchange two cells use swapCells().
 | 
|---|
| 5840 | */
 | 
|---|
| 5841 | 
 | 
|---|
| 5842 | void QTable::takeItem( QTableItem *i )
 | 
|---|
| 5843 | {
 | 
|---|
| 5844 |     if ( !i )
 | 
|---|
| 5845 |         return;
 | 
|---|
| 5846 |     QRect rect = cellGeometry( i->row(), i->col() );
 | 
|---|
| 5847 |     contents.setAutoDelete( FALSE );
 | 
|---|
| 5848 |     int bottom = i->row() + i->rowSpan();
 | 
|---|
| 5849 |     if ( bottom > numRows() )
 | 
|---|
| 5850 |         bottom = numRows();
 | 
|---|
| 5851 |     int right = i->col() + i->colSpan();
 | 
|---|
| 5852 |     if ( right > numCols() )
 | 
|---|
| 5853 |         right = numCols();
 | 
|---|
| 5854 |     for ( int r = i->row(); r < bottom; ++r ) {
 | 
|---|
| 5855 |         for ( int c = i->col(); c < right; ++c )
 | 
|---|
| 5856 |             contents.remove( indexOf( r, c ) );
 | 
|---|
| 5857 |     }
 | 
|---|
| 5858 |     contents.setAutoDelete( TRUE );
 | 
|---|
| 5859 |     repaintContents( rect, FALSE );
 | 
|---|
| 5860 |     int orow = i->row();
 | 
|---|
| 5861 |     int ocol = i->col();
 | 
|---|
| 5862 |     i->setRow( -1 );
 | 
|---|
| 5863 |     i->setCol( -1 );
 | 
|---|
| 5864 |     i->updateEditor( orow, ocol );
 | 
|---|
| 5865 |     i->t = 0;
 | 
|---|
| 5866 | }
 | 
|---|
| 5867 | 
 | 
|---|
| 5868 | /*!
 | 
|---|
| 5869 |     Sets the widget \a e to the cell at \a row, \a col and takes care of
 | 
|---|
| 5870 |     placing and resizing the widget when the cell geometry changes.
 | 
|---|
| 5871 | 
 | 
|---|
| 5872 |     By default widgets are inserted into a vector with numRows() *
 | 
|---|
| 5873 |     numCols() elements. In very large tables you will probably want to
 | 
|---|
| 5874 |     store the widgets in a data structure that consumes less memory (see
 | 
|---|
| 5875 |     the notes on large tables). To support the use of your own data
 | 
|---|
| 5876 |     structure this function calls insertWidget() to add the widget to
 | 
|---|
| 5877 |     the internal data structure. To use your own data structure
 | 
|---|
| 5878 |     reimplement insertWidget(), cellWidget() and clearCellWidget().
 | 
|---|
| 5879 | 
 | 
|---|
| 5880 |     Cell widgets are created dynamically with the \c new operator. The
 | 
|---|
| 5881 |     cell widgets are destroyed automatically once the table is
 | 
|---|
| 5882 |     destroyed; the table takes ownership of the widget when using
 | 
|---|
| 5883 |     setCellWidget.
 | 
|---|
| 5884 | 
 | 
|---|
| 5885 | */
 | 
|---|
| 5886 | 
 | 
|---|
| 5887 | void QTable::setCellWidget( int row, int col, QWidget *e )
 | 
|---|
| 5888 | {
 | 
|---|
| 5889 |     if ( !e || row >= numRows() || col >= numCols() )
 | 
|---|
| 5890 |         return;
 | 
|---|
| 5891 | 
 | 
|---|
| 5892 |     QWidget *w = cellWidget( row, col );
 | 
|---|
| 5893 |     if ( w && row == editRow && col == editCol )
 | 
|---|
| 5894 |         endEdit( editRow, editCol, FALSE, edMode != Editing );
 | 
|---|
| 5895 | 
 | 
|---|
| 5896 |     e->installEventFilter( this );
 | 
|---|
| 5897 |     clearCellWidget( row, col );
 | 
|---|
| 5898 |     if ( e->parent() != viewport() )
 | 
|---|
| 5899 |         e->reparent( viewport(), QPoint( 0,0 ) );
 | 
|---|
| 5900 |     insertWidget( row, col, e );
 | 
|---|
| 5901 |     QRect cr = cellGeometry( row, col );
 | 
|---|
| 5902 |     e->resize( cr.size() );
 | 
|---|
| 5903 |     moveChild( e, cr.x(), cr.y() );
 | 
|---|
| 5904 |     e->show();
 | 
|---|
| 5905 | }
 | 
|---|
| 5906 | 
 | 
|---|
| 5907 | /*!
 | 
|---|
| 5908 |     Inserts widget \a w at \a row, \a col into the internal
 | 
|---|
| 5909 |     data structure. See the documentation of setCellWidget() for
 | 
|---|
| 5910 |     further details.
 | 
|---|
| 5911 | 
 | 
|---|
| 5912 |     If you don't use \l{QTableItem}s you may need to reimplement this
 | 
|---|
| 5913 |     function: see the notes on large tables.
 | 
|---|
| 5914 | */
 | 
|---|
| 5915 | 
 | 
|---|
| 5916 | void QTable::insertWidget( int row, int col, QWidget *w )
 | 
|---|
| 5917 | {
 | 
|---|
| 5918 |     if ( row < 0 || col < 0 || row > numRows() - 1 || col > numCols() - 1 )
 | 
|---|
| 5919 |         return;
 | 
|---|
| 5920 | 
 | 
|---|
| 5921 |     if ( (int)widgets.size() != numRows() * numCols() )
 | 
|---|
| 5922 |         widgets.resize( numRows() * numCols() );
 | 
|---|
| 5923 | 
 | 
|---|
| 5924 |     widgets.insert( indexOf( row, col ), w );
 | 
|---|
| 5925 | }
 | 
|---|
| 5926 | 
 | 
|---|
| 5927 | /*!
 | 
|---|
| 5928 |     Returns the widget that has been set for the cell at \a row, \a
 | 
|---|
| 5929 |     col, or 0 if no widget has been set.
 | 
|---|
| 5930 | 
 | 
|---|
| 5931 |     If you don't use \l{QTableItem}s you may need to reimplement this
 | 
|---|
| 5932 |     function: see the notes on large tables.
 | 
|---|
| 5933 | 
 | 
|---|
| 5934 |     \sa clearCellWidget() setCellWidget()
 | 
|---|
| 5935 | */
 | 
|---|
| 5936 | 
 | 
|---|
| 5937 | QWidget *QTable::cellWidget( int row, int col ) const
 | 
|---|
| 5938 | {
 | 
|---|
| 5939 |     if ( row < 0 || col < 0 || row > numRows() - 1 || col > numCols() - 1 )
 | 
|---|
| 5940 |         return 0;
 | 
|---|
| 5941 | 
 | 
|---|
| 5942 |     if ( (int)widgets.size() != numRows() * numCols() )
 | 
|---|
| 5943 |         ( (QTable*)this )->widgets.resize( numRows() * numCols() );
 | 
|---|
| 5944 | 
 | 
|---|
| 5945 |     return widgets[ indexOf( row, col ) ];
 | 
|---|
| 5946 | }
 | 
|---|
| 5947 | 
 | 
|---|
| 5948 | /*!
 | 
|---|
| 5949 |     Removes the widget (if there is one) set for the cell at \a row,
 | 
|---|
| 5950 |     \a col.
 | 
|---|
| 5951 | 
 | 
|---|
| 5952 |     If you don't use \l{QTableItem}s you may need to reimplement this
 | 
|---|
| 5953 |     function: see the notes on large tables.
 | 
|---|
| 5954 | 
 | 
|---|
| 5955 |     This function deletes the widget at \a row, \a col. Note that the
 | 
|---|
| 5956 |     widget is not deleted immediately; instead QObject::deleteLater()
 | 
|---|
| 5957 |     is called on the widget to avoid problems with timing issues.
 | 
|---|
| 5958 | 
 | 
|---|
| 5959 |     \sa cellWidget() setCellWidget()
 | 
|---|
| 5960 | */
 | 
|---|
| 5961 | 
 | 
|---|
| 5962 | void QTable::clearCellWidget( int row, int col )
 | 
|---|
| 5963 | {
 | 
|---|
| 5964 |     if ( row < 0 || col < 0 || row > numRows() - 1 || col > numCols() - 1 )
 | 
|---|
| 5965 |         return;
 | 
|---|
| 5966 | 
 | 
|---|
| 5967 |     if ( (int)widgets.size() != numRows() * numCols() )
 | 
|---|
| 5968 |         widgets.resize( numRows() * numCols() );
 | 
|---|
| 5969 | 
 | 
|---|
| 5970 |     QWidget *w = cellWidget( row, col );
 | 
|---|
| 5971 |     if ( w ) {
 | 
|---|
| 5972 |         w->removeEventFilter( this );
 | 
|---|
| 5973 |         w->deleteLater();
 | 
|---|
| 5974 |     }
 | 
|---|
| 5975 |     widgets.setAutoDelete( FALSE );
 | 
|---|
| 5976 |     widgets.remove( indexOf( row, col ) );
 | 
|---|
| 5977 |     widgets.setAutoDelete( TRUE );
 | 
|---|
| 5978 | }
 | 
|---|
| 5979 | 
 | 
|---|
| 5980 | /*!
 | 
|---|
| 5981 |     \fn void QTable::dropped ( QDropEvent * e )
 | 
|---|
| 5982 | 
 | 
|---|
| 5983 |     This signal is emitted when a drop event occurred on the table.
 | 
|---|
| 5984 | 
 | 
|---|
| 5985 |     \a e contains information about the drop.
 | 
|---|
| 5986 | */
 | 
|---|
| 5987 | 
 | 
|---|
| 5988 | /*!
 | 
|---|
| 5989 |     If \a b is TRUE, the table starts a drag (see dragObject()) when
 | 
|---|
| 5990 |     the user presses and moves the mouse on a selected cell.
 | 
|---|
| 5991 | */
 | 
|---|
| 5992 | 
 | 
|---|
| 5993 | void QTable::setDragEnabled( bool b )
 | 
|---|
| 5994 | {
 | 
|---|
| 5995 |     dEnabled = b;
 | 
|---|
| 5996 | }
 | 
|---|
| 5997 | 
 | 
|---|
| 5998 | /*!
 | 
|---|
| 5999 |     If this function returns TRUE, the table supports dragging.
 | 
|---|
| 6000 | 
 | 
|---|
| 6001 |     \sa setDragEnabled();
 | 
|---|
| 6002 | */
 | 
|---|
| 6003 | 
 | 
|---|
| 6004 | bool QTable::dragEnabled() const
 | 
|---|
| 6005 | {
 | 
|---|
| 6006 |     return dEnabled;
 | 
|---|
| 6007 | }
 | 
|---|
| 6008 | 
 | 
|---|
| 6009 | /*!
 | 
|---|
| 6010 |     Inserts \a count empty rows at row \a row. Also clears the selection(s).
 | 
|---|
| 6011 | 
 | 
|---|
| 6012 |     \sa insertColumns() removeRow()
 | 
|---|
| 6013 | */
 | 
|---|
| 6014 | 
 | 
|---|
| 6015 | void QTable::insertRows( int row, int count )
 | 
|---|
| 6016 | {
 | 
|---|
| 6017 |     // special case, so a call like insertRow( currentRow(), 1 ) also
 | 
|---|
| 6018 |     // works, when we have 0 rows and currentRow() is -1
 | 
|---|
| 6019 |     if ( row == -1 && curRow == -1 )
 | 
|---|
| 6020 |         row = 0;
 | 
|---|
| 6021 |     if ( row < 0 || count <= 0 )
 | 
|---|
| 6022 |         return;
 | 
|---|
| 6023 | 
 | 
|---|
| 6024 |     if ( curRow >= row && curRow < row + count )
 | 
|---|
| 6025 |         curRow = row + count;
 | 
|---|
| 6026 | 
 | 
|---|
| 6027 |     --row;
 | 
|---|
| 6028 |     if ( row >= numRows() )
 | 
|---|
| 6029 |         return;
 | 
|---|
| 6030 | 
 | 
|---|
| 6031 |     bool updatesEnabled = isUpdatesEnabled();
 | 
|---|
| 6032 |     setUpdatesEnabled( FALSE );
 | 
|---|
| 6033 |     bool leftHeaderUpdatesEnabled = leftHeader->isUpdatesEnabled();
 | 
|---|
| 6034 |     leftHeader->setUpdatesEnabled( FALSE );
 | 
|---|
| 6035 |     int oldLeftMargin = leftMargin();
 | 
|---|
| 6036 | 
 | 
|---|
| 6037 |     setNumRows( numRows() + count );
 | 
|---|
| 6038 | 
 | 
|---|
| 6039 |     for ( int i = numRows() - count - 1; i > row; --i )
 | 
|---|
| 6040 |         leftHeader->swapSections( i, i + count );
 | 
|---|
| 6041 | 
 | 
|---|
| 6042 |     leftHeader->setUpdatesEnabled( leftHeaderUpdatesEnabled );
 | 
|---|
| 6043 |     setUpdatesEnabled( updatesEnabled );
 | 
|---|
| 6044 | 
 | 
|---|
| 6045 |     int cr = QMAX( 0, currentRow() );
 | 
|---|
| 6046 |     int cc = QMAX( 0, currentColumn() );
 | 
|---|
| 6047 |     if ( curRow > row )
 | 
|---|
| 6048 |         curRow -= count; // this is where curRow was
 | 
|---|
| 6049 |     setCurrentCell( cr, cc, TRUE, FALSE ); // without ensureCellVisible
 | 
|---|
| 6050 | 
 | 
|---|
| 6051 |     // Repaint the header
 | 
|---|
| 6052 |     if ( leftHeaderUpdatesEnabled ) {
 | 
|---|
| 6053 |         int y = rowPos( row ) - contentsY();
 | 
|---|
| 6054 |         if ( leftMargin() != oldLeftMargin || d->hasRowSpan )
 | 
|---|
| 6055 |             y = 0; // full repaint
 | 
|---|
| 6056 |         QRect rect( 0, y, leftHeader->width(), contentsHeight() );
 | 
|---|
| 6057 |         leftHeader->update( rect );
 | 
|---|
| 6058 |     }
 | 
|---|
| 6059 | 
 | 
|---|
| 6060 |     if ( updatesEnabled ) {
 | 
|---|
| 6061 |         int p = rowPos( row );
 | 
|---|
| 6062 |         if ( d->hasRowSpan )
 | 
|---|
| 6063 |             p = contentsY();
 | 
|---|
| 6064 |         updateContents( contentsX(), p, visibleWidth(), contentsHeight() + 1 );
 | 
|---|
| 6065 |     }
 | 
|---|
| 6066 | }
 | 
|---|
| 6067 | 
 | 
|---|
| 6068 | /*!
 | 
|---|
| 6069 |     Inserts \a count empty columns at column \a col.  Also clears the selection(s).
 | 
|---|
| 6070 | 
 | 
|---|
| 6071 |     \sa insertRows() removeColumn()
 | 
|---|
| 6072 | */
 | 
|---|
| 6073 | 
 | 
|---|
| 6074 | void QTable::insertColumns( int col, int count )
 | 
|---|
| 6075 | {
 | 
|---|
| 6076 |     // see comment in insertRows()
 | 
|---|
| 6077 |     if ( col == -1 && curCol == -1 )
 | 
|---|
| 6078 |         col = 0;
 | 
|---|
| 6079 |     if ( col < 0 || count <= 0 )
 | 
|---|
| 6080 |         return;
 | 
|---|
| 6081 | 
 | 
|---|
| 6082 |     if ( curCol >= col && curCol < col + count )
 | 
|---|
| 6083 |         curCol = col + count;
 | 
|---|
| 6084 | 
 | 
|---|
| 6085 |     --col;
 | 
|---|
| 6086 |     if ( col >= numCols() )
 | 
|---|
| 6087 |         return;
 | 
|---|
| 6088 | 
 | 
|---|
| 6089 |     bool updatesEnabled = isUpdatesEnabled();
 | 
|---|
| 6090 |     setUpdatesEnabled( FALSE );
 | 
|---|
| 6091 |     bool topHeaderUpdatesEnabled = topHeader->isUpdatesEnabled();
 | 
|---|
| 6092 |     topHeader->setUpdatesEnabled( FALSE );
 | 
|---|
| 6093 |     int oldTopMargin = topMargin();
 | 
|---|
| 6094 | 
 | 
|---|
| 6095 |     setNumCols( numCols() + count );
 | 
|---|
| 6096 | 
 | 
|---|
| 6097 |     for ( int i = numCols() - count - 1; i > col; --i )
 | 
|---|
| 6098 |         topHeader->swapSections( i, i + count );
 | 
|---|
| 6099 | 
 | 
|---|
| 6100 |     topHeader->setUpdatesEnabled( topHeaderUpdatesEnabled );
 | 
|---|
| 6101 |     setUpdatesEnabled( updatesEnabled );
 | 
|---|
| 6102 | 
 | 
|---|
| 6103 |     int cr = QMAX( 0, currentRow() );
 | 
|---|
| 6104 |     int cc = QMAX( 0, currentColumn() );
 | 
|---|
| 6105 |     if ( curCol > col )
 | 
|---|
| 6106 |         curCol -= count; // this is where curCol was
 | 
|---|
| 6107 |     setCurrentCell( cr, cc, TRUE, FALSE ); // without ensureCellVisible
 | 
|---|
| 6108 | 
 | 
|---|
| 6109 |     // Repaint the header
 | 
|---|
| 6110 |     if ( topHeaderUpdatesEnabled ) {
 | 
|---|
| 6111 |         int x = columnPos( col ) - contentsX();
 | 
|---|
| 6112 |         if ( topMargin() != oldTopMargin || d->hasColSpan )
 | 
|---|
| 6113 |             x = 0; // full repaint
 | 
|---|
| 6114 |         QRect rect( x, 0, contentsWidth(), topHeader->height() );
 | 
|---|
| 6115 |         topHeader->update( rect );
 | 
|---|
| 6116 |     }
 | 
|---|
| 6117 | 
 | 
|---|
| 6118 |     if ( updatesEnabled ) {
 | 
|---|
| 6119 |         int p = columnPos( col );
 | 
|---|
| 6120 |         if ( d->hasColSpan )
 | 
|---|
| 6121 |             p = contentsX();
 | 
|---|
| 6122 |         updateContents( p, contentsY(), contentsWidth() + 1, visibleHeight() );
 | 
|---|
| 6123 |     }
 | 
|---|
| 6124 | }
 | 
|---|
| 6125 | 
 | 
|---|
| 6126 | /*!
 | 
|---|
| 6127 |     Removes row \a row, and deletes all its cells including any table
 | 
|---|
| 6128 |     items and widgets the cells may contain. Also clears the selection(s).
 | 
|---|
| 6129 | 
 | 
|---|
| 6130 |     \sa hideRow() insertRows() removeColumn() removeRows()
 | 
|---|
| 6131 | */
 | 
|---|
| 6132 | 
 | 
|---|
| 6133 | void QTable::removeRow( int row )
 | 
|---|
| 6134 | {
 | 
|---|
| 6135 |     if ( row < 0 || row >= numRows() )
 | 
|---|
| 6136 |         return;
 | 
|---|
| 6137 |     if ( row < numRows() - 1 ) {
 | 
|---|
| 6138 |         if (d->hiddenRows.find(row))
 | 
|---|
| 6139 |             d->hiddenRows.remove(row);
 | 
|---|
| 6140 | 
 | 
|---|
| 6141 |         for ( int i = row; i < numRows() - 1; ++i )
 | 
|---|
| 6142 |             ( (QTableHeader*)verticalHeader() )->swapSections( i, i + 1 );
 | 
|---|
| 6143 |     }
 | 
|---|
| 6144 |     setNumRows( numRows() - 1 );
 | 
|---|
| 6145 | }
 | 
|---|
| 6146 | 
 | 
|---|
| 6147 | /*!
 | 
|---|
| 6148 |     Removes the rows listed in the array \a rows, and deletes all their
 | 
|---|
| 6149 |     cells including any table items and widgets the cells may contain.
 | 
|---|
| 6150 | 
 | 
|---|
| 6151 |     The array passed in must only contain valid rows (in the range
 | 
|---|
| 6152 |     from 0 to numRows() - 1) with no duplicates, and must be sorted in
 | 
|---|
| 6153 |     ascending order. Also clears the selection(s).
 | 
|---|
| 6154 | 
 | 
|---|
| 6155 |     \sa removeRow() insertRows() removeColumns()
 | 
|---|
| 6156 | */
 | 
|---|
| 6157 | 
 | 
|---|
| 6158 | void QTable::removeRows( const QMemArray<int> &rows )
 | 
|---|
| 6159 | {
 | 
|---|
| 6160 |     if ( rows.count() == 0 )
 | 
|---|
| 6161 |         return;
 | 
|---|
| 6162 |     int i;
 | 
|---|
| 6163 |     for ( i = 0; i < (int)rows.count() - 1; ++i ) {
 | 
|---|
| 6164 |         for ( int j = rows[i] - i; j < rows[i + 1] - i - 1; j++ ) {
 | 
|---|
| 6165 |             ( (QTableHeader*)verticalHeader() )->swapSections( j, j + i + 1 );
 | 
|---|
| 6166 |         }
 | 
|---|
| 6167 |     }
 | 
|---|
| 6168 | 
 | 
|---|
| 6169 |     for ( int j = rows[i] - i; j < numRows() - (int)rows.size(); j++)
 | 
|---|
| 6170 |         ( (QTableHeader*)verticalHeader() )->swapSections( j, j + rows.count() );
 | 
|---|
| 6171 | 
 | 
|---|
| 6172 |     setNumRows( numRows() - rows.count() );
 | 
|---|
| 6173 | }
 | 
|---|
| 6174 | 
 | 
|---|
| 6175 | /*!
 | 
|---|
| 6176 |     Removes column \a col, and deletes all its cells including any
 | 
|---|
| 6177 |     table items and widgets the cells may contain. Also clears the
 | 
|---|
| 6178 |     selection(s).
 | 
|---|
| 6179 | 
 | 
|---|
| 6180 |     \sa removeColumns() hideColumn() insertColumns() removeRow()
 | 
|---|
| 6181 | */
 | 
|---|
| 6182 | 
 | 
|---|
| 6183 | void QTable::removeColumn( int col )
 | 
|---|
| 6184 | {
 | 
|---|
| 6185 |     if ( col < 0 || col >= numCols() )
 | 
|---|
| 6186 |         return;
 | 
|---|
| 6187 |     if ( col < numCols() - 1 ) {
 | 
|---|
| 6188 |         if (d->hiddenCols.find(col))
 | 
|---|
| 6189 |             d->hiddenCols.remove(col);
 | 
|---|
| 6190 | 
 | 
|---|
| 6191 |         for ( int i = col; i < numCols() - 1; ++i )
 | 
|---|
| 6192 |             ( (QTableHeader*)horizontalHeader() )->swapSections( i, i + 1 );
 | 
|---|
| 6193 |     }
 | 
|---|
| 6194 |     setNumCols( numCols() - 1 );
 | 
|---|
| 6195 | }
 | 
|---|
| 6196 | 
 | 
|---|
| 6197 | /*!
 | 
|---|
| 6198 |     Removes the columns listed in the array \a cols, and deletes all
 | 
|---|
| 6199 |     their cells including any table items and widgets the cells may
 | 
|---|
| 6200 |     contain.
 | 
|---|
| 6201 | 
 | 
|---|
| 6202 |     The array passed in must only contain valid columns (in the range
 | 
|---|
| 6203 |     from 0 to numCols() - 1) with no duplicates, and must be sorted in
 | 
|---|
| 6204 |     ascending order. Also clears the selection(s).
 | 
|---|
| 6205 | 
 | 
|---|
| 6206 |    \sa removeColumn() insertColumns() removeRows()
 | 
|---|
| 6207 | */
 | 
|---|
| 6208 | 
 | 
|---|
| 6209 | void QTable::removeColumns( const QMemArray<int> &cols )
 | 
|---|
| 6210 | {
 | 
|---|
| 6211 |     if ( cols.count() == 0 )
 | 
|---|
| 6212 |         return;
 | 
|---|
| 6213 |     int i;
 | 
|---|
| 6214 |     for ( i = 0; i < (int)cols.count() - 1; ++i ) {
 | 
|---|
| 6215 |         for ( int j = cols[i] - i; j < cols[i + 1] - i - 1; j++ ) {
 | 
|---|
| 6216 |             ( (QTableHeader*)horizontalHeader() )->swapSections( j, j + i + 1 );
 | 
|---|
| 6217 |         }
 | 
|---|
| 6218 |     }
 | 
|---|
| 6219 | 
 | 
|---|
| 6220 |     for ( int j = cols[i] - i; j < numCols() - (int)cols.size(); j++)
 | 
|---|
| 6221 |         ( (QTableHeader*)horizontalHeader() )->swapSections( j, j + cols.count() );
 | 
|---|
| 6222 | 
 | 
|---|
| 6223 |     setNumCols( numCols() - cols.count() );
 | 
|---|
| 6224 | }
 | 
|---|
| 6225 | 
 | 
|---|
| 6226 | /*!
 | 
|---|
| 6227 |     Starts editing the cell at \a row, \a col.
 | 
|---|
| 6228 | 
 | 
|---|
| 6229 |     If \a replace is TRUE the content of this cell will be replaced by
 | 
|---|
| 6230 |     the content of the editor when editing is finished, i.e. the user
 | 
|---|
| 6231 |     will be entering new data; otherwise the current content of the
 | 
|---|
| 6232 |     cell (if any) will be modified in the editor.
 | 
|---|
| 6233 | 
 | 
|---|
| 6234 |     \sa beginEdit()
 | 
|---|
| 6235 | */
 | 
|---|
| 6236 | 
 | 
|---|
| 6237 | void QTable::editCell( int row, int col, bool replace )
 | 
|---|
| 6238 | {
 | 
|---|
| 6239 |     if ( row < 0 || col < 0 || row > numRows() - 1 || col > numCols() - 1 )
 | 
|---|
| 6240 |         return;
 | 
|---|
| 6241 | 
 | 
|---|
| 6242 |     if ( beginEdit( row, col, replace ) ) {
 | 
|---|
| 6243 |         edMode = Editing;
 | 
|---|
| 6244 |         editRow = row;
 | 
|---|
| 6245 |         editCol = col;
 | 
|---|
| 6246 |     }
 | 
|---|
| 6247 | }
 | 
|---|
| 6248 | 
 | 
|---|
| 6249 | #ifndef QT_NO_DRAGANDDROP
 | 
|---|
| 6250 | 
 | 
|---|
| 6251 | /*!
 | 
|---|
| 6252 |     This event handler is called whenever a QTable object receives a
 | 
|---|
| 6253 |     \l QDragEnterEvent \a e, i.e. when the user pressed the mouse
 | 
|---|
| 6254 |     button to drag something.
 | 
|---|
| 6255 | 
 | 
|---|
| 6256 |     The focus is moved to the cell where the QDragEnterEvent occurred.
 | 
|---|
| 6257 | */
 | 
|---|
| 6258 | 
 | 
|---|
| 6259 | void QTable::contentsDragEnterEvent( QDragEnterEvent *e )
 | 
|---|
| 6260 | {
 | 
|---|
| 6261 |     oldCurrentRow = curRow;
 | 
|---|
| 6262 |     oldCurrentCol = curCol;
 | 
|---|
| 6263 |     int tmpRow = rowAt( e->pos().y() );
 | 
|---|
| 6264 |     int tmpCol = columnAt( e->pos().x() );
 | 
|---|
| 6265 |     fixRow( tmpRow, e->pos().y() );
 | 
|---|
| 6266 |     fixCol( tmpCol, e->pos().x() );
 | 
|---|
| 6267 |     if (e->source() != (QObject*)cellWidget( currentRow(), currentColumn() ) )
 | 
|---|
| 6268 |         setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 6269 |     e->accept();
 | 
|---|
| 6270 | }
 | 
|---|
| 6271 | 
 | 
|---|
| 6272 | /*!
 | 
|---|
| 6273 |     This event handler is called whenever a QTable object receives a
 | 
|---|
| 6274 |     \l QDragMoveEvent \a e, i.e. when the user actually drags the
 | 
|---|
| 6275 |     mouse.
 | 
|---|
| 6276 | 
 | 
|---|
| 6277 |     The focus is moved to the cell where the QDragMoveEvent occurred.
 | 
|---|
| 6278 | */
 | 
|---|
| 6279 | 
 | 
|---|
| 6280 | void QTable::contentsDragMoveEvent( QDragMoveEvent *e )
 | 
|---|
| 6281 | {
 | 
|---|
| 6282 |     int tmpRow = rowAt( e->pos().y() );
 | 
|---|
| 6283 |     int tmpCol = columnAt( e->pos().x() );
 | 
|---|
| 6284 |     fixRow( tmpRow, e->pos().y() );
 | 
|---|
| 6285 |     fixCol( tmpCol, e->pos().x() );
 | 
|---|
| 6286 |     if (e->source() != (QObject*)cellWidget( currentRow(), currentColumn() ) )
 | 
|---|
| 6287 |         setCurrentCell( tmpRow, tmpCol, FALSE, TRUE );
 | 
|---|
| 6288 |     e->accept();
 | 
|---|
| 6289 | }
 | 
|---|
| 6290 | 
 | 
|---|
| 6291 | /*!
 | 
|---|
| 6292 |     This event handler is called when a drag activity leaves \e this
 | 
|---|
| 6293 |     QTable object with event \a e.
 | 
|---|
| 6294 | */
 | 
|---|
| 6295 | 
 | 
|---|
| 6296 | void QTable::contentsDragLeaveEvent( QDragLeaveEvent * )
 | 
|---|
| 6297 | {
 | 
|---|
| 6298 |     setCurrentCell( oldCurrentRow, oldCurrentCol, FALSE, TRUE );
 | 
|---|
| 6299 | }
 | 
|---|
| 6300 | 
 | 
|---|
| 6301 | /*!
 | 
|---|
| 6302 |     This event handler is called when the user ends a drag and drop by
 | 
|---|
| 6303 |     dropping something onto \e this QTable and thus triggers the drop
 | 
|---|
| 6304 |     event, \a e.
 | 
|---|
| 6305 | */
 | 
|---|
| 6306 | 
 | 
|---|
| 6307 | void QTable::contentsDropEvent( QDropEvent *e )
 | 
|---|
| 6308 | {
 | 
|---|
| 6309 |     setCurrentCell( oldCurrentRow, oldCurrentCol, FALSE, TRUE );
 | 
|---|
| 6310 |     emit dropped( e );
 | 
|---|
| 6311 | }
 | 
|---|
| 6312 | 
 | 
|---|
| 6313 | /*!
 | 
|---|
| 6314 |     If the user presses the mouse on a selected cell, starts moving
 | 
|---|
| 6315 |     (i.e. dragging), and dragEnabled() is TRUE, this function is
 | 
|---|
| 6316 |     called to obtain a drag object. A drag using this object begins
 | 
|---|
| 6317 |     immediately unless dragObject() returns 0.
 | 
|---|
| 6318 | 
 | 
|---|
| 6319 |     By default this function returns 0. You might reimplement it and
 | 
|---|
| 6320 |     create a QDragObject depending on the selected items.
 | 
|---|
| 6321 | 
 | 
|---|
| 6322 |     \sa dropped()
 | 
|---|
| 6323 | */
 | 
|---|
| 6324 | 
 | 
|---|
| 6325 | QDragObject *QTable::dragObject()
 | 
|---|
| 6326 | {
 | 
|---|
| 6327 |     return 0;
 | 
|---|
| 6328 | }
 | 
|---|
| 6329 | 
 | 
|---|
| 6330 | /*!
 | 
|---|
| 6331 |     Starts a drag.
 | 
|---|
| 6332 | 
 | 
|---|
| 6333 |     Usually you don't need to call or reimplement this function yourself.
 | 
|---|
| 6334 | 
 | 
|---|
| 6335 |     \sa dragObject();
 | 
|---|
| 6336 | */
 | 
|---|
| 6337 | 
 | 
|---|
| 6338 | void QTable::startDrag()
 | 
|---|
| 6339 | {
 | 
|---|
| 6340 |     if ( startDragRow == -1 || startDragCol == -1 )
 | 
|---|
| 6341 |         return;
 | 
|---|
| 6342 | 
 | 
|---|
| 6343 |     startDragRow = startDragCol = -1;
 | 
|---|
| 6344 | 
 | 
|---|
| 6345 |     QDragObject *drag = dragObject();
 | 
|---|
| 6346 |     if ( !drag )
 | 
|---|
| 6347 |         return;
 | 
|---|
| 6348 | 
 | 
|---|
| 6349 |     drag->drag();
 | 
|---|
| 6350 | }
 | 
|---|
| 6351 | 
 | 
|---|
| 6352 | #endif
 | 
|---|
| 6353 | 
 | 
|---|
| 6354 | /*! \reimp */
 | 
|---|
| 6355 | void QTable::windowActivationChange( bool oldActive )
 | 
|---|
| 6356 | {
 | 
|---|
| 6357 |     if ( oldActive && autoScrollTimer )
 | 
|---|
| 6358 |         autoScrollTimer->stop();
 | 
|---|
| 6359 | 
 | 
|---|
| 6360 |     if ( !isVisible() )
 | 
|---|
| 6361 |         return;
 | 
|---|
| 6362 | 
 | 
|---|
| 6363 |     if ( palette().active() != palette().inactive() )
 | 
|---|
| 6364 |         updateContents();
 | 
|---|
| 6365 | }
 | 
|---|
| 6366 | 
 | 
|---|
| 6367 | /*! \reimp */
 | 
|---|
| 6368 | void QTable::setEnabled( bool b )
 | 
|---|
| 6369 | {
 | 
|---|
| 6370 |     if ( !b ) {
 | 
|---|
| 6371 |         // editor will lose focus, causing a crash deep in setEnabled(),
 | 
|---|
| 6372 |         // so we'll end the edit early.
 | 
|---|
| 6373 |         endEdit( editRow, editCol, TRUE, edMode != Editing );
 | 
|---|
| 6374 |     }
 | 
|---|
| 6375 |     QScrollView::setEnabled(b);
 | 
|---|
| 6376 | }
 | 
|---|
| 6377 | 
 | 
|---|
| 6378 | 
 | 
|---|
| 6379 | /*
 | 
|---|
| 6380 |     \class QTableHeader
 | 
|---|
| 6381 |     \brief The QTableHeader class allows for creation and manipulation
 | 
|---|
| 6382 |     of table headers.
 | 
|---|
| 6383 | \if defined(commercial)
 | 
|---|
| 6384 |     It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
 | 
|---|
| 6385 | \endif
 | 
|---|
| 6386 | 
 | 
|---|
| 6387 |     \ingroup advanced
 | 
|---|
| 6388 |     \module table
 | 
|---|
| 6389 | 
 | 
|---|
| 6390 | 
 | 
|---|
| 6391 |    QTable uses this subclass of QHeader for its headers. QTable has a
 | 
|---|
| 6392 |    horizontalHeader() for displaying column labels, and a
 | 
|---|
| 6393 |    verticalHeader() for displaying row labels.
 | 
|---|
| 6394 | 
 | 
|---|
| 6395 | */
 | 
|---|
| 6396 | 
 | 
|---|
| 6397 | /*
 | 
|---|
| 6398 |     \enum QTableHeader::SectionState
 | 
|---|
| 6399 | 
 | 
|---|
| 6400 |     This enum type denotes the state of the header's text
 | 
|---|
| 6401 | 
 | 
|---|
| 6402 |     \value Normal the default
 | 
|---|
| 6403 |     \value Bold
 | 
|---|
| 6404 |     \value Selected  typically represented by showing the section "sunken"
 | 
|---|
| 6405 |     or "pressed in"
 | 
|---|
| 6406 | */
 | 
|---|
| 6407 | 
 | 
|---|
| 6408 | /*!
 | 
|---|
| 6409 |     Creates a new table header called \a name with \a i sections. It
 | 
|---|
| 6410 |     is a child of widget \a parent and attached to table \a t.
 | 
|---|
| 6411 | */
 | 
|---|
| 6412 | 
 | 
|---|
| 6413 | QTableHeader::QTableHeader( int i, QTable *t,
 | 
|---|
| 6414 |                             QWidget *parent, const char *name )
 | 
|---|
| 6415 |     : QHeader( i, parent, name ), mousePressed(FALSE), startPos(-1),
 | 
|---|
| 6416 |       table( t ), caching( FALSE ), resizedSection(-1),
 | 
|---|
| 6417 |       numStretches( 0 )
 | 
|---|
| 6418 | {
 | 
|---|
| 6419 |     setIsATableHeader( TRUE );
 | 
|---|
| 6420 |     d = 0;
 | 
|---|
| 6421 |     states.resize( i );
 | 
|---|
| 6422 |     stretchable.resize( i );
 | 
|---|
| 6423 |     states.fill( Normal, -1 );
 | 
|---|
| 6424 |     stretchable.fill( FALSE, -1 );
 | 
|---|
| 6425 |     autoScrollTimer = new QTimer( this );
 | 
|---|
| 6426 |     connect( autoScrollTimer, SIGNAL( timeout() ),
 | 
|---|
| 6427 |              this, SLOT( doAutoScroll() ) );
 | 
|---|
| 6428 | #ifndef NO_LINE_WIDGET
 | 
|---|
| 6429 |     line1 = new QWidget( table->viewport(), "qt_line1" );
 | 
|---|
| 6430 |     line1->hide();
 | 
|---|
| 6431 |     line1->setBackgroundMode( PaletteText );
 | 
|---|
| 6432 |     table->addChild( line1 );
 | 
|---|
| 6433 |     line2 = new QWidget( table->viewport(), "qt_line2" );
 | 
|---|
| 6434 |     line2->hide();
 | 
|---|
| 6435 |     line2->setBackgroundMode( PaletteText );
 | 
|---|
| 6436 |     table->addChild( line2 );
 | 
|---|
| 6437 | #else
 | 
|---|
| 6438 |     d = new QTableHeaderPrivate;
 | 
|---|
| 6439 |     d->oldLinePos = -1; //outside, in contents coords
 | 
|---|
| 6440 | #endif
 | 
|---|
| 6441 |     connect( this, SIGNAL( sizeChange(int,int,int) ),
 | 
|---|
| 6442 |              this, SLOT( sectionWidthChanged(int,int,int) ) );
 | 
|---|
| 6443 |     connect( this, SIGNAL( indexChange(int,int,int) ),
 | 
|---|
| 6444 |              this, SLOT( indexChanged(int,int,int) ) );
 | 
|---|
| 6445 | 
 | 
|---|
| 6446 |     stretchTimer = new QTimer( this );
 | 
|---|
| 6447 |     widgetStretchTimer = new QTimer( this );
 | 
|---|
| 6448 |     connect( stretchTimer, SIGNAL( timeout() ),
 | 
|---|
| 6449 |              this, SLOT( updateStretches() ) );
 | 
|---|
| 6450 |     connect( widgetStretchTimer, SIGNAL( timeout() ),
 | 
|---|
| 6451 |              this, SLOT( updateWidgetStretches() ) );
 | 
|---|
| 6452 |     startPos = -1;
 | 
|---|
| 6453 | }
 | 
|---|
| 6454 | 
 | 
|---|
| 6455 | /*!
 | 
|---|
| 6456 |     Adds a new section, \a size pixels wide (or high for vertical
 | 
|---|
| 6457 |     headers) with the label \a s. If \a size is negative the section's
 | 
|---|
| 6458 |     size is calculated based on the width (or height) of the label's
 | 
|---|
| 6459 |     text.
 | 
|---|
| 6460 | */
 | 
|---|
| 6461 | 
 | 
|---|
| 6462 | void QTableHeader::addLabel( const QString &s , int size )
 | 
|---|
| 6463 | {
 | 
|---|
| 6464 |     QHeader::addLabel( s, size );
 | 
|---|
| 6465 |     if ( count() > (int)states.size() ) {
 | 
|---|
| 6466 |         int s = states.size();
 | 
|---|
| 6467 |         states.resize( count() );
 | 
|---|
| 6468 |         stretchable.resize( count() );
 | 
|---|
| 6469 |         for ( ; s < count(); ++s ) {
 | 
|---|
| 6470 |             states[ s ] = Normal;
 | 
|---|
| 6471 |             stretchable[ s ] = FALSE;
 | 
|---|
| 6472 |         }
 | 
|---|
| 6473 |     }
 | 
|---|
| 6474 | }
 | 
|---|
| 6475 | 
 | 
|---|
| 6476 | void QTableHeader::removeLabel( int section )
 | 
|---|
| 6477 | {
 | 
|---|
| 6478 |     QHeader::removeLabel( section );
 | 
|---|
| 6479 |     if ( section == (int)states.size() - 1 ) {
 | 
|---|
| 6480 |         states.resize( states.size() - 1 );
 | 
|---|
| 6481 |         stretchable.resize( stretchable.size() - 1 );
 | 
|---|
| 6482 |     }
 | 
|---|
| 6483 | }
 | 
|---|
| 6484 | 
 | 
|---|
| 6485 | void QTableHeader::resizeArrays( int n )
 | 
|---|
| 6486 | {
 | 
|---|
| 6487 |     int old = states.size();
 | 
|---|
| 6488 |     states.resize( n );
 | 
|---|
| 6489 |     stretchable.resize( n );
 | 
|---|
| 6490 |     if ( n > old ) {
 | 
|---|
| 6491 |         for ( int i = old; i < n; ++i ) {
 | 
|---|
| 6492 |             stretchable[ i ] = FALSE;
 | 
|---|
| 6493 |             states[ i ] = Normal;
 | 
|---|
| 6494 |         }
 | 
|---|
| 6495 |     }
 | 
|---|
| 6496 | }
 | 
|---|
| 6497 | 
 | 
|---|
| 6498 | void QTableHeader::setLabel( int section, const QString & s, int size )
 | 
|---|
| 6499 | {
 | 
|---|
| 6500 |     QHeader::setLabel( section, s, size );
 | 
|---|
| 6501 |     sectionLabelChanged( section );
 | 
|---|
| 6502 | }
 | 
|---|
| 6503 | 
 | 
|---|
| 6504 | void QTableHeader::setLabel( int section, const QIconSet & iconset,
 | 
|---|
| 6505 |                              const QString & s, int size )
 | 
|---|
| 6506 | {
 | 
|---|
| 6507 |     QHeader::setLabel( section, iconset, s, size );
 | 
|---|
| 6508 |     sectionLabelChanged( section );
 | 
|---|
| 6509 | }
 | 
|---|
| 6510 | 
 | 
|---|
| 6511 | /*!
 | 
|---|
| 6512 |     Sets the SectionState of section \a s to \a astate.
 | 
|---|
| 6513 | 
 | 
|---|
| 6514 |     \sa sectionState()
 | 
|---|
| 6515 | */
 | 
|---|
| 6516 | 
 | 
|---|
| 6517 | void QTableHeader::setSectionState( int s, SectionState astate )
 | 
|---|
| 6518 | {
 | 
|---|
| 6519 |     if ( s < 0 || s >= (int)states.count() )
 | 
|---|
| 6520 |         return;
 | 
|---|
| 6521 |     if ( states.data()[ s ] == astate )
 | 
|---|
| 6522 |         return;
 | 
|---|
| 6523 |     if ( isRowSelection( table->selectionMode() ) && orientation() == Horizontal )
 | 
|---|
| 6524 |         return;
 | 
|---|
| 6525 | 
 | 
|---|
| 6526 |     states.data()[ s ] = astate;
 | 
|---|
| 6527 |     if ( isUpdatesEnabled() ) {
 | 
|---|
| 6528 |         if ( orientation() == Horizontal )
 | 
|---|
| 6529 |             repaint( sectionPos( s ) - offset(), 0, sectionSize( s ), height(), FALSE );
 | 
|---|
| 6530 |         else
 | 
|---|
| 6531 |             repaint( 0, sectionPos( s ) - offset(), width(), sectionSize( s ), FALSE );
 | 
|---|
| 6532 |     }
 | 
|---|
| 6533 | }
 | 
|---|
| 6534 | 
 | 
|---|
| 6535 | void QTableHeader::setSectionStateToAll( SectionState state )
 | 
|---|
| 6536 | {
 | 
|---|
| 6537 |     if ( isRowSelection( table->selectionMode() ) && orientation() == Horizontal )
 | 
|---|
| 6538 |         return;
 | 
|---|
| 6539 | 
 | 
|---|
| 6540 |     register int *d = (int *) states.data();
 | 
|---|
| 6541 |     int n = count();
 | 
|---|
| 6542 | 
 | 
|---|
| 6543 |     while (n >= 4) {
 | 
|---|
| 6544 |         d[0] = state;
 | 
|---|
| 6545 |         d[1] = state;
 | 
|---|
| 6546 |         d[2] = state;
 | 
|---|
| 6547 |         d[3] = state;
 | 
|---|
| 6548 |         d += 4;
 | 
|---|
| 6549 |         n -= 4;
 | 
|---|
| 6550 |     }
 | 
|---|
| 6551 | 
 | 
|---|
| 6552 |     if (n > 0) {
 | 
|---|
| 6553 |         d[0] = state;
 | 
|---|
| 6554 |         if (n > 1) {
 | 
|---|
| 6555 |             d[1] = state;
 | 
|---|
| 6556 |             if (n > 2) {
 | 
|---|
| 6557 |                 d[2] = state;
 | 
|---|
| 6558 |             }
 | 
|---|
| 6559 |         }
 | 
|---|
| 6560 |     }
 | 
|---|
| 6561 | }
 | 
|---|
| 6562 | 
 | 
|---|
| 6563 | /*!
 | 
|---|
| 6564 |     Returns the SectionState of section \a s.
 | 
|---|
| 6565 | 
 | 
|---|
| 6566 |     \sa setSectionState()
 | 
|---|
| 6567 | */
 | 
|---|
| 6568 | 
 | 
|---|
| 6569 | QTableHeader::SectionState QTableHeader::sectionState( int s ) const
 | 
|---|
| 6570 | {
 | 
|---|
| 6571 |     return (QTableHeader::SectionState)states[ s ];
 | 
|---|
| 6572 | }
 | 
|---|
| 6573 | 
 | 
|---|
| 6574 | /*! \reimp
 | 
|---|
| 6575 | */
 | 
|---|
| 6576 | 
 | 
|---|
| 6577 | void QTableHeader::paintEvent( QPaintEvent *e )
 | 
|---|
| 6578 | {
 | 
|---|
| 6579 |     QPainter p( this );
 | 
|---|
| 6580 |     p.setPen( colorGroup().buttonText() );
 | 
|---|
| 6581 |     int pos = orientation() == Horizontal
 | 
|---|
| 6582 |                      ? e->rect().left()
 | 
|---|
| 6583 |                      : e->rect().top();
 | 
|---|
| 6584 |     int id = mapToIndex( sectionAt( pos + offset() ) );
 | 
|---|
| 6585 |     if ( id < 0 ) {
 | 
|---|
| 6586 |         if ( pos > 0 )
 | 
|---|
| 6587 |             return;
 | 
|---|
| 6588 |         else
 | 
|---|
| 6589 |             id = 0;
 | 
|---|
| 6590 |     }
 | 
|---|
| 6591 | 
 | 
|---|
| 6592 |     QRegion reg = e->region();
 | 
|---|
| 6593 |     for ( int i = id; i < count(); i++ ) {
 | 
|---|
| 6594 |         QRect r = sRect( i );
 | 
|---|
| 6595 |         reg -= r;
 | 
|---|
| 6596 |         p.save();
 | 
|---|
| 6597 |         if ( !( orientation() == Horizontal && isRowSelection( table->selectionMode() ) ) &&
 | 
|---|
| 6598 |              ( sectionState( i ) == Bold || sectionState( i ) == Selected ) ) {
 | 
|---|
| 6599 |             QFont f( font() );
 | 
|---|
| 6600 |             f.setBold( TRUE );
 | 
|---|
| 6601 |             p.setFont( f );
 | 
|---|
| 6602 |         }
 | 
|---|
| 6603 |         paintSection( &p, i, r );
 | 
|---|
| 6604 |         p.restore();
 | 
|---|
| 6605 |         if ( orientation() == Horizontal && r. right() >= e->rect().right() ||
 | 
|---|
| 6606 |              orientation() == Vertical && r. bottom() >= e->rect().bottom() )
 | 
|---|
| 6607 |             return;
 | 
|---|
| 6608 |     }
 | 
|---|
| 6609 |     if ( !reg.isEmpty() )
 | 
|---|
| 6610 |         erase( reg );
 | 
|---|
| 6611 | }
 | 
|---|
| 6612 | 
 | 
|---|
| 6613 | /*!
 | 
|---|
| 6614 |     \reimp
 | 
|---|
| 6615 | 
 | 
|---|
| 6616 |     Paints the header section with index \a index into the rectangular
 | 
|---|
| 6617 |     region \a fr on the painter \a p.
 | 
|---|
| 6618 | */
 | 
|---|
| 6619 | 
 | 
|---|
| 6620 | void QTableHeader::paintSection( QPainter *p, int index, const QRect& fr )
 | 
|---|
| 6621 | {
 | 
|---|
| 6622 |     int section = mapToSection( index );
 | 
|---|
| 6623 |     if ( section < 0 || cellSize( section ) <= 0 )
 | 
|---|
| 6624 |         return;
 | 
|---|
| 6625 | 
 | 
|---|
| 6626 |    if ( sectionState( index ) != Selected ||
 | 
|---|
| 6627 |          orientation() == Horizontal && isRowSelection( table->selectionMode() ) ) {
 | 
|---|
| 6628 |         QHeader::paintSection( p, index, fr );
 | 
|---|
| 6629 |    } else {
 | 
|---|
| 6630 |        QStyle::SFlags flags = QStyle::Style_Off | ( orient == Horizontal ? QStyle::Style_Horizontal : 0 );
 | 
|---|
| 6631 |        if(isEnabled())
 | 
|---|
| 6632 |            flags |= QStyle::Style_Enabled;
 | 
|---|
| 6633 |        if(isClickEnabled()) {
 | 
|---|
| 6634 |            if(sectionState(index) == Selected) {
 | 
|---|
| 6635 |                flags |= QStyle::Style_Down;
 | 
|---|
| 6636 |                if(!mousePressed)
 | 
|---|
| 6637 |                    flags |= QStyle::Style_Sunken;
 | 
|---|
| 6638 |            }
 | 
|---|
| 6639 |        }
 | 
|---|
| 6640 |        if(!(flags & QStyle::Style_Down))
 | 
|---|
| 6641 |            flags |= QStyle::Style_Raised;
 | 
|---|
| 6642 |        style().drawPrimitive( QStyle::PE_HeaderSection, p, QRect(fr.x(), fr.y(), fr.width(), fr.height()),
 | 
|---|
| 6643 |                               colorGroup(), flags );
 | 
|---|
| 6644 |        paintSectionLabel( p, index, fr );
 | 
|---|
| 6645 |    }
 | 
|---|
| 6646 | }
 | 
|---|
| 6647 | 
 | 
|---|
| 6648 | static int real_pos( const QPoint &p, Qt::Orientation o )
 | 
|---|
| 6649 | {
 | 
|---|
| 6650 |     if ( o == Qt::Horizontal )
 | 
|---|
| 6651 |         return p.x();
 | 
|---|
| 6652 |     return p.y();
 | 
|---|
| 6653 | }
 | 
|---|
| 6654 | 
 | 
|---|
| 6655 | /*! \reimp
 | 
|---|
| 6656 | */
 | 
|---|
| 6657 | 
 | 
|---|
| 6658 | void QTableHeader::mousePressEvent( QMouseEvent *e )
 | 
|---|
| 6659 | {
 | 
|---|
| 6660 |     if ( e->button() != LeftButton )
 | 
|---|
| 6661 |         return;
 | 
|---|
| 6662 |     QHeader::mousePressEvent( e );
 | 
|---|
| 6663 |     mousePressed = TRUE;
 | 
|---|
| 6664 |     pressPos = real_pos( e->pos(), orientation() );
 | 
|---|
| 6665 |     if ( !table->currentSel || ( e->state() & ShiftButton ) != ShiftButton )
 | 
|---|
| 6666 |         startPos = -1;
 | 
|---|
| 6667 |     setCaching( TRUE );
 | 
|---|
| 6668 |     resizedSection = -1;
 | 
|---|
| 6669 | #ifdef QT_NO_CURSOR
 | 
|---|
| 6670 |     isResizing = FALSE;
 | 
|---|
| 6671 | #else
 | 
|---|
| 6672 |     isResizing = cursor().shape() != ArrowCursor;
 | 
|---|
| 6673 |     if ( !isResizing && sectionAt( pressPos ) != -1 )
 | 
|---|
| 6674 |         doSelection( e );
 | 
|---|
| 6675 | #endif
 | 
|---|
| 6676 | }
 | 
|---|
| 6677 | 
 | 
|---|
| 6678 | /*! \reimp
 | 
|---|
| 6679 | */
 | 
|---|
| 6680 | 
 | 
|---|
| 6681 | void QTableHeader::mouseMoveEvent( QMouseEvent *e )
 | 
|---|
| 6682 | {
 | 
|---|
| 6683 |     if ( (e->state() & MouseButtonMask) != LeftButton // Using LeftButton simulates old behavior.
 | 
|---|
| 6684 | #ifndef QT_NO_CURSOR
 | 
|---|
| 6685 |          || cursor().shape() != ArrowCursor
 | 
|---|
| 6686 | #endif
 | 
|---|
| 6687 |          || ( ( e->state() & ControlButton ) == ControlButton &&
 | 
|---|
| 6688 |               ( orientation() == Horizontal
 | 
|---|
| 6689 |              ? table->columnMovingEnabled() : table->rowMovingEnabled() ) ) ) {
 | 
|---|
| 6690 |         QHeader::mouseMoveEvent( e );
 | 
|---|
| 6691 |         return;
 | 
|---|
| 6692 |     }
 | 
|---|
| 6693 | 
 | 
|---|
| 6694 |     if ( !doSelection( e ) )
 | 
|---|
| 6695 |         QHeader::mouseMoveEvent( e );
 | 
|---|
| 6696 | }
 | 
|---|
| 6697 | 
 | 
|---|
| 6698 | bool QTableHeader::doSelection( QMouseEvent *e )
 | 
|---|
| 6699 | {
 | 
|---|
| 6700 |     int p = real_pos( e->pos(), orientation() ) + offset();
 | 
|---|
| 6701 | 
 | 
|---|
| 6702 |     if ( isRowSelection( table->selectionMode() ) ) {
 | 
|---|
| 6703 |         if ( orientation() == Horizontal )
 | 
|---|
| 6704 |             return TRUE;
 | 
|---|
| 6705 |         if ( table->selectionMode() == QTable::SingleRow ) {
 | 
|---|
| 6706 |             int secAt = sectionAt( p );
 | 
|---|
| 6707 |             if ( secAt == -1 )
 | 
|---|
| 6708 |                 return TRUE;
 | 
|---|
| 6709 |             table->setCurrentCell( secAt, table->currentColumn() );
 | 
|---|
| 6710 |             return TRUE;
 | 
|---|
| 6711 |         }
 | 
|---|
| 6712 |     }
 | 
|---|
| 6713 | 
 | 
|---|
| 6714 |     if ( startPos == -1 ) {
 | 
|---|
| 6715 |         int secAt = sectionAt( p );
 | 
|---|
| 6716 |         if ( ( e->state() & ControlButton ) != ControlButton &&
 | 
|---|
| 6717 |              ( e->state() & ShiftButton ) != ShiftButton ||
 | 
|---|
| 6718 |              table->selectionMode() == QTable::Single ||
 | 
|---|
| 6719 |              table->selectionMode() == QTable::SingleRow ) {
 | 
|---|
| 6720 |             startPos = p;
 | 
|---|
| 6721 |             bool b = table->signalsBlocked();
 | 
|---|
| 6722 |             table->blockSignals( TRUE );
 | 
|---|
| 6723 |             table->clearSelection();
 | 
|---|
| 6724 |             table->blockSignals( b );
 | 
|---|
| 6725 |         }
 | 
|---|
| 6726 |         saveStates();
 | 
|---|
| 6727 | 
 | 
|---|
| 6728 |         if ( table->selectionMode() != QTable::NoSelection ) {
 | 
|---|
| 6729 |             startPos = p;
 | 
|---|
| 6730 |             QTableSelection *oldSelection = table->currentSel;
 | 
|---|
| 6731 | 
 | 
|---|
| 6732 |             if ( orientation() == Vertical ) {
 | 
|---|
| 6733 |                 if ( !table->isRowSelected( secAt, TRUE ) ) {
 | 
|---|
| 6734 |                     table->currentSel = new QTableSelection();
 | 
|---|
| 6735 |                     table->selections.append( table->currentSel );
 | 
|---|
| 6736 |                     table->currentSel->init( secAt, 0 );
 | 
|---|
| 6737 |                     table->currentSel->expandTo( secAt, table->numCols() - 1 );
 | 
|---|
| 6738 |                 } else if ( table->currentSel ) {
 | 
|---|
| 6739 |                     table->currentSel->init( secAt, 0 );
 | 
|---|
| 6740 |                 }
 | 
|---|
| 6741 |                 table->setCurrentCell( secAt, 0 );
 | 
|---|
| 6742 |             } else { // orientation == Horizontal
 | 
|---|
| 6743 |                 if ( !table->isColumnSelected( secAt, TRUE ) ) {
 | 
|---|
| 6744 |                     table->currentSel = new QTableSelection();
 | 
|---|
| 6745 |                     table->selections.append( table->currentSel );
 | 
|---|
| 6746 |                     table->currentSel->init( 0, secAt );
 | 
|---|
| 6747 |                     table->currentSel->expandTo( table->numRows() - 1, secAt );
 | 
|---|
| 6748 |                 } else if ( table->currentSel ) {
 | 
|---|
| 6749 |                     table->currentSel->init( 0, secAt );
 | 
|---|
| 6750 |                 }
 | 
|---|
| 6751 |                 table->setCurrentCell( 0, secAt );
 | 
|---|
| 6752 |             }
 | 
|---|
| 6753 |             table->repaintSelections( oldSelection, table->currentSel,
 | 
|---|
| 6754 |                                       orientation() == Horizontal,
 | 
|---|
| 6755 |                                       orientation() == Vertical );
 | 
|---|
| 6756 |             if ( sectionAt( p ) != -1 )
 | 
|---|
| 6757 |                 endPos = p;
 | 
|---|
| 6758 |             return TRUE;
 | 
|---|
| 6759 |         }
 | 
|---|
| 6760 |     }
 | 
|---|
| 6761 |     if ( sectionAt( p ) != -1 )
 | 
|---|
| 6762 |         endPos = p;
 | 
|---|
| 6763 |     if ( startPos != -1 ) {
 | 
|---|
| 6764 |         updateSelections();
 | 
|---|
| 6765 |         p -= offset();
 | 
|---|
| 6766 |         if ( orientation() == Horizontal && ( p < 0 || p > width() ) ) {
 | 
|---|
| 6767 |             doAutoScroll();
 | 
|---|
| 6768 |             autoScrollTimer->start( 100, TRUE );
 | 
|---|
| 6769 |         } else if ( orientation() == Vertical && ( p < 0 || p > height() ) ) {
 | 
|---|
| 6770 |             doAutoScroll();
 | 
|---|
| 6771 |             autoScrollTimer->start( 100, TRUE );
 | 
|---|
| 6772 |         }
 | 
|---|
| 6773 |         return TRUE;
 | 
|---|
| 6774 |     }
 | 
|---|
| 6775 |     return table->selectionMode() == QTable::NoSelection;
 | 
|---|
| 6776 | }
 | 
|---|
| 6777 | 
 | 
|---|
| 6778 | static inline bool mayOverwriteMargin( int before, int after )
 | 
|---|
| 6779 | {
 | 
|---|
| 6780 |     /*
 | 
|---|
| 6781 |       0 is the only user value that we always respect. We also never
 | 
|---|
| 6782 |       shrink a margin, in case the user wanted it that way.
 | 
|---|
| 6783 |     */
 | 
|---|
| 6784 |     return before != 0 && before < after;
 | 
|---|
| 6785 | }
 | 
|---|
| 6786 | 
 | 
|---|
| 6787 | void QTableHeader::sectionLabelChanged( int section )
 | 
|---|
| 6788 | {
 | 
|---|
| 6789 |     emit sectionSizeChanged( section );
 | 
|---|
| 6790 | 
 | 
|---|
| 6791 |     // this does not really belong here
 | 
|---|
| 6792 |     if ( orientation() == Horizontal ) {
 | 
|---|
| 6793 |         int h = sizeHint().height();
 | 
|---|
| 6794 |         if ( h != height() && mayOverwriteMargin(table->topMargin(), h) )
 | 
|---|
| 6795 |             table->setTopMargin( h );
 | 
|---|
| 6796 |     } else {
 | 
|---|
| 6797 |         int w = sizeHint().width();
 | 
|---|
| 6798 |         if ( w != width() && mayOverwriteMargin( ( QApplication::reverseLayout() ? table->rightMargin() : table->leftMargin() ), w) )
 | 
|---|
| 6799 |             table->setLeftMargin( w );
 | 
|---|
| 6800 |     }
 | 
|---|
| 6801 | }
 | 
|---|
| 6802 | 
 | 
|---|
| 6803 | /*! \reimp */
 | 
|---|
| 6804 | void QTableHeader::mouseReleaseEvent( QMouseEvent *e )
 | 
|---|
| 6805 | {
 | 
|---|
| 6806 |     if ( e->button() != LeftButton )
 | 
|---|
| 6807 |         return;
 | 
|---|
| 6808 |     autoScrollTimer->stop();
 | 
|---|
| 6809 |     mousePressed = FALSE;
 | 
|---|
| 6810 |     setCaching( FALSE );
 | 
|---|
| 6811 |     QHeader::mouseReleaseEvent( e );
 | 
|---|
| 6812 | #ifndef NO_LINE_WIDGET
 | 
|---|
| 6813 |     line1->hide();
 | 
|---|
| 6814 |     line2->hide();
 | 
|---|
| 6815 | #else
 | 
|---|
| 6816 |     if ( d->oldLinePos >= 0 )
 | 
|---|
| 6817 |         if ( orientation() == Horizontal )
 | 
|---|
| 6818 |             table->updateContents( d->oldLinePos, table->contentsY(),
 | 
|---|
| 6819 |                                    1, table->visibleHeight() );
 | 
|---|
| 6820 |         else
 | 
|---|
| 6821 |             table->updateContents(  table->contentsX(), d->oldLinePos,
 | 
|---|
| 6822 |                                     table->visibleWidth(), 1 );
 | 
|---|
| 6823 |     d->oldLinePos = -1;
 | 
|---|
| 6824 | #endif
 | 
|---|
| 6825 |     if ( resizedSection != -1 ) {
 | 
|---|
| 6826 |         emit sectionSizeChanged( resizedSection );
 | 
|---|
| 6827 |         updateStretches();
 | 
|---|
| 6828 |     }
 | 
|---|
| 6829 | 
 | 
|---|
| 6830 |     //Make sure all newly selected sections are painted one last time
 | 
|---|
| 6831 |     QRect selectedRects;
 | 
|---|
| 6832 |     for ( int i = 0; i < count(); i++ ) {
 | 
|---|
| 6833 |         if(sectionState( i ) == Selected)
 | 
|---|
| 6834 |             selectedRects |= sRect( i );
 | 
|---|
| 6835 |     }
 | 
|---|
| 6836 |     if(!selectedRects.isNull())
 | 
|---|
| 6837 |         repaint(selectedRects);
 | 
|---|
| 6838 | }
 | 
|---|
| 6839 | 
 | 
|---|
| 6840 | /*! \reimp
 | 
|---|
| 6841 | */
 | 
|---|
| 6842 | 
 | 
|---|
| 6843 | void QTableHeader::mouseDoubleClickEvent( QMouseEvent *e )
 | 
|---|
| 6844 | {
 | 
|---|
| 6845 |     if ( e->button() != LeftButton )
 | 
|---|
| 6846 |         return;
 | 
|---|
| 6847 |     if ( isResizing ) {
 | 
|---|
| 6848 |         int p = real_pos( e->pos(), orientation() ) + offset();
 | 
|---|
| 6849 |         int section = sectionAt( p );
 | 
|---|
| 6850 |         if ( section == -1 )
 | 
|---|
| 6851 |             return;
 | 
|---|
| 6852 |         section--;
 | 
|---|
| 6853 |         if ( p >= sectionPos( count() - 1 ) + sectionSize( count() - 1 ) )
 | 
|---|
| 6854 |             ++section;
 | 
|---|
| 6855 |         while ( sectionSize( section ) == 0 )
 | 
|---|
| 6856 |             section--;
 | 
|---|
| 6857 |         if ( section < 0 )
 | 
|---|
| 6858 |             return;
 | 
|---|
| 6859 |         int oldSize = sectionSize( section );
 | 
|---|
| 6860 |         if ( orientation() == Horizontal ) {
 | 
|---|
| 6861 |             table->adjustColumn( section );
 | 
|---|
| 6862 |             int newSize = sectionSize( section );
 | 
|---|
| 6863 |             if ( oldSize != newSize )
 | 
|---|
| 6864 |                 emit sizeChange( section, oldSize, newSize );
 | 
|---|
| 6865 |             for ( int i = 0; i < table->numCols(); ++i ) {
 | 
|---|
| 6866 |                 if ( table->isColumnSelected( i ) && sectionSize( i ) != 0 )
 | 
|---|
| 6867 |                     table->adjustColumn( i );
 | 
|---|
| 6868 |             }
 | 
|---|
| 6869 |         } else {
 | 
|---|
| 6870 |             table->adjustRow( section );
 | 
|---|
| 6871 |             int newSize = sectionSize( section );
 | 
|---|
| 6872 |             if ( oldSize != newSize )
 | 
|---|
| 6873 |                 emit sizeChange( section, oldSize, newSize );
 | 
|---|
| 6874 |             for ( int i = 0; i < table->numRows(); ++i ) {
 | 
|---|
| 6875 |                 if ( table->isRowSelected( i )  && sectionSize( i ) != 0 )
 | 
|---|
| 6876 |                     table->adjustRow( i );
 | 
|---|
| 6877 |             }
 | 
|---|
| 6878 |         }
 | 
|---|
| 6879 |     }
 | 
|---|
| 6880 | }
 | 
|---|
| 6881 | 
 | 
|---|
| 6882 | /*! \reimp
 | 
|---|
| 6883 | */
 | 
|---|
| 6884 | 
 | 
|---|
| 6885 | void QTableHeader::resizeEvent( QResizeEvent *e )
 | 
|---|
| 6886 | {
 | 
|---|
| 6887 |     stretchTimer->stop();
 | 
|---|
| 6888 |     widgetStretchTimer->stop();
 | 
|---|
| 6889 |     QHeader::resizeEvent( e );
 | 
|---|
| 6890 |     if ( numStretches == 0 )
 | 
|---|
| 6891 |         return;
 | 
|---|
| 6892 |     stretchTimer->start( 0, TRUE );
 | 
|---|
| 6893 | }
 | 
|---|
| 6894 | 
 | 
|---|
| 6895 | void QTableHeader::updateStretches()
 | 
|---|
| 6896 | {
 | 
|---|
| 6897 |     if ( numStretches == 0 )
 | 
|---|
| 6898 |         return;
 | 
|---|
| 6899 | 
 | 
|---|
| 6900 |     int dim = orientation() == Horizontal ? width() : height();
 | 
|---|
| 6901 |     if ( sectionPos(count() - 1) + sectionSize(count() - 1) == dim )
 | 
|---|
| 6902 |         return;
 | 
|---|
| 6903 |     int i;
 | 
|---|
| 6904 |     int pd = dim - ( sectionPos(count() - 1)
 | 
|---|
| 6905 |                      + sectionSize(count() - 1) );
 | 
|---|
| 6906 |     bool block = signalsBlocked();
 | 
|---|
| 6907 |     blockSignals( TRUE );
 | 
|---|
| 6908 |     for ( i = 0; i < (int)stretchable.count(); ++i ) {
 | 
|---|
| 6909 |         if ( !stretchable[i] ||
 | 
|---|
| 6910 |              ( stretchable[i] && table->d->hiddenCols[i] ) )
 | 
|---|
| 6911 |             continue;
 | 
|---|
| 6912 |         pd += sectionSize( i );
 | 
|---|
| 6913 |     }
 | 
|---|
| 6914 |     pd /= numStretches;
 | 
|---|
| 6915 |     for ( i = 0; i < (int)stretchable.count(); ++i ) {
 | 
|---|
| 6916 |         if ( !stretchable[i] ||
 | 
|---|
| 6917 |              ( stretchable[i] && table->d->hiddenCols[i] ) )
 | 
|---|
| 6918 |             continue;
 | 
|---|
| 6919 |         if ( i == (int)stretchable.count() - 1 &&
 | 
|---|
| 6920 |              sectionPos( i ) + pd < dim )
 | 
|---|
| 6921 |             pd = dim - sectionPos( i );
 | 
|---|
| 6922 |         resizeSection( i, QMAX( 20, pd ) );
 | 
|---|
| 6923 |     }
 | 
|---|
| 6924 |     blockSignals( block );
 | 
|---|
| 6925 |     table->repaintContents( FALSE );
 | 
|---|
| 6926 |     widgetStretchTimer->start( 100, TRUE );
 | 
|---|
| 6927 | }
 | 
|---|
| 6928 | 
 | 
|---|
| 6929 | void QTableHeader::updateWidgetStretches()
 | 
|---|
| 6930 | {
 | 
|---|
| 6931 |     QSize s = table->tableSize();
 | 
|---|
| 6932 |     table->resizeContents( s.width(), s.height() );
 | 
|---|
| 6933 |     for ( int i = 0; i < table->numCols(); ++i )
 | 
|---|
| 6934 |         table->updateColWidgets( i );
 | 
|---|
| 6935 | }
 | 
|---|
| 6936 | 
 | 
|---|
| 6937 | void QTableHeader::updateSelections()
 | 
|---|
| 6938 | {
 | 
|---|
| 6939 |     if ( table->selectionMode() == QTable::NoSelection ||
 | 
|---|
| 6940 |          (isRowSelection( table->selectionMode() ) && orientation() != Vertical  ) )
 | 
|---|
| 6941 |         return;
 | 
|---|
| 6942 |     int a = sectionAt( startPos );
 | 
|---|
| 6943 |     int b = sectionAt( endPos );
 | 
|---|
| 6944 |     int start = QMIN( a, b );
 | 
|---|
| 6945 |     int end = QMAX( a, b );
 | 
|---|
| 6946 |     register int *s = states.data();
 | 
|---|
| 6947 |     for ( int i = 0; i < count(); ++i ) {
 | 
|---|
| 6948 |         if ( i < start || i > end )
 | 
|---|
| 6949 |             *s = oldStates.data()[ i ];
 | 
|---|
| 6950 |         else
 | 
|---|
| 6951 |             *s = Selected;
 | 
|---|
| 6952 |         ++s;
 | 
|---|
| 6953 |     }
 | 
|---|
| 6954 |     repaint( FALSE );
 | 
|---|
| 6955 | 
 | 
|---|
| 6956 |     if (table->currentSel) {
 | 
|---|
| 6957 |         QTableSelection oldSelection = *table->currentSel;
 | 
|---|
| 6958 |         if ( orientation() == Vertical )
 | 
|---|
| 6959 |             table->currentSel->expandTo( b, table->horizontalHeader()->count() - 1 );
 | 
|---|
| 6960 |         else
 | 
|---|
| 6961 |             table->currentSel->expandTo( table->verticalHeader()->count() - 1, b );
 | 
|---|
| 6962 |         table->repaintSelections( &oldSelection, table->currentSel,
 | 
|---|
| 6963 |                                   orientation() == Horizontal,
 | 
|---|
| 6964 |                                   orientation() == Vertical );
 | 
|---|
| 6965 |     }
 | 
|---|
| 6966 |     emit table->selectionChanged();
 | 
|---|
| 6967 | }
 | 
|---|
| 6968 | 
 | 
|---|
| 6969 | void QTableHeader::saveStates()
 | 
|---|
| 6970 | {
 | 
|---|
| 6971 |     oldStates.resize( count() );
 | 
|---|
| 6972 |     register int *s = states.data();
 | 
|---|
| 6973 |     register int *s2 = oldStates.data();
 | 
|---|
| 6974 |     for ( int i = 0; i < count(); ++i ) {
 | 
|---|
| 6975 |         *s2 = *s;
 | 
|---|
| 6976 |         ++s2;
 | 
|---|
| 6977 |         ++s;
 | 
|---|
| 6978 |     }
 | 
|---|
| 6979 | }
 | 
|---|
| 6980 | 
 | 
|---|
| 6981 | void QTableHeader::doAutoScroll()
 | 
|---|
| 6982 | {
 | 
|---|
| 6983 |     QPoint pos = mapFromGlobal( QCursor::pos() );
 | 
|---|
| 6984 |     int p = real_pos( pos, orientation() ) + offset();
 | 
|---|
| 6985 |     if ( sectionAt( p ) != -1 )
 | 
|---|
| 6986 |         endPos = p;
 | 
|---|
| 6987 |     if ( orientation() == Horizontal )
 | 
|---|
| 6988 |         table->ensureVisible( endPos, table->contentsY() );
 | 
|---|
| 6989 |     else
 | 
|---|
| 6990 |         table->ensureVisible( table->contentsX(), endPos );
 | 
|---|
| 6991 |     updateSelections();
 | 
|---|
| 6992 |     autoScrollTimer->start( 100, TRUE );
 | 
|---|
| 6993 | }
 | 
|---|
| 6994 | 
 | 
|---|
| 6995 | void QTableHeader::sectionWidthChanged( int col, int, int )
 | 
|---|
| 6996 | {
 | 
|---|
| 6997 |     resizedSection = col;
 | 
|---|
| 6998 |     if ( orientation() == Horizontal ) {
 | 
|---|
| 6999 | #ifndef NO_LINE_WIDGET
 | 
|---|
| 7000 |         table->moveChild( line1, QHeader::sectionPos( col ) - 1,
 | 
|---|
| 7001 |                           table->contentsY() );
 | 
|---|
| 7002 |         line1->resize( 1, table->visibleHeight() );
 | 
|---|
| 7003 |         line1->show();
 | 
|---|
| 7004 |         line1->raise();
 | 
|---|
| 7005 |         table->moveChild( line2,
 | 
|---|
| 7006 |                           QHeader::sectionPos( col ) + QHeader::sectionSize( col ) - 1,
 | 
|---|
| 7007 |                           table->contentsY() );
 | 
|---|
| 7008 |         line2->resize( 1, table->visibleHeight() );
 | 
|---|
| 7009 |         line2->show();
 | 
|---|
| 7010 |         line2->raise();
 | 
|---|
| 7011 | #else
 | 
|---|
| 7012 |         QPainter p( table->viewport() );
 | 
|---|
| 7013 |         int lx = QHeader::sectionPos( col ) + QHeader::sectionSize( col ) - 1;
 | 
|---|
| 7014 |         int ly = table->contentsY();
 | 
|---|
| 7015 | 
 | 
|---|
| 7016 |         if ( lx != d->oldLinePos ) {
 | 
|---|
| 7017 |             QPoint pt = table->contentsToViewport( QPoint( lx, ly ) );
 | 
|---|
| 7018 |             p.drawLine( pt.x(), pt.y()+1,
 | 
|---|
| 7019 |                         pt.x(), pt.y()+ table->visibleHeight() );
 | 
|---|
| 7020 |             if ( d->oldLinePos >= 0 )
 | 
|---|
| 7021 |                 table->repaintContents( d->oldLinePos, table->contentsY(),
 | 
|---|
| 7022 |                                        1, table->visibleHeight() );
 | 
|---|
| 7023 | 
 | 
|---|
| 7024 |             d->oldLinePos = lx;
 | 
|---|
| 7025 |         }
 | 
|---|
| 7026 | #endif
 | 
|---|
| 7027 |     } else {
 | 
|---|
| 7028 | #ifndef NO_LINE_WIDGET
 | 
|---|
| 7029 |         table->moveChild( line1, table->contentsX(),
 | 
|---|
| 7030 |                           QHeader::sectionPos( col ) - 1 );
 | 
|---|
| 7031 |         line1->resize( table->visibleWidth(), 1 );
 | 
|---|
| 7032 |         line1->show();
 | 
|---|
| 7033 |         line1->raise();
 | 
|---|
| 7034 |         table->moveChild( line2, table->contentsX(),
 | 
|---|
| 7035 |                           QHeader::sectionPos( col ) + QHeader::sectionSize( col ) - 1 );
 | 
|---|
| 7036 |         line2->resize( table->visibleWidth(), 1 );
 | 
|---|
| 7037 |         line2->show();
 | 
|---|
| 7038 |         line2->raise();
 | 
|---|
| 7039 | 
 | 
|---|
| 7040 | #else
 | 
|---|
| 7041 |         QPainter p( table->viewport() );
 | 
|---|
| 7042 |         int lx = table->contentsX();
 | 
|---|
| 7043 |         int ly = QHeader::sectionPos( col ) + QHeader::sectionSize( col ) - 1;
 | 
|---|
| 7044 | 
 | 
|---|
| 7045 |         if ( ly != d->oldLinePos ) {
 | 
|---|
| 7046 |             QPoint pt = table->contentsToViewport( QPoint( lx, ly ) );
 | 
|---|
| 7047 |             p.drawLine( pt.x()+1, pt.y(),
 | 
|---|
| 7048 |                         pt.x() + table->visibleWidth(), pt.y() );
 | 
|---|
| 7049 |             if ( d->oldLinePos >= 0 )
 | 
|---|
| 7050 |                 table->repaintContents(  table->contentsX(), d->oldLinePos,
 | 
|---|
| 7051 |                                         table->visibleWidth(), 1 );
 | 
|---|
| 7052 |             d->oldLinePos = ly;
 | 
|---|
| 7053 |         }
 | 
|---|
| 7054 | 
 | 
|---|
| 7055 | #endif
 | 
|---|
| 7056 |     }
 | 
|---|
| 7057 | }
 | 
|---|
| 7058 | 
 | 
|---|
| 7059 | /*!
 | 
|---|
| 7060 |     \reimp
 | 
|---|
| 7061 | 
 | 
|---|
| 7062 |     Returns the size of section \a section in pixels or -1 if \a
 | 
|---|
| 7063 |     section is out of range.
 | 
|---|
| 7064 | */
 | 
|---|
| 7065 | 
 | 
|---|
| 7066 | int QTableHeader::sectionSize( int section ) const
 | 
|---|
| 7067 | {
 | 
|---|
| 7068 |     if ( count() <= 0 || section < 0 || section >= count() )
 | 
|---|
| 7069 |         return -1;
 | 
|---|
| 7070 |     if ( caching && section < (int)sectionSizes.count() )
 | 
|---|
| 7071 |          return sectionSizes[ section ];
 | 
|---|
| 7072 |     return QHeader::sectionSize( section );
 | 
|---|
| 7073 | }
 | 
|---|
| 7074 | 
 | 
|---|
| 7075 | /*!
 | 
|---|
| 7076 |     \reimp
 | 
|---|
| 7077 | 
 | 
|---|
| 7078 |     Returns the start position of section \a section in pixels or -1
 | 
|---|
| 7079 |     if \a section is out of range.
 | 
|---|
| 7080 | 
 | 
|---|
| 7081 |     \sa sectionAt()
 | 
|---|
| 7082 | */
 | 
|---|
| 7083 | 
 | 
|---|
| 7084 | int QTableHeader::sectionPos( int section ) const
 | 
|---|
| 7085 | {
 | 
|---|
| 7086 |     if ( count() <= 0 || section < 0 || section >= count() )
 | 
|---|
| 7087 |         return -1;
 | 
|---|
| 7088 |     if ( caching && section < (int)sectionPoses.count() )
 | 
|---|
| 7089 |         return sectionPoses[ section ];
 | 
|---|
| 7090 |     return QHeader::sectionPos( section );
 | 
|---|
| 7091 | }
 | 
|---|
| 7092 | 
 | 
|---|
| 7093 | /*!
 | 
|---|
| 7094 |     \reimp
 | 
|---|
| 7095 | 
 | 
|---|
| 7096 |     Returns the number of the section at index position \a pos or -1
 | 
|---|
| 7097 |     if there is no section at the position given.
 | 
|---|
| 7098 | 
 | 
|---|
| 7099 |     \sa sectionPos()
 | 
|---|
| 7100 | */
 | 
|---|
| 7101 | 
 | 
|---|
| 7102 | int QTableHeader::sectionAt( int pos ) const
 | 
|---|
| 7103 | {
 | 
|---|
| 7104 |     if ( !caching || sectionSizes.count() <= 0 || sectionPoses.count() <= 0 )
 | 
|---|
| 7105 |         return QHeader::sectionAt( pos );
 | 
|---|
| 7106 |     if ( count() <= 0 || pos > sectionPoses[ count() - 1 ] + sectionSizes[ count() - 1 ] )
 | 
|---|
| 7107 |         return -1;
 | 
|---|
| 7108 |     int l = 0;
 | 
|---|
| 7109 |     int r = count() - 1;
 | 
|---|
| 7110 |     int i = ( (l+r+1) / 2 );
 | 
|---|
| 7111 |     while ( r - l ) {
 | 
|---|
| 7112 |         if ( sectionPoses[i] > pos )
 | 
|---|
| 7113 |             r = i -1;
 | 
|---|
| 7114 |         else
 | 
|---|
| 7115 |             l = i;
 | 
|---|
| 7116 |         i = ( (l+r+1) / 2 );
 | 
|---|
| 7117 |     }
 | 
|---|
| 7118 |     if ( sectionPoses[i] <= pos &&
 | 
|---|
| 7119 |          pos <= sectionPoses[i] + sectionSizes[ mapToSection( i ) ] )
 | 
|---|
| 7120 |         return mapToSection( i );
 | 
|---|
| 7121 |     return -1;
 | 
|---|
| 7122 | }
 | 
|---|
| 7123 | 
 | 
|---|
| 7124 | void QTableHeader::updateCache()
 | 
|---|
| 7125 | {
 | 
|---|
| 7126 |     sectionPoses.resize( count() );
 | 
|---|
| 7127 |     sectionSizes.resize( count() );
 | 
|---|
| 7128 |     if ( !caching )
 | 
|---|
| 7129 |         return;
 | 
|---|
| 7130 |     for ( int i = 0; i < count(); ++i ) {
 | 
|---|
| 7131 |         sectionSizes[ i ] = QHeader::sectionSize( i );
 | 
|---|
| 7132 |         sectionPoses[ i ] = QHeader::sectionPos( i );
 | 
|---|
| 7133 |     }
 | 
|---|
| 7134 | }
 | 
|---|
| 7135 | 
 | 
|---|
| 7136 | void QTableHeader::setCaching( bool b )
 | 
|---|
| 7137 | {
 | 
|---|
| 7138 |     if ( caching == b )
 | 
|---|
| 7139 |         return;
 | 
|---|
| 7140 |     caching = b;
 | 
|---|
| 7141 |     sectionPoses.resize( count() );
 | 
|---|
| 7142 |     sectionSizes.resize( count() );
 | 
|---|
| 7143 |     if ( b ) {
 | 
|---|
| 7144 |         for ( int i = 0; i < count(); ++i ) {
 | 
|---|
| 7145 |             sectionSizes[ i ] = QHeader::sectionSize( i );
 | 
|---|
| 7146 |             sectionPoses[ i ] = QHeader::sectionPos( i );
 | 
|---|
| 7147 |         }
 | 
|---|
| 7148 |     }
 | 
|---|
| 7149 | }
 | 
|---|
| 7150 | 
 | 
|---|
| 7151 | /*!
 | 
|---|
| 7152 |     If \a b is TRUE, section \a s is stretchable; otherwise the
 | 
|---|
| 7153 |     section is not stretchable.
 | 
|---|
| 7154 | 
 | 
|---|
| 7155 |     \sa isSectionStretchable()
 | 
|---|
| 7156 | */
 | 
|---|
| 7157 | 
 | 
|---|
| 7158 | void QTableHeader::setSectionStretchable( int s, bool b )
 | 
|---|
| 7159 | {
 | 
|---|
| 7160 |     if ( stretchable[ s ] == b )
 | 
|---|
| 7161 |         return;
 | 
|---|
| 7162 |     stretchable[ s ] = b;
 | 
|---|
| 7163 |     if ( b )
 | 
|---|
| 7164 |         numStretches++;
 | 
|---|
| 7165 |     else
 | 
|---|
| 7166 |         numStretches--;
 | 
|---|
| 7167 | }
 | 
|---|
| 7168 | 
 | 
|---|
| 7169 | /*!
 | 
|---|
| 7170 |     Returns TRUE if section \a s is stretcheable; otherwise returns
 | 
|---|
| 7171 |     FALSE.
 | 
|---|
| 7172 | 
 | 
|---|
| 7173 |     \sa setSectionStretchable()
 | 
|---|
| 7174 | */
 | 
|---|
| 7175 | 
 | 
|---|
| 7176 | bool QTableHeader::isSectionStretchable( int s ) const
 | 
|---|
| 7177 | {
 | 
|---|
| 7178 |     return stretchable[ s ];
 | 
|---|
| 7179 | }
 | 
|---|
| 7180 | 
 | 
|---|
| 7181 | void QTableHeader::swapSections( int oldIdx, int newIdx, bool swapTable )
 | 
|---|
| 7182 | {
 | 
|---|
| 7183 |     extern bool qt_qheader_label_return_null_strings; // qheader.cpp
 | 
|---|
| 7184 |     qt_qheader_label_return_null_strings = TRUE;
 | 
|---|
| 7185 | 
 | 
|---|
| 7186 |     QIconSet oldIconSet, newIconSet;
 | 
|---|
| 7187 |     if ( iconSet( oldIdx ) )
 | 
|---|
| 7188 |         oldIconSet = *iconSet( oldIdx );
 | 
|---|
| 7189 |     if ( iconSet( newIdx ) )
 | 
|---|
| 7190 |         newIconSet = *iconSet( newIdx );
 | 
|---|
| 7191 |     QString oldLabel = label( oldIdx );
 | 
|---|
| 7192 |     setLabel( oldIdx, newIconSet, label( newIdx ) );
 | 
|---|
| 7193 |     setLabel( newIdx, oldIconSet, oldLabel );
 | 
|---|
| 7194 | 
 | 
|---|
| 7195 |     qt_qheader_label_return_null_strings = FALSE;
 | 
|---|
| 7196 | 
 | 
|---|
| 7197 |      int w1 = sectionSize( oldIdx );
 | 
|---|
| 7198 |      int w2 = sectionSize( newIdx );
 | 
|---|
| 7199 |      if ( w1 != w2 ) {
 | 
|---|
| 7200 |          resizeSection( oldIdx, w2 );
 | 
|---|
| 7201 |          resizeSection( newIdx, w1 );
 | 
|---|
| 7202 |      }
 | 
|---|
| 7203 | 
 | 
|---|
| 7204 |      if ( !swapTable )
 | 
|---|
| 7205 |          return;
 | 
|---|
| 7206 |      if ( orientation() == Horizontal )
 | 
|---|
| 7207 |          table->swapColumns( oldIdx, newIdx );
 | 
|---|
| 7208 |      else
 | 
|---|
| 7209 |          table->swapRows( oldIdx, newIdx );
 | 
|---|
| 7210 | }
 | 
|---|
| 7211 | 
 | 
|---|
| 7212 | void QTableHeader::indexChanged( int sec, int oldIdx, int newIdx )
 | 
|---|
| 7213 | {
 | 
|---|
| 7214 |     newIdx = mapToIndex( sec );
 | 
|---|
| 7215 |     if ( oldIdx > newIdx )
 | 
|---|
| 7216 |         moveSection( sec, oldIdx + 1 );
 | 
|---|
| 7217 |     else
 | 
|---|
| 7218 |         moveSection( sec, oldIdx );
 | 
|---|
| 7219 | 
 | 
|---|
| 7220 |     if ( oldIdx < newIdx ) {
 | 
|---|
| 7221 |         while ( oldIdx < newIdx ) {
 | 
|---|
| 7222 |             swapSections( oldIdx, oldIdx + 1 );
 | 
|---|
| 7223 |             oldIdx++;
 | 
|---|
| 7224 |         }
 | 
|---|
| 7225 |     } else {
 | 
|---|
| 7226 |         while ( oldIdx > newIdx ) {
 | 
|---|
| 7227 |             swapSections( oldIdx - 1, oldIdx );
 | 
|---|
| 7228 |             oldIdx--;
 | 
|---|
| 7229 |         }
 | 
|---|
| 7230 |     }
 | 
|---|
| 7231 | 
 | 
|---|
| 7232 |     table->repaintContents( table->contentsX(), table->contentsY(),
 | 
|---|
| 7233 |                             table->visibleWidth(), table->visibleHeight() );
 | 
|---|
| 7234 | }
 | 
|---|
| 7235 | 
 | 
|---|
| 7236 | void QTableHeader::setLabels(const QStringList & labels)
 | 
|---|
| 7237 | {
 | 
|---|
| 7238 |     int i = 0;
 | 
|---|
| 7239 |     bool updates = isUpdatesEnabled();
 | 
|---|
| 7240 |     setUpdatesEnabled(FALSE);
 | 
|---|
| 7241 |     for ( QStringList::ConstIterator it = labels.begin();
 | 
|---|
| 7242 |           it != labels.end() && i < count(); ++i, ++it ) {
 | 
|---|
| 7243 |         if (i == (int)labels.count() - 1) {
 | 
|---|
| 7244 |             setUpdatesEnabled(updates);
 | 
|---|
| 7245 |             setLabel( i, *it );
 | 
|---|
| 7246 |         } else {
 | 
|---|
| 7247 |             QHeader::setLabel( i, *it );
 | 
|---|
| 7248 |             emit sectionSizeChanged( i );
 | 
|---|
| 7249 |         }
 | 
|---|
| 7250 |     }
 | 
|---|
| 7251 | }
 | 
|---|
| 7252 | 
 | 
|---|
| 7253 | #include "qtable.moc"
 | 
|---|
| 7254 | 
 | 
|---|
| 7255 | #endif // QT_NO_TABLE
 | 
|---|