summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swift/QtUI')
-rw-r--r--Swift/QtUI/QtChatOverviewBundle.cpp22
-rw-r--r--Swift/QtUI/QtChatOverviewBundle.h5
-rw-r--r--Swift/QtUI/QtExpandedListView.cpp109
-rw-r--r--Swift/QtUI/QtExpandedListView.h34
-rw-r--r--Swift/QtUI/SConscript1
5 files changed, 149 insertions, 22 deletions
diff --git a/Swift/QtUI/QtChatOverviewBundle.cpp b/Swift/QtUI/QtChatOverviewBundle.cpp
index bf99b0c..8505541 100644
--- a/Swift/QtUI/QtChatOverviewBundle.cpp
+++ b/Swift/QtUI/QtChatOverviewBundle.cpp
@@ -9,7 +9,6 @@
#include <QDebug>
#include <QHBoxLayout>
#include <QLabel>
-#include <QListView>
#include <QPalette>
#include <QSortFilterProxyModel>
#include <QVBoxLayout>
@@ -19,6 +18,7 @@
#include <Swift/QtUI/ChattablesModel.h>
#include <Swift/QtUI/QtChatOverviewDelegate.h>
#include <Swift/QtUI/QtClickableLabel.h>
+#include <Swift/QtUI/QtExpandedListView.h>
#include <Swift/QtUI/QtSwiftUtil.h>
namespace Swift {
@@ -100,34 +100,16 @@ QtChatOverviewBundle::QtChatOverviewBundle(ChattablesModel* rootModel, QString n
headerLayout->addWidget(filterLabel_);
connect(filterLabel_, SIGNAL(clicked()), this, SLOT(handleFilterClicked()));
}
- listView_ = new QListView(this);
+ listView_ = new QtExpandedListView(this);
listView_->setModel(proxyModel_);
listView_->setFrameStyle(QFrame::NoFrame);
listView_->setItemDelegate(new QtChatOverviewDelegate(this));
connect(listView_, SIGNAL(clicked(const QModelIndex&)), this, SLOT(handleItemClicked(const QModelIndex&)));
- recalculateSize();
mainLayout->addWidget(listView_);
- connect(proxyModel_, SIGNAL(rowsInserted(const QModelIndex&, int, int)), this, SLOT(recalculateSize()));
- connect(proxyModel_, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), this, SLOT(recalculateSize()));
- connect(proxyModel_, SIGNAL(modelReset()), this, SLOT(recalculateSize()));
}
QtChatOverviewBundle::~QtChatOverviewBundle() {}
-void QtChatOverviewBundle::recalculateSize() {
- int totalHeight = 0;
- for (int i = 0; i < proxyModel_->rowCount(); i++) {
- totalHeight += listView_->sizeHintForRow(i);
- }
- listView_->setFixedHeight(totalHeight);
- if (hideWhenEmpty_ && totalHeight == 0) {
- hide();
- }
- else {
- show();
- }
-}
-
void QtChatOverviewBundle::handleFilterClicked() {
if (proxyModel_->hasFilter(BundleFilter::Filter::Online)) {
proxyModel_->removeFilter(BundleFilter::Filter::Online);
diff --git a/Swift/QtUI/QtChatOverviewBundle.h b/Swift/QtUI/QtChatOverviewBundle.h
index f469fea..6e232ca 100644
--- a/Swift/QtUI/QtChatOverviewBundle.h
+++ b/Swift/QtUI/QtChatOverviewBundle.h
@@ -19,6 +19,7 @@ class QListView;
namespace Swift {
class ChattablesModel;
class QtClickableLabel;
+ class QtExpandedListView;
class BundleFilter : public QSortFilterProxyModel {
Q_OBJECT
@@ -44,12 +45,12 @@ namespace Swift {
void clicked(JID jid);
private slots:
- void recalculateSize();
void handleFilterClicked();
void handleItemClicked(const QModelIndex&);
+
private:
ChattablesModel* rootModel_;
- QListView* listView_;
+ QtExpandedListView* listView_;
BundleFilter* proxyModel_;
bool hideWhenEmpty_;
QtClickableLabel* filterLabel_ = nullptr;
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);
+}
+
+}
diff --git a/Swift/QtUI/QtExpandedListView.h b/Swift/QtUI/QtExpandedListView.h
new file mode 100644
index 0000000..df78376
--- /dev/null
+++ b/Swift/QtUI/QtExpandedListView.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <QListView>
+
+namespace Swift {
+
+class QtExpandedListView : public QListView {
+public:
+ QtExpandedListView(QWidget* parent);
+ ~QtExpandedListView() override;
+
+ void setModel(QAbstractItemModel* model) override;
+ bool viewportEvent(QEvent* event) override;
+ QSize minimumSizeHint() const override;
+ QSize sizeHint() const override;
+
+protected slots:
+ void currentChanged(const QModelIndex &current, const QModelIndex &previous) override;
+
+private slots:
+ void adjustHeightToModelChange();
+
+private:
+ void connectToModel(QAbstractItemModel* model);
+ void disconnectFromModel(QAbstractItemModel* model);
+};
+
+}
diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript
index e61bdcf..b8ec3ba 100644
--- a/Swift/QtUI/SConscript
+++ b/Swift/QtUI/SConscript
@@ -169,6 +169,7 @@ sources = [
"QtEmojisScroll.cpp",
"QtEmojisSelector.cpp",
"QtEmoticonsGrid.cpp",
+ "QtExpandedListView.cpp",
"QtFileTransferListItemModel.cpp",
"QtFileTransferListWidget.cpp",
"QtFormResultItemModel.cpp",