summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/QtUI/QtExpandedListView.cpp')
-rw-r--r--Swift/QtUI/QtExpandedListView.cpp109
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 &current, 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);
+}
+
+}