📄 q3header.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the Qt3Support module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "q3header.h"#ifndef QT_NO_HEADER#include "qapplication.h"#include "qbitarray.h"#include "qcursor.h"#include "qdrawutil.h"#include "qevent.h"#include "qpainter.h"#include "qpixmap.h"#include "qstyle.h"#include "qstyleoption.h"#include "qvector.h"class Q3HeaderData{public: Q3HeaderData(int n) { count = n; sizes.resize(n); positions.resize(n); labels.resize(n); nullStringLabels.resize(n); icons.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; 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; sortSection = -1; sortDirection = true; positionsDirty = true; lastPos = 0; fullSize = -2; pos_dirty = false; is_a_table_header = false; focusIdx = 0; } ~Q3HeaderData() { for (int i = 0; i < icons.size(); ++i) delete icons.at(i); } QVector<int> sizes; int height; // we abuse the heights as widths for vertical layout bool heightDirty; QVector<int> positions; // sorted by index QVector<QString> labels; QVector<QIcon *> icons; QVector<int> i2s; QVector<int> s2i; QBitArray clicks; QBitArray resize; QBitArray nullStringLabels; uint move : 1; uint clicks_default : 1; // default value for new clicks bits uint resize_default : 1; // default value for new resize bits uint pos_dirty : 1; uint is_a_table_header : 1; bool sortDirection; bool positionsDirty; int sortSection; int count; int lastPos; int fullSize; int focusIdx; int pressDelta; 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; }};static QStyleOptionHeader getStyleOption(const Q3Header *header, int section){ QStyleOptionHeader opt; opt.init(header); opt.section = section; opt.textAlignment = Qt::AlignVCenter; opt.iconAlignment = Qt::AlignVCenter; if (header->iconSet(section)) opt.icon = *header->iconSet(section); opt.text = header->label(section); if (header->orientation() == Qt::Horizontal) opt.state = QStyle::State_Horizontal; return opt;}bool qt_get_null_label_bit(Q3HeaderData *data, int section){ return data->nullStringLabels.testBit(section);}void qt_set_null_label_bit(Q3HeaderData *data, int section, bool b){ data->nullStringLabels.setBit(section, b);}/*! \class Q3Header q3header.h \brief The Q3Header class provides a header row or column, e.g. for tables and listviews. \compat This class provides a header, e.g. a vertical header to display row labels, or a horizontal header to display column labels. It is used by Q3Table and Q3ListView for example. A header is composed of one or more \e sections, each of which can display a text label and an \link QIcon icon\endlink. A sort indicator (an arrow) can also be displayed using setSortIndicator(). Sections are added with addLabel() and removed with removeLabel(). The label and icon are set in addLabel() and can be changed later with setLabel(). Use count() to retrieve the number of sections in the header. The orientation of the header is set with setOrientation(). If setStretchEnabled() is true, the sections will expand to take up the full width (height for vertical headers) of the header. The user can resize the sections manually if setResizeEnabled() is true. Call adjustHeaderSize() to have the sections resize to occupy the full width (or height). A section can be moved with moveSection(). If setMovingEnabled() is true (the default)the user may drag a section from one position to another. If a section is moved, the index positions at which sections were added (with addLabel()), may not be the same after the move. You don't have to worry about this in practice because the Q3Header API works in terms of section numbers, so it doesn't matter where a particular section has been moved to. If you want the current index position of a section call mapToIndex() giving it the section number. (This is the number returned by the addLabel() call which created the section.) If you want to get the section number of a section at a particular index position call mapToSection() giving it the index number. Here's an example to clarify mapToSection() and mapToIndex(): \table \header \i41 Index positions \row \i 0 \i 1 \i 2 \i 3 \header \i41 Original section ordering \row \i Sect 0 \i Sect 1 \i Sect 2 \i Sect 3 \header \i41 Ordering after the user moves a section \row \i Sect 0 \i Sect 2 \i Sect 3 \i Sect 1 \endtable \table \header \i \e k \i mapToSection(\e k) \i mapToIndex(\e k) \row \i 0 \i 0 \i 0 \row \i 1 \i 2 \i 3 \row \i 2 \i 3 \i 1 \row \i 3 \i 1 \i 2 \endtable In the example above, if we wanted to find out which section is at index position 3 we'd call mapToSection(3) and get a section number of 1 since section 1 was moved. Similarly, if we wanted to know which index position section 2 occupied we'd call mapToIndex(2) and get an index of 1. Q3Header provides the clicked(), pressed() and released() signals. If the user changes the size of a section, the sizeChange() signal is emitted. If you want to have a sizeChange() signal emitted continuously whilst the user is resizing (rather than just after the resizing is finished), use setTracking(). If the user moves a section the indexChange() signal is emitted. \sa Q3ListView Q3Table*//*! Constructs a horizontal header called \a name, with parent \a parent.*/Q3Header::Q3Header(QWidget *parent, const char *name) : QWidget(parent, name, Qt::WStaticContents){ orient = Qt::Horizontal; init(0);}/*! Constructs a horizontal header called \a name, with \a n sections and parent \a parent.*/Q3Header::Q3Header(int n, QWidget *parent, const char *name) : QWidget(parent, name, Qt::WStaticContents){ orient = Qt::Horizontal; init(n);}/*! Destroys the header and all its sections.*/Q3Header::~Q3Header(){ delete d; d = 0;}/*! \reimp */void Q3Header::showEvent(QShowEvent *e){ calculatePositions(); QWidget::showEvent(e);}/*! \fn void Q3Header::sizeChange(int section, int oldSize, int newSize) This signal is emitted when the user has changed the size of a \a section from \a oldSize to \a newSize. This signal is typically connected to a slot that repaints the table or list that contains the header.*//*! \fn void Q3Header::clicked(int section) If isClickEnabled() is true, this signal is emitted when the user clicks section \a section. \sa pressed(), released()*//*! \fn void Q3Header::pressed(int section) This signal is emitted when the user presses section \a section down. \sa released()*//*! \fn void Q3Header::released(int section) This signal is emitted when section \a section is released. \sa pressed()*//*! \fn void Q3Header::indexChange(int section, int fromIndex, int toIndex) This signal is emitted when the user moves section \a section from index position \a fromIndex, to index position \a toIndex.*//*! \fn void Q3Header::moved(int fromIndex, int toIndex) 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 Q3Header::sectionClicked(int index) 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 that sorts the specified column (or row).*//*! \fn int Q3Header::cellSize(int) const Use sectionSize() instead. Returns the size in pixels of the section that is displayed at the index \a i.*//*! \fn void Q3Header::sectionHandleDoubleClicked(int section) This signal is emitted when the user doubleclicks on the edge (handle) of section \a section.*//*! Use sectionPos() instead. Returns the position in pixels of the section that is displayed at the index \a i. The position is measured from the start of the header.*/int Q3Header::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));}/*! \property Q3Header::count \brief the number of sections in the header*/int Q3Header::count() const{ return d->count;}/*! \property Q3Header::tracking \brief whether the sizeChange() signal is emitted continuously If tracking is on, the sizeChange() signal is emitted continuously while the mouse is moved (i.e. when the header is resized), otherwise it is only emitted when the mouse button is released at the end of resizing. Tracking defaults to false.*//* Initializes with \a n columns.*/void Q3Header::init(int n){ state = Idle; cachedPos = 0; // unused d = new Q3HeaderData(n); d->height = 0; d->heightDirty = true; offs = 0; if(reverse()) offs = d->lastPos - width(); oldHandleIdx = oldHIdxSize = handleIdx = 0; setMouseTracking(true); trackingIsOn = false; setBackgroundRole(QPalette::Button); setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); setAttribute(Qt::WA_PaintOutsidePaintEvent);}/*! \property Q3Header::orientation \brief the header's orientation The orientation is either Qt::Vertical or Qt::Horizontal (the default). Call setOrientation() before adding labels if you don't provide a size parameter otherwise the sizes will be incorrect.*/void Q3Header::setOrientation(Qt::Orientation orientation){ if (orient == orientation) return; orient = orientation; if (orient == Qt::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 Q3Header::paintRect(int p, int s){ QPainter paint(this); paint.setPen(QPen(Qt::black, 1, Qt::DotLine)); if (reverse()) paint.drawRect(p - s, 3, s, height() - 5); else if (orient == Qt::Horizontal) paint.drawRect(p, 3, s, height() - 5); else paint.drawRect(3, p, height() - 5, s);}/* Marks the division line at \a idx.*/void Q3Header::markLine(int idx){ QPainter paint(this); paint.setPen(QPen(Qt::black, 1, Qt::DotLine)); int MARKSIZE = style()->pixelMetric(QStyle::PM_HeaderMarkSize); int p = pPos(idx); int x = p - MARKSIZE/2; int y = 2; int x2 = p + MARKSIZE/2; int y2 = height() - 3; if (orient == Qt::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 Q3Header::unMarkLine(int idx){ if (idx < 0) return; int MARKSIZE = style()->pixelMetric(QStyle::PM_HeaderMarkSize); int p = pPos(idx); int x = p - MARKSIZE/2; int y = 2; int x2 = p + MARKSIZE/2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -