diff options
Diffstat (limited to 'src/quicktemplates2')
-rw-r--r-- | src/quicktemplates2/qquickabstractbutton.cpp | 7 | ||||
-rw-r--r-- | src/quicktemplates2/qquickabstractbutton_p_p.h | 1 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcombobox.cpp | 8 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcombobox_p.h | 1 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol.cpp | 12 | ||||
-rw-r--r-- | src/quicktemplates2/qquickcontrol_p_p.h | 2 | ||||
-rw-r--r-- | src/quicktemplates2/qquickdialogbuttonbox.cpp | 7 | ||||
-rw-r--r-- | src/quicktemplates2/qquickheaderview.cpp | 500 | ||||
-rw-r--r-- | src/quicktemplates2/qquickheaderview_p.h | 125 | ||||
-rw-r--r-- | src/quicktemplates2/qquickheaderview_p_p.h | 136 | ||||
-rw-r--r-- | src/quicktemplates2/qquicktooltip.cpp | 20 | ||||
-rw-r--r-- | src/quicktemplates2/quicktemplates2.pri | 3 |
12 files changed, 814 insertions, 8 deletions
diff --git a/src/quicktemplates2/qquickabstractbutton.cpp b/src/quicktemplates2/qquickabstractbutton.cpp index 8ce4d0e5..8632e14c 100644 --- a/src/quicktemplates2/qquickabstractbutton.cpp +++ b/src/quicktemplates2/qquickabstractbutton.cpp @@ -178,7 +178,7 @@ void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point) if (wasPressed) { emit q->released(); - if (!wasHeld) + if (!wasHeld && !wasDoubleClick) trigger(); } else { emit q->canceled(); @@ -188,6 +188,8 @@ void QQuickAbstractButtonPrivate::handleRelease(const QPointF &point) stopPressRepeat(); else stopPressAndHold(); + + wasDoubleClick = false; } void QQuickAbstractButtonPrivate::handleUngrab() @@ -201,6 +203,7 @@ void QQuickAbstractButtonPrivate::handleUngrab() q->setPressed(false); stopPressRepeat(); stopPressAndHold(); + wasDoubleClick = false; emit q->canceled(); } @@ -1080,8 +1083,10 @@ void QQuickAbstractButton::mousePressEvent(QMouseEvent *event) void QQuickAbstractButton::mouseDoubleClickEvent(QMouseEvent *event) { + Q_D(QQuickAbstractButton); QQuickControl::mouseDoubleClickEvent(event); emit doubleClicked(); + d->wasDoubleClick = true; } void QQuickAbstractButton::timerEvent(QTimerEvent *event) diff --git a/src/quicktemplates2/qquickabstractbutton_p_p.h b/src/quicktemplates2/qquickabstractbutton_p_p.h index 8ad479e2..9291c1a8 100644 --- a/src/quicktemplates2/qquickabstractbutton_p_p.h +++ b/src/quicktemplates2/qquickabstractbutton_p_p.h @@ -124,6 +124,7 @@ public: bool autoExclusive = false; bool autoRepeat = false; bool wasHeld = false; + bool wasDoubleClick = false; int holdTimer = 0; int delayTimer = 0; int repeatTimer = 0; diff --git a/src/quicktemplates2/qquickcombobox.cpp b/src/quicktemplates2/qquickcombobox.cpp index 5f3f1cfc..d9bbd2bd 100644 --- a/src/quicktemplates2/qquickcombobox.cpp +++ b/src/quicktemplates2/qquickcombobox.cpp @@ -1865,6 +1865,14 @@ void QQuickComboBox::wheelEvent(QWheelEvent *event) } #endif +bool QQuickComboBox::event(QEvent *e) +{ + Q_D(QQuickComboBox); + if (e->type() == QEvent::LanguageChange) + d->updateCurrentText(); + return QQuickControl::event(e); +} + void QQuickComboBox::componentComplete() { Q_D(QQuickComboBox); diff --git a/src/quicktemplates2/qquickcombobox_p.h b/src/quicktemplates2/qquickcombobox_p.h index b52d7545..282f3d23 100644 --- a/src/quicktemplates2/qquickcombobox_p.h +++ b/src/quicktemplates2/qquickcombobox_p.h @@ -227,6 +227,7 @@ protected: #if QT_CONFIG(wheelevent) void wheelEvent(QWheelEvent *event) override; #endif + bool event(QEvent *e) override; void componentComplete() override; void itemChange(ItemChange change, const ItemChangeData &value) override; diff --git a/src/quicktemplates2/qquickcontrol.cpp b/src/quicktemplates2/qquickcontrol.cpp index 6b845ae6..4eb411c2 100644 --- a/src/quicktemplates2/qquickcontrol.cpp +++ b/src/quicktemplates2/qquickcontrol.cpp @@ -180,6 +180,12 @@ bool QQuickControlPrivate::acceptTouch(const QTouchEvent::TouchPoint &point) return true; } + // If the control is on a Flickable that has a pressDelay, then the press is never + // sent as a touch event, therefore we need to check for this case. + if (touchId == -1 && pressWasTouch && point.state() == Qt::TouchPointReleased && + point.pos() == previousPressPos) { + return true; + } return false; } #endif @@ -215,6 +221,8 @@ void QQuickControlPrivate::handleRelease(const QPointF &) if ((focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && QGuiApplication::styleHints()->setFocusOnTouchRelease()) setActiveFocus(q, Qt::MouseFocusReason); touchId = -1; + pressWasTouch = false; + previousPressPos = QPointF(); } void QQuickControlPrivate::handleUngrab() @@ -2121,6 +2129,10 @@ void QQuickControl::mousePressEvent(QMouseEvent *event) { Q_D(QQuickControl); d->handlePress(event->localPos()); + if (event->source() == Qt::MouseEventSynthesizedByQt) { + d->pressWasTouch = true; + d->previousPressPos = event->localPos(); + } event->accept(); } diff --git a/src/quicktemplates2/qquickcontrol_p_p.h b/src/quicktemplates2/qquickcontrol_p_p.h index b649db0a..fa06c97f 100644 --- a/src/quicktemplates2/qquickcontrol_p_p.h +++ b/src/quicktemplates2/qquickcontrol_p_p.h @@ -230,7 +230,9 @@ public: bool explicitHoverEnabled = false; #endif bool resizingBackground = false; + bool pressWasTouch = false; int touchId = -1; + QPointF previousPressPos; qreal padding = 0; qreal horizontalPadding = 0; qreal verticalPadding = 0; diff --git a/src/quicktemplates2/qquickdialogbuttonbox.cpp b/src/quicktemplates2/qquickdialogbuttonbox.cpp index 2c09cd11..f3dd2da1 100644 --- a/src/quicktemplates2/qquickdialogbuttonbox.cpp +++ b/src/quicktemplates2/qquickdialogbuttonbox.cpp @@ -455,8 +455,11 @@ void QQuickDialogButtonBoxPrivate::updateLanguage() qmlAttachedPropertiesObject<QQuickDialogButtonBox>(button, true)); const auto boxAttachedPrivate = QQuickDialogButtonBoxAttachedPrivate::get(attached); const QPlatformDialogHelper::StandardButton standardButton = boxAttachedPrivate->standardButton; - const QString buttonText = QGuiApplicationPrivate::platformTheme()->standardButtonText(standardButton); - button->setText(QPlatformTheme::removeMnemonics(buttonText)); + // The button might be a custom one with explicitly specified text, so we shouldn't change it in that case. + if (standardButton != QPlatformDialogHelper::NoButton) { + const QString buttonText = QGuiApplicationPrivate::platformTheme()->standardButtonText(standardButton); + button->setText(QPlatformTheme::removeMnemonics(buttonText)); + } } --i; } diff --git a/src/quicktemplates2/qquickheaderview.cpp b/src/quicktemplates2/qquickheaderview.cpp new file mode 100644 index 00000000..49463944 --- /dev/null +++ b/src/quicktemplates2/qquickheaderview.cpp @@ -0,0 +1,500 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtQuickTemplates2/private/qquickheaderview_p_p.h> +#include <algorithm> + +/*! + \qmltype HorizontalHeaderView + \inqmlmodule QtQuick.Controls + \ingroup qtquickcontrols2-containers + \inherits TableView + \brief Provides a horizontal header view to accompany a \l TableView. + + A HorizontalHeaderView provides labeling of the columns of a \l TableView. + To add a horizontal header to a TableView, bind the + \l {HorizontalHeaderView::syncView} {syncView} property to the TableView: + + \snippet qtquickcontrols2-headerview-simple.qml horizontal + + The header displays data from the {syncView}'s model by default, but can + also have its own model. If the model is a QAbstractTableModel, then + the header will display the model's horizontal headerData(); otherwise, + the model's data(). +*/ + +/*! + \qmltype VerticalHeaderView + \inqmlmodule QtQuick.Controls + \ingroup qtquickcontrols2-containers + \inherits TableView + \brief Provides a vertical header view to accompany a \l TableView. + + A VerticalHeaderView provides labeling of the rows of a \l TableView. + To add a vertical header to a TableView, bind the + \l {VerticalHeaderView::syncView} {syncView} property to the TableView: + + \snippet qtquickcontrols2-headerview-simple.qml vertical + + The header displays data from the {syncView}'s model by default, but can + also have its own model. If the model is a QAbstractTableModel, then + the header will display the model's vertical headerData(); otherwise, + the model's data(). +*/ + +/*! + \qmlproperty TableView QtQuick::HorizontalHeaderView::syncView + + This property holds the TableView to synchronize with. + + Once this property is bound to another TableView, both header and table + will synchronize with regard to column widths, column spacing, and flicking + horizontally. + + If the \l model is not explicitly set, then the header will use the syncView's + model to label the columns. + + \sa model TableView +*/ + +/*! + \qmlproperty TableView QtQuick::VerticalHeaderView::syncView + + This property holds the TableView to synchronize with. + + Once this property is bound to another TableView, both header and table + will synchronize with regard to row heights, row spacing, and flicking + vertically. + + If the \l model is not explicitly set, then the header will use the syncView's + model to label the rows. + + \sa model TableView +*/ + +/*! + \qmlproperty QVariant QtQuick::HorizontalHeaderView::model + + This property holds the model providing data for the horizontal header view. + + When model is not explicitly set, the header will use the syncView's + model once syncView is set. + + If model is a QAbstractTableModel, its horizontal headerData() will + be accessed. + + If model is a QAbstractItemModel other than QAbstractTableModel, model's data() + will be accessed. + + Otherwise, the behavior is same as setting TableView::model. + + \sa TableView {TableView::model} {model} QAbstractTableModel +*/ + +/*! + \qmlproperty QVariant QtQuick::VerticalHeaderView::model + + This property holds the model providing data for the vertical header view. + + When model is not explicitly set, it will be synchronized with syncView's model + once syncView is set. + + If model is a QAbstractTableModel, its vertical headerData() will + be accessed. + + If model is a QAbstractItemModel other than QAbstractTableModel, model's data() + will be accessed. + + Otherwise, the behavior is same as setting TableView::model. + + \sa TableView {TableView::model} {model} QAbstractTableModel +*/ + +/*! + \qmlproperty QString QtQuick::HorizontalHeaderView::textRole + + This property holds the model role used to display text in each header cell. + + The default value is the \c "display" role. + + \sa QAbstractItemModel::roleNames() +*/ + +/*! + \qmlproperty QString QtQuick::VerticalHeaderView::textRole + + This property holds the model role used to display text in each header cell. + + The default value is the \c "display" role. + + \sa QAbstractItemModel::roleNames() +*/ + +QT_BEGIN_NAMESPACE + +QQuickHeaderViewBasePrivate::QQuickHeaderViewBasePrivate() + : QQuickTableViewPrivate() +{ +} + +QQuickHeaderViewBasePrivate::~QQuickHeaderViewBasePrivate() +{ +} + +const QPointer<QQuickItem> QQuickHeaderViewBasePrivate::delegateItemAt(int row, int col) const +{ + return loadedTableItem(QPoint(col, row))->item; +} + +QVariant QQuickHeaderViewBasePrivate::modelImpl() const +{ + if (auto model = m_headerDataProxyModel.sourceModel()) + return QVariant::fromValue(model.data()); + if (auto model = m_transposeProxyModel.sourceModel()) + return QVariant::fromValue(model); + return QQuickTableViewPrivate::modelImpl(); +} + +template <typename P, typename M> +inline bool proxyModelSetter(QQuickHeaderViewBase *const q, P &proxyModel, M *model) +{ + if (model) { + if (model == proxyModel.sourceModel()) + return true; + proxyModel.setSourceModel(model); + const auto &modelVariant = QVariant::fromValue(std::addressof(proxyModel)); + bool isProxyModelChanged = (modelVariant != QQuickTableViewPrivate::get(q)->QQuickTableViewPrivate::modelImpl()); + QQuickTableViewPrivate::get(q)->QQuickTableViewPrivate::setModelImpl(modelVariant); + //Necessary, since TableView's assigned model not changed, but proxy's source changed + if (!isProxyModelChanged) + emit q->modelChanged(); + return true; + } + proxyModel.setSourceModel(nullptr); + return false; +} + +void QQuickHeaderViewBasePrivate::setModelImpl(const QVariant &newModel) +{ + Q_Q(QQuickHeaderViewBase); + m_modelExplicitlySetByUser = true; + // Case 1: newModel is QAbstractTableModel + if (proxyModelSetter(q, m_headerDataProxyModel, newModel.value<QAbstractTableModel *>())) + return; + // Case 2: newModel is QAbstractItemModel but not QAbstractTableModel + if (orientation() == Qt::Horizontal + && proxyModelSetter(q, m_transposeProxyModel, newModel.value<QAbstractItemModel *>())) + return; + + QQuickTableViewPrivate::setModelImpl(newModel); +} + +void QQuickHeaderViewBasePrivate::syncModel() +{ + Q_Q(QQuickHeaderViewBase); + if (assignedSyncView && !m_modelExplicitlySetByUser) { + auto newModel = assignedSyncView->model(); + if (auto m = newModel.value<QAbstractTableModel *>()) { + proxyModelSetter(q, m_headerDataProxyModel, m); + } else if (orientation() == Qt::Horizontal) { + if (auto m = newModel.value<QAbstractItemModel *>()) + proxyModelSetter(q, m_transposeProxyModel, m); + } else { + QQuickTableViewPrivate::setModelImpl(newModel); + } + } + + QQuickTableViewPrivate::syncModel(); +} + +void QQuickHeaderViewBasePrivate::syncSyncView() +{ + Q_Q(QQuickHeaderViewBase); + if (assignedSyncDirection != orientation()) { + qmlWarning(q_func()) << "Setting syncDirection other than Qt::" + << QVariant::fromValue(orientation()).toString() + << " is invalid."; + assignedSyncDirection = orientation(); + } + if (assignedSyncView) { + QBoolBlocker fixupGuard(inUpdateContentSize, true); + if (orientation() == Qt::Horizontal) { + q->setLeftMargin(assignedSyncView->leftMargin()); + q->setRightMargin(assignedSyncView->rightMargin()); + } else { + q->setTopMargin(assignedSyncView->topMargin()); + q->setBottomMargin(assignedSyncView->bottomMargin()); + } + } + QQuickTableViewPrivate::syncSyncView(); +} + +QQuickHeaderViewBase::QQuickHeaderViewBase(Qt::Orientation orient, QQuickItem *parent) + : QQuickTableView(*(new QQuickHeaderViewBasePrivate), parent) +{ + d_func()->setOrientation(orient); + setSyncDirection(orient); +} + +QQuickHeaderViewBase::QQuickHeaderViewBase(QQuickHeaderViewBasePrivate &dd, QQuickItem *parent) + : QQuickTableView(dd, parent) +{ +} + +QQuickHeaderViewBase::~QQuickHeaderViewBase() +{ +} + +QString QQuickHeaderViewBase::textRole() const +{ + Q_D(const QQuickHeaderViewBase); + return d->m_textRole; +} + +void QQuickHeaderViewBase::setTextRole(const QString &role) +{ + Q_D(QQuickHeaderViewBase); + if (d->m_textRole == role) + return; + + d->m_textRole = role; + emit textRoleChanged(); +} + +Qt::Orientation QQuickHeaderViewBasePrivate::orientation() const +{ + return m_headerDataProxyModel.orientation(); +} + +void QQuickHeaderViewBasePrivate::setOrientation(Qt::Orientation orientation) +{ + if (QQuickHeaderViewBasePrivate::orientation() == orientation) + return; + m_headerDataProxyModel.setOrientation(orientation); +} + +QQuickVerticalHeaderView::QQuickVerticalHeaderView(QQuickVerticalHeaderViewPrivate &dd, QQuickItem *parent) + : QQuickHeaderViewBase(dd, parent) +{ +} + +/*! \internal + \class QHeaderDataProxyModel + \brief + QHeaderDataProxyModel is a proxy AbstractItemModel type that maps + source model's headerData() to correspondent data() + */ +QHeaderDataProxyModel::QHeaderDataProxyModel(QObject *parent) + : QAbstractItemModel(parent) +{ +} + +QHeaderDataProxyModel::~QHeaderDataProxyModel() = default; + +void QHeaderDataProxyModel::setSourceModel(QAbstractItemModel *newSourceModel) +{ + if (m_model == newSourceModel) + return; + beginResetModel(); + disconnectFromModel(); + m_model = newSourceModel; + connectToModel(); + endResetModel(); +} + +QModelIndex QHeaderDataProxyModel::index(int row, int column, const QModelIndex &parent) const +{ + return hasIndex(row, column, parent) ? createIndex(row, column) : QModelIndex(); +} + +QModelIndex QHeaderDataProxyModel::parent(const QModelIndex &child) const +{ + Q_UNUSED(child) + return QModelIndex(); +} + +QModelIndex QHeaderDataProxyModel::sibling(int row, int column, const QModelIndex &idx) const +{ + return index(row, column, idx); +} + +int QHeaderDataProxyModel::rowCount(const QModelIndex &parent) const +{ + return m_model.isNull() ? -1 : (m_orientation == Qt::Horizontal ? 1 : m_model->rowCount(parent)); +} + +int QHeaderDataProxyModel::columnCount(const QModelIndex &parent) const +{ + return m_model.isNull() ? -1 : (m_orientation == Qt::Vertical ? 1 : m_model->columnCount(parent)); +} + +QVariant QHeaderDataProxyModel::data(const QModelIndex &index, int role) const +{ + if (m_model.isNull()) + return QVariant(); + if (!hasIndex(index.row(), index.column())) + return QModelIndex(); + auto section = m_orientation == Qt::Vertical ? index.row() : index.column(); + return m_model->headerData(section, m_orientation, role); +} + +bool QHeaderDataProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + if (!hasIndex(index.row(), index.column())) + return false; + auto section = m_orientation == Qt::Vertical ? index.row() : index.column(); + auto ret = m_model->setHeaderData(section, m_orientation, value, role); + emit dataChanged(index, index, { role }); + return ret; +} + +bool QHeaderDataProxyModel::hasChildren(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return false; +} + +QVariant QHeaderDataProxyModel::variantValue() const +{ + return QVariant::fromValue(static_cast<QObject *>(const_cast<QHeaderDataProxyModel *>(this))); +} + +void QHeaderDataProxyModel::setOrientation(Qt::Orientation o) +{ + if (o == m_orientation) + return; + beginResetModel(); + m_orientation = o; + endResetModel(); +} + +Qt::Orientation QHeaderDataProxyModel::orientation() const +{ + return m_orientation; +} + +QPointer<QAbstractItemModel> QHeaderDataProxyModel::sourceModel() const +{ + return m_model; +} + +void QHeaderDataProxyModel::connectToModel() +{ + if (m_model.isNull()) + return; + connect(m_model, &QAbstractItemModel::headerDataChanged, + [this](Qt::Orientation orient, int first, int last) { + if (orient != orientation()) + return; + if (orient == Qt::Horizontal) { + emit dataChanged(createIndex(0, first), createIndex(0, last)); + } else { + emit dataChanged(createIndex(first, 0), createIndex(last, 0)); + } + }); + connect(m_model, &QAbstractItemModel::modelAboutToBeReset, + this, &QHeaderDataProxyModel::modelAboutToBeReset, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::modelReset, + this, &QHeaderDataProxyModel::modelReset, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsAboutToBeMoved, + this, &QHeaderDataProxyModel::rowsAboutToBeMoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsMoved, + this, &QHeaderDataProxyModel::rowsMoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsAboutToBeInserted, + this, &QHeaderDataProxyModel::rowsAboutToBeInserted, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsInserted, + this, &QHeaderDataProxyModel::rowsInserted, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsAboutToBeRemoved, + this, &QHeaderDataProxyModel::rowsAboutToBeRemoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::rowsRemoved, + this, &QHeaderDataProxyModel::rowsRemoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsAboutToBeMoved, + this, &QHeaderDataProxyModel::columnsAboutToBeMoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsMoved, + this, &QHeaderDataProxyModel::columnsMoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsAboutToBeInserted, + this, &QHeaderDataProxyModel::columnsAboutToBeInserted, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsInserted, + this, &QHeaderDataProxyModel::columnsInserted, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsAboutToBeRemoved, + this, &QHeaderDataProxyModel::columnsAboutToBeRemoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::columnsRemoved, + this, &QHeaderDataProxyModel::columnsRemoved, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::layoutAboutToBeChanged, + this, &QHeaderDataProxyModel::layoutAboutToBeChanged, Qt::UniqueConnection); + connect(m_model, &QAbstractItemModel::layoutChanged, + this, &QHeaderDataProxyModel::layoutChanged, Qt::UniqueConnection); +} + +void QHeaderDataProxyModel::disconnectFromModel() +{ + if (m_model.isNull()) + return; + m_model->disconnect(this); +} + +QQuickHorizontalHeaderView::QQuickHorizontalHeaderView(QQuickItem *parent) + : QQuickHeaderViewBase(Qt::Horizontal, parent) +{ + setFlickableDirection(FlickableDirection::HorizontalFlick); +} + +QQuickHorizontalHeaderView::~QQuickHorizontalHeaderView() +{ +} + +QQuickVerticalHeaderView::QQuickVerticalHeaderView(QQuickItem *parent) + : QQuickHeaderViewBase(Qt::Vertical, parent) +{ + setFlickableDirection(FlickableDirection::VerticalFlick); +} + +QQuickVerticalHeaderView::~QQuickVerticalHeaderView() +{ +} + +QQuickHorizontalHeaderViewPrivate::QQuickHorizontalHeaderViewPrivate() = default; + +QQuickHorizontalHeaderViewPrivate::~QQuickHorizontalHeaderViewPrivate() = default; + +QQuickVerticalHeaderViewPrivate::QQuickVerticalHeaderViewPrivate() = default; + +QQuickVerticalHeaderViewPrivate::~QQuickVerticalHeaderViewPrivate() = default; + +QT_END_NAMESPACE diff --git a/src/quicktemplates2/qquickheaderview_p.h b/src/quicktemplates2/qquickheaderview_p.h new file mode 100644 index 00000000..10c55c6e --- /dev/null +++ b/src/quicktemplates2/qquickheaderview_p.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKHEADERVIEW_P_H +#define QQUICKHEADERVIEW_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <private/qquicktableview_p.h> +#include <private/qtquicktemplates2global_p.h> + +QT_BEGIN_NAMESPACE + +class QQuickHeaderViewBase; +class QQuickHeaderViewBasePrivate; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickHeaderViewBase : public QQuickTableView +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickHeaderViewBase) + Q_PROPERTY(QString textRole READ textRole WRITE setTextRole NOTIFY textRoleChanged FINAL) + +public: + explicit QQuickHeaderViewBase(Qt::Orientation orient, QQuickItem *parent = nullptr); + ~QQuickHeaderViewBase(); + + QString textRole() const; + void setTextRole(const QString &role); + +protected: + QQuickHeaderViewBase(QQuickHeaderViewBasePrivate &dd, QQuickItem *parent); + +Q_SIGNALS: + void textRoleChanged(); + +private: + Q_DISABLE_COPY(QQuickHeaderViewBase) + friend class QQuickHorizontalHeaderView; + friend class QQuickVerticalHeaderView; +}; + +class QQuickHorizontalHeaderViewPrivate; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickHorizontalHeaderView : public QQuickHeaderViewBase +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickHorizontalHeaderView) + +public: + QQuickHorizontalHeaderView(QQuickItem *parent = nullptr); + ~QQuickHorizontalHeaderView() override; + +protected: + QQuickHorizontalHeaderView(QQuickHorizontalHeaderViewPrivate &dd, QQuickItem *parent); + +private: + Q_DISABLE_COPY(QQuickHorizontalHeaderView) +}; + +class QQuickVerticalHeaderViewPrivate; +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickVerticalHeaderView : public QQuickHeaderViewBase +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QQuickVerticalHeaderView) + +public: + QQuickVerticalHeaderView(QQuickItem *parent = nullptr); + ~QQuickVerticalHeaderView() override; + +protected: + QQuickVerticalHeaderView(QQuickVerticalHeaderViewPrivate &dd, QQuickItem *parent); + +private: + Q_DISABLE_COPY(QQuickVerticalHeaderView) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickHorizontalHeaderView) +QML_DECLARE_TYPE(QQuickVerticalHeaderView) + +#endif // QQUICKHEADERVIEW_P_H diff --git a/src/quicktemplates2/qquickheaderview_p_p.h b/src/quicktemplates2/qquickheaderview_p_p.h new file mode 100644 index 00000000..961c554b --- /dev/null +++ b/src/quicktemplates2/qquickheaderview_p_p.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKHEADERVIEW_P_P_H +#define QQUICKHEADERVIEW_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QAbstractItemModel> +#include <QtCore/QPointer> +#include <QtCore/QTransposeProxyModel> +#include <QtQuick/private/qquicktableview_p_p.h> +#include <private/qquickheaderview_p.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QHeaderDataProxyModel : public QAbstractItemModel +{ + Q_OBJECT + Q_DISABLE_COPY(QHeaderDataProxyModel) + Q_PROPERTY(QAbstractItemModel *sourceModel READ sourceModel) +public: + explicit QHeaderDataProxyModel(QObject *parent = nullptr); + ~QHeaderDataProxyModel(); + + void setSourceModel(QAbstractItemModel *newSourceModel); + QPointer<QAbstractItemModel> sourceModel() const; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &child) const override; + QModelIndex sibling(int row, int column, const QModelIndex &idx) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + bool hasChildren(const QModelIndex &parent = QModelIndex()) const override; + + inline QVariant variantValue() const; + inline Qt::Orientation orientation() const; + inline void setOrientation(Qt::Orientation o); + +private: + inline void connectToModel(); + inline void disconnectFromModel(); + QPointer<QAbstractItemModel> m_model = nullptr; + Qt::Orientation m_orientation = Qt::Horizontal; +}; + +class QQuickHeaderViewBasePrivate : public QQuickTableViewPrivate +{ + Q_DECLARE_PUBLIC(QQuickHeaderViewBase) +public: + QQuickHeaderViewBasePrivate(); + ~QQuickHeaderViewBasePrivate(); + + Qt::Orientation orientation() const; + void setOrientation(Qt::Orientation orientation); + const QPointer<QQuickItem> delegateItemAt(int row, int col) const; + QVariant modelImpl() const override; + void setModelImpl(const QVariant &newModel) override; + void syncModel() override; + void syncSyncView() override; + +protected: + QHeaderDataProxyModel m_headerDataProxyModel; + QTransposeProxyModel m_transposeProxyModel; + struct SectionSize + { + int section; + qreal previousSize; + }; + QStack<SectionSize> m_hiddenSectionSizes; + bool m_modelExplicitlySetByUser = false; + QString m_textRole = QStringLiteral("display"); +}; + +class QQuickHorizontalHeaderViewPrivate : public QQuickHeaderViewBasePrivate +{ + Q_DECLARE_PUBLIC(QQuickHorizontalHeaderView) +public: + QQuickHorizontalHeaderViewPrivate(); + ~QQuickHorizontalHeaderViewPrivate(); +}; + +class QQuickVerticalHeaderViewPrivate : public QQuickHeaderViewBasePrivate +{ + Q_DECLARE_PUBLIC(QQuickVerticalHeaderView) +public: + QQuickVerticalHeaderViewPrivate(); + ~QQuickVerticalHeaderViewPrivate(); +}; + +QT_END_NAMESPACE + +#endif // QQUICKHEADERVIEW_P_P_H diff --git a/src/quicktemplates2/qquicktooltip.cpp b/src/quicktemplates2/qquicktooltip.cpp index 9ea0160e..8b61375e 100644 --- a/src/quicktemplates2/qquicktooltip.cpp +++ b/src/quicktemplates2/qquicktooltip.cpp @@ -252,9 +252,18 @@ void QQuickToolTip::setVisible(bool visible) { Q_D(QQuickToolTip); if (visible) { - if (!d->visible && d->delay > 0) { - d->startDelay(); - return; + if (!d->visible) { + // We are being made visible, and we weren't before. + if (d->delay > 0) { + d->startDelay(); + return; + } + } else { + // We are being made visible, even though we already were. + // We've probably been re-opened before our exit transition could finish. + // In that case, we need to manually start the timeout, as that is usually + // done in itemChange(), which won't be called in this situation. + d->startTimeout(); } } else { d->stopDelay(); @@ -557,8 +566,9 @@ void QQuickToolTipAttached::hide() QQuickToolTip *tip = d->instance(false); if (!tip) return; - - tip->close(); + // check the parent item to prevent unexpectedly closing tooltip by new created invisible tooltip + if (parent() == tip->parentItem()) + tip->close(); } QT_END_NAMESPACE diff --git a/src/quicktemplates2/quicktemplates2.pri b/src/quicktemplates2/quicktemplates2.pri index c145c20f..fa6929f9 100644 --- a/src/quicktemplates2/quicktemplates2.pri +++ b/src/quicktemplates2/quicktemplates2.pri @@ -31,6 +31,8 @@ HEADERS += \ $$PWD/qquickframe_p.h \ $$PWD/qquickframe_p_p.h \ $$PWD/qquickgroupbox_p.h \ + $$PWD/qquickheaderview_p.h \ + $$PWD/qquickheaderview_p_p.h \ $$PWD/qquickicon_p.h \ $$PWD/qquickitemdelegate_p.h \ $$PWD/qquickitemdelegate_p_p.h \ @@ -120,6 +122,7 @@ SOURCES += \ $$PWD/qquickdrawer.cpp \ $$PWD/qquickframe.cpp \ $$PWD/qquickgroupbox.cpp \ + $$PWD/qquickheaderview.cpp \ $$PWD/qquickicon.cpp \ $$PWD/qquickitemdelegate.cpp \ $$PWD/qquicklabel.cpp \ |