?? qheader.cpp
字號(hào):
/****************************************************************************** $Id: qt/src/widgets/qheader.cpp 2.3.12 edited 2005-10-27 $**** Implementation of QHeader widget class (table header)**** Created : 961105**** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.**** This file is part of the widgets module of the Qt GUI Toolkit.**** This file may be distributed under the terms of the Q Public License** as defined by Trolltech AS of Norway and appearing in the file** LICENSE.QPL included in the packaging of this file.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition** licenses may use this file in accordance with the Qt Commercial License** Agreement provided with the Software.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for** information about Qt Commercial License Agreements.** See http://www.trolltech.com/qpl/ for QPL licensing information.** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "qheader.h"#ifndef QT_NO_HEADER#include "qpainter.h"#include "qdrawutil.h"#include "qbitmap.h"#include "qbitarray.h"#include "qvector.h"static const int GRIPMARGIN = 4; //half the size of the resize areastatic const int MARKSIZE = 32;static const int QH_MARGIN = 4;struct QHeaderData{ QHeaderData(int n) { count = n; labels.setAutoDelete( TRUE ); iconsets.setAutoDelete( TRUE ); sizes.resize(n); positions.resize(n); heights.resize(n); labels.resize(n); if ( int( iconsets.size() ) < n ) iconsets.resize( n ); i2s.resize(n); s2i.resize(n); clicks.resize(n); resize.resize(n); int p =0; for ( int i = 0; i < n ; i ++ ) { sizes[i] = 88; // heights[i] = 10; set properly in QHeader::init() i2s[i] = i; s2i[i] = i; positions[i] = p; p += sizes[i]; } clicks_default = TRUE; resize_default = TRUE; clicks.fill( clicks_default ); resize.fill( resize_default ); move = TRUE; sortColumn = -1; sortDirection = TRUE; positionsDirty = TRUE; } QArray<QCOORD> sizes; QArray<QCOORD> heights; QArray<QCOORD> positions; // sorted by index QVector<QString> labels; QVector<QIconSet> iconsets; QArray<int> i2s; QArray<int> s2i; QBitArray clicks; QBitArray resize; uint move : 1; uint clicks_default : 1; // default value for new clicks bits uint resize_default : 1; // default value for new resize bits bool sortDirection; int sortColumn; int count; bool positionsDirty; void calculatePositions(){ // positions is sorted by index, not by section positionsDirty = FALSE; int p = 0; for ( int i = 0; i < count; i++ ) { positions[i] = p; p +=sizes[i2s[i]]; } } int sectionAt( int pos ) { // positions is sorted by index, not by section if ( !count ) return -1; int l = 0; int r = count - 1; int i = ( (l+r+1) / 2 ); while ( r - l ) { if ( positions[i] > pos ) r = i -1; else l = i; i = ( (l+r+1) / 2 ); } if ( positions[i] <= pos && pos <= positions[i] + sizes[ i2s[i] ] ) return i2s[i]; return -1; }};// BEING REVISED: eiriken/*! \class QHeader qheader.h \brief The QHeader class provides a table header. \ingroup advanced This class provides a table header as known from spreadsheet-like widgets. QHeader can be used vertically or horizontally (see setOrientation()). With addLabel() you can add sections, and with removeLabel() you can remove them. If you enabled clicking for one or all sections (see setClickEnabled()), the user can reorder the sections and click on them which may be used for sorting (see also setSortIndicator()). This feature is turned on by default. So, if the user reorders the sections by clicking and moving them with the mouse the index of a section may change. This means, the section you inserted at the first position might be displayed at a different index then. To get the index at which e.g the first section is displayed, use mapToIndex() with 0 as argument for our example. If you want e.g. to know which section is displayed at e.g. index 3 use mapToSection() with 3 as argument. So, you can always work with the section numbers as you inserted them without caring about the index at which they are displayed at the moment. Also the API of QHeader works with the section numbers. <img src=qheader-m.png> <img src=qheader-w.png> \sa QListView QTableView *//*! Constructs a horizontal header. The \e parent and \e name arguments are sent to the QWidget constructor.*/QHeader::QHeader( QWidget *parent, const char *name ) : QWidget( parent, name, WNorthWestGravity ){ orient = Horizontal; init( 0 );}/*! Constructs a horizontal header with \a n sections. The \e parent and \e name arguments are sent to the QWidget constructor.*/QHeader::QHeader( int n, QWidget *parent, const char *name ) : QWidget( parent, name, WNorthWestGravity ){ orient = Horizontal; init( n );}/*! Destructs the header. */QHeader::~QHeader(){ delete d; d = 0;}/*! \reimp */void QHeader::showEvent( QShowEvent *e ){ d->calculatePositions(); QWidget::showEvent( e );}/*! \fn void QHeader::sizeChange( int section, int oldSize, int newSize ) This signal is emitted when the user has changed the size of some of a \a section of the header from \a oldSize to \a newSize. This signal is typically connected to a slot that repaints the table.*//*! \fn void QHeader::clicked( int section ) This signal is emitted when the user clicked onto the section \a section. \sa pressed(), released()*//*! \fn void QHeader::pressed( int section ) This signal is emitted when the user presses section \a section down. \sa released()*//*! \fn void QHeader::released( int section ) This signal is emitted when section \a section is released. \sa pressed()*//*! \fn void QHeader::indexChange( int section, int fromIndex, int toIndex ) This signal is emitted if the user moved the section \a section, which was displayed at the index \a fromIndex to the new index \a toIndex.*//*! \fn void QHeader::moved( int fromIndex, int toIndex ) \obsolete Use indexChange() instead! This signal is emitted when the user has moved the section which is displayed at the index \a fromIndex to the index \a toIndex.*//*! \fn void QHeader::sectionClicked( int index ) \obsolete Use clicked() instead! This signal is emitted when a part of the header is clicked. \a index is the index at which the section is displayed. In a list view, this signal would typically be connected to a slot which sorts the specified column (or row).*//*! \obsolete Use sectionSize() instead! Returns the size in pixels of the section which is displayed at the index \a i.*/int QHeader::cellSize( int i ) const{ return sectionSize( mapToSection(i) );}/*! \obsolete Use sectionPos() instead! Returns the position in pixels of the section which is displayed at the index \a i. The position is measured from the start of the header.*/int QHeader::cellPos( int i ) const{ if ( i == count() && i > 0 ) return d->positions[i-1] + d->sizes[d->i2s[i-1]]; // compatibility return sectionPos( mapToSection(i) );}/*! Returns the number of sections in the header.*/int QHeader::count() const{ return d->count;}/*! \fn Orientation QHeader::orientation() const Returns \c Horizontal if the header is horizontal, \c Vertical if the header is vertical. *//*! \fn void QHeader::setTracking( bool enable ) Sets tracking if \a enable is TRUE, otherwise turns off tracking. If tracking is on, the sizeChange() signal is emitted continuously while the mouse is moved, otherwise it is only emitted when the mouse button is released. \sa tracking() *//*! \fn bool QHeader::tracking() const Returns TRUE if tracking is on, FALSE otherwise. \sa setTracking() *//*! Initializes with \a n columns. */void QHeader::init( int n ){ state = Idle; offs = 0; cachedIdx = 0; // unused cachedPos = 0; // unused d = new QHeaderData(n); for ( int i = 0; i < n ; i ++ ) { d->heights[i] = fontMetrics().lineSpacing()+6; } handleIdx = 0; setMouseTracking( TRUE ); trackingIsOn = FALSE; setBackgroundMode( PaletteButton ); setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );}/*! Sets the header orientation. The \e orientation must be QHeader::Vertical or QHeader::Horizontal. When adding labels without the size parameter, setOrientation should be called first, otherwise labels will be sized incorrectly. \sa orientation()*/void QHeader::setOrientation( Orientation orientation ){ if (orient==orientation) return; orient = orientation; if ( orient == Horizontal ) setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) ); else setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Preferred ) ); update(); updateGeometry();}/*! Paints a rectangle starting at \a p, with length \s. */void QHeader::paintRect( int p, int s ){ QPainter paint( this ); paint.setPen( QPen( black, 1, DotLine ) ); if ( orient == Horizontal ) paint.drawRect( p, 3, s, height() - 5 ); else paint.drawRect( 3, p, height() - 5, s );}/*! Marks the division line at \a idx. */void QHeader::markLine( int idx ){ QPainter paint( this ); paint.setPen( QPen( black, 1, DotLine ) ); int p = pPos( idx ); int x = p - MARKSIZE/2; int y = 2; int x2 = p + MARKSIZE/2; int y2 = height() - 3; if ( orient == Vertical ) { int t = x; x = y; y = t; t = x2; x2 = y2; y2 = t; } paint.drawLine( x, y, x2, y ); paint.drawLine( x, y+1, x2, y+1 ); paint.drawLine( x, y2, x2, y2 ); paint.drawLine( x, y2-1, x2, y2-1 ); paint.drawLine( x, y, x, y2 ); paint.drawLine( x+1, y, x+1, y2 ); paint.drawLine( x2, y, x2, y2 ); paint.drawLine( x2-1, y, x2-1, y2 );}/*! Removes the mark at the division line at \a idx. */void QHeader::unMarkLine( int idx ){ if ( idx < 0 ) return; int p = pPos( idx ); int x = p - MARKSIZE/2; int y = 2; int x2 = p + MARKSIZE/2; int y2 = height() - 3; if ( orient == Vertical ) { int t = x; x = y; y = t; t = x2; x2 = y2; y2 = t; } repaint( x, y, x2-x+1, y2-y+1 );}/*! \obsolete Use sectionAt() instead! Returns the index at which the section is displayed, which contains \a pos in widget coordinates, or -1 if \a pos is outside the header sections.*/int QHeader::cellAt( int pos ) const{ return mapToIndex( sectionAt(pos + offset()) );}/*! Tries to find a line that is not a neighbor of \c handleIdx. */int QHeader::findLine( int c ){ int lastpos = d->positions[d->count-1] + d->sizes[d->i2s[d->count-1]]; int i = 0; if ( c > lastpos ) { return d->count; } else { int section = sectionAt( c ); if ( section < 0 ) return handleIdx; i = d->s2i[section]; } if ( i == handleIdx ) return i; if ( i == handleIdx - 1 && pPos( handleIdx ) - c > MARKSIZE/2 ) return i; if ( i == handleIdx + 1 && c - pPos( i ) > MARKSIZE/2 ) return i + 1; if ( c - pPos( i ) > pSize( i ) / 2 ) return i + 1; else return i;}/*! \obsolete Use moveSection() instead! Moves the section which is currently displayed at the index \a fromIndex to the index \a toIdx.*/void QHeader::moveCell( int fromIdx, int toIdx ){ moveSection( mapToSection(fromIdx), toIdx );}/*! \reimp*/void QHeader::mousePressEvent( QMouseEvent *e ){ if ( e->button() != LeftButton || state != Idle ) return; handleIdx = 0; int c = orient == Horizontal ? e->pos().x() : e->pos().y(); c += offset(); int section = sectionAt( c );
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -