diff options
Diffstat (limited to 'Swift/QtUI/QtExpandedListView.cpp')
-rw-r--r-- | Swift/QtUI/QtExpandedListView.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/Swift/QtUI/QtExpandedListView.cpp b/Swift/QtUI/QtExpandedListView.cpp new file mode 100644 index 0000000..8cbfab6 --- /dev/null +++ b/Swift/QtUI/QtExpandedListView.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swift/QtUI/QtExpandedListView.h> + +#include <QWheelEvent> +#include <QScrollArea> + +namespace Swift { + +QtExpandedListView::QtExpandedListView(QWidget* parent) : QListView(parent) { + // Disable macOS focus rectangle due to bad performance. + setAttribute(Qt::WA_MacShowFocusRect, 0); + setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed); +} + +void QtExpandedListView::setModel(QAbstractItemModel* newModel) { + if (model()) { + disconnectFromModel(model()); + } + if (newModel) { + connectToModel(newModel); + } + QListView::setModel(newModel); + adjustHeightToModelChange(); +} + +QtExpandedListView::~QtExpandedListView() { + if (model()) { + disconnectFromModel(model()); + } +} + +bool QtExpandedListView::viewportEvent(QEvent* event) { + // Ignore wheel events for faster mouse scrolling. + if (event && event->type() == QEvent::Wheel) { + return false; + } + + return QListView::viewportEvent(event); +} + +template <typename T> +T getParentOfType(QWidget* start) { + auto parentW = start->parentWidget(); + if (parentW == nullptr) { + return nullptr; + } + T result = dynamic_cast<T>(parentW); + if (result) { + return result; + } + return getParentOfType<T>(parentW); +} + +void QtExpandedListView::currentChanged(const QModelIndex ¤t, const QModelIndex &) { + // Make sure that the current selected index is visible in the parent QScrollArea. + auto scrollArea = getParentOfType<QScrollArea*>(parentWidget()); + if (scrollArea) { + QList<QPoint> points; + auto visRect = visualRect(current); + points << pos() + visRect.topLeft(); + points << pos() + visRect.topRight(); + points << pos() + visRect.bottomLeft(); + points << pos() + visRect.bottomRight(); + + for (auto&& point : points) { + scrollArea->ensureVisible(point.x(), point.y(), 0, 0); + } + } +} + +void QtExpandedListView::adjustHeightToModelChange() { + updateGeometry(); +} + +QSize QtExpandedListView::minimumSizeHint() const { + auto sh = sizeHint(); + return QSize(0, sh.height()); +} + +QSize QtExpandedListView::sizeHint() const { + auto listViewSH = QListView::sizeHint(); + if (model()) { + auto lastRect = rectForIndex(model()->index(model()->rowCount()-1, 0, rootIndex())); + auto idealHeight = lastRect.y() + lastRect.height() + frameWidth() * 2; + listViewSH.setHeight(idealHeight); + } + return listViewSH; +} + +void QtExpandedListView::connectToModel(QAbstractItemModel* model) { + connect(model, &QAbstractItemModel::dataChanged, this, &QtExpandedListView::adjustHeightToModelChange); + connect(model, &QAbstractItemModel::modelReset, this, &QtExpandedListView::adjustHeightToModelChange); + connect(model, &QAbstractItemModel::rowsInserted, this, &QtExpandedListView::adjustHeightToModelChange); + connect(model, &QAbstractItemModel::rowsRemoved, this, &QtExpandedListView::adjustHeightToModelChange); +} + +void QtExpandedListView::disconnectFromModel(QAbstractItemModel* model) { + disconnect(model, &QAbstractItemModel::dataChanged, this, &QtExpandedListView::adjustHeightToModelChange); + disconnect(model, &QAbstractItemModel::modelReset, this, &QtExpandedListView::adjustHeightToModelChange); + disconnect(model, &QAbstractItemModel::rowsInserted, this, &QtExpandedListView::adjustHeightToModelChange); + disconnect(model, &QAbstractItemModel::rowsRemoved, this, &QtExpandedListView::adjustHeightToModelChange); +} + +} |