diff --git a/CMakeLists.txt b/CMakeLists.txt
index aa81f285..7e68db77 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -492,6 +492,7 @@ qt5_wrap_cpp(MOC_HEADERS
src/ChatPage.h
src/CommunitiesList.h
src/CommunitiesListItem.h
+ src/CompletionProxyModel.h
src/DeviceVerificationFlow.h
src/InviteeItem.h
src/LoginPage.h
@@ -508,6 +509,7 @@ qt5_wrap_cpp(MOC_HEADERS
src/TrayIcon.h
src/UserInfoWidget.h
src/UserSettingsPage.h
+ src/UsersModel.h
src/WebRTCSession.h
src/WelcomePage.h
src/popups/PopupItem.h
diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml
index d53eae62..2c520dec 100644
--- a/resources/qml/Completer.qml
+++ b/resources/qml/Completer.qml
@@ -34,11 +34,17 @@ Popup {
onCompleterNameChanged: {
if (completerName)
completer = TimelineManager.timeline.input.completerFor(completerName);
-
+ else
+ completer = undefined;
}
padding: 0
onAboutToShow: currentIndex = -1
+ Connections {
+ onTimelineChanged: completer = null
+ target: TimelineManager
+ }
+
ColumnLayout {
anchors.fill: parent
spacing: 0
diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index a4a47a3e..50ff7324 100644
--- a/resources/qml/MessageInput.qml
+++ b/resources/qml/MessageInput.qml
@@ -77,14 +77,13 @@ Rectangle {
onTextChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text)
onCursorPositionChanged: {
TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text);
- if (cursorPosition < completerTriggeredAt) {
+ if (cursorPosition <= completerTriggeredAt) {
completerTriggeredAt = -1;
popup.close();
}
}
onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text)
onSelectionEndChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text)
- // Ensure that we get escape key press events first.
Keys.onShortcutOverride: event.accepted = (completerTriggeredAt != -1 && (event.key === Qt.Key_Escape || event.key === Qt.Key_Tab || event.key === Qt.Key_Enter))
Keys.onPressed: {
if (event.matches(StandardKey.Paste)) {
@@ -97,18 +96,20 @@ Rectangle {
} else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) {
textArea.text = TimelineManager.timeline.input.nextText();
} else if (event.key == Qt.Key_At) {
- completerTriggeredAt = cursorPosition + 1;
+ completerTriggeredAt = cursorPosition;
popup.completerName = "user";
popup.open();
} else if (event.key == Qt.Key_Escape && popup.opened) {
completerTriggeredAt = -1;
+ popup.completerName = "";
event.accepted = true;
popup.close();
} else if (event.matches(StandardKey.InsertParagraphSeparator) && popup.opened) {
var currentCompletion = popup.currentCompletion();
+ popup.completerName = "";
popup.close();
if (currentCompletion) {
- textArea.remove(completerTriggeredAt - 1, cursorPosition);
+ textArea.remove(completerTriggeredAt, cursorPosition);
textArea.insert(cursorPosition, currentCompletion);
event.accepted = true;
return ;
@@ -129,6 +130,17 @@ Rectangle {
}
}
+ Connections {
+ onTimelineChanged: {
+ textArea.clear();
+ textArea.append(TimelineManager.timeline.input.text());
+ textArea.completerTriggeredAt = -1;
+ popup.completerName = "";
+ }
+ target: TimelineManager
+ }
+ // Ensure that we get escape key press events first.
+
Completer {
id: popup
diff --git a/src/CompletionModel.h b/src/CompletionModel.h
deleted file mode 100644
index ed021051..00000000
--- a/src/CompletionModel.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-// Class for showing a limited amount of completions at a time
-
-#include <QSortFilterProxyModel>
-
-class CompletionModel : public QSortFilterProxyModel
-{
-public:
- CompletionModel(QAbstractItemModel *model, QObject *parent = nullptr)
- : QSortFilterProxyModel(parent)
- {
- setSourceModel(model);
- }
- int rowCount(const QModelIndex &parent) const override
- {
- auto row_count = QSortFilterProxyModel::rowCount(parent);
- return (row_count < 7) ? row_count : 7;
- }
-};
diff --git a/src/CompletionModelRoles.h b/src/CompletionModelRoles.h
index bd6c4114..7c7307d3 100644
--- a/src/CompletionModelRoles.h
+++ b/src/CompletionModelRoles.h
@@ -10,6 +10,6 @@ enum Roles
{
CompletionRole = Qt::UserRole * 2, // The string to replace the active completion
SearchRole, // String completer uses for search
+ SearchRole2, // Secondary string completer uses for search
};
-
}
diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h
index ee38075e..757aa990 100644
--- a/src/CompletionProxyModel.h
+++ b/src/CompletionProxyModel.h
@@ -4,17 +4,36 @@
#include <QSortFilterProxyModel>
+#include "CompletionModelRoles.h"
+
class CompletionProxyModel : public QSortFilterProxyModel
{
+ Q_OBJECT
+
public:
CompletionProxyModel(QAbstractItemModel *model, QObject *parent = nullptr)
: QSortFilterProxyModel(parent)
{
setSourceModel(model);
}
- int rowCount(const QModelIndex &parent) const override
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return this->sourceModel()->roleNames();
+ }
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
auto row_count = QSortFilterProxyModel::rowCount(parent);
return (row_count < 7) ? row_count : 7;
}
+
+public slots:
+ QVariant completionAt(int i) const
+ {
+ if (i >= 0 && i < rowCount())
+ return data(index(i, 0), CompletionModel::CompletionRole);
+ else
+ return {};
+ }
};
diff --git a/src/UsersModel.cpp b/src/UsersModel.cpp
index c63292bb..f102cff1 100644
--- a/src/UsersModel.cpp
+++ b/src/UsersModel.cpp
@@ -3,12 +3,23 @@
#include "Cache.h"
#include "CompletionModelRoles.h"
-#include <QPixmap>
-
UsersModel::UsersModel(const std::string &roomId, QObject *parent)
: QAbstractListModel(parent)
+ , room_id(roomId)
+{
+ roomMembers_ = cache::roomMembers(roomId);
+}
+
+QHash<int, QByteArray>
+UsersModel::roleNames() const
{
- roomMembers_ = cache::getMembers(roomId, 0, 9999);
+ return {
+ {CompletionModel::CompletionRole, "completionRole"},
+ {CompletionModel::SearchRole, "searchRole"},
+ {CompletionModel::SearchRole2, "searchRole2"},
+ {Roles::DisplayName, "displayName"},
+ {Roles::AvatarUrl, "avatarUrl"},
+ };
}
QVariant
@@ -19,9 +30,14 @@ UsersModel::data(const QModelIndex &index, int role) const
case CompletionModel::CompletionRole:
case CompletionModel::SearchRole:
case Qt::DisplayRole:
- return roomMembers_[index.row()].display_name;
- case Avatar:
- return roomMembers_[index.row()].avatar;
+ case Roles::DisplayName:
+ return QString::fromStdString(
+ cache::displayName(room_id, roomMembers_[index.row()]));
+ case CompletionModel::SearchRole2:
+ return QString::fromStdString(roomMembers_[index.row()]);
+ case Roles::AvatarUrl:
+ return cache::avatarUrl(QString::fromStdString(room_id),
+ QString::fromStdString(roomMembers_[index.row()]));
}
}
return {};
diff --git a/src/UsersModel.h b/src/UsersModel.h
index 09ccbf25..6ee8261f 100644
--- a/src/UsersModel.h
+++ b/src/UsersModel.h
@@ -2,23 +2,25 @@
#include <QAbstractListModel>
-class RoomMember;
-
class UsersModel : public QAbstractListModel
{
public:
enum Roles
{
- Avatar = Qt::UserRole // QImage avatar
+ AvatarUrl = Qt::UserRole,
+ DisplayName,
};
UsersModel(const std::string &roomId, QObject *parent = nullptr);
+ QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override
{
- return (parent == QModelIndex()) ? roomMembers_.size() : 0;
+ (void)parent;
+ return roomMembers_.size();
}
QVariant data(const QModelIndex &index, int role) const override;
private:
- std::vector<RoomMember> roomMembers_;
+ std::string room_id;
+ std::vector<std::string> roomMembers_;
};
diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp
index 82649faa..641d8379 100644
--- a/src/timeline/InputBar.cpp
+++ b/src/timeline/InputBar.cpp
@@ -14,12 +14,14 @@
#include "Cache.h"
#include "CallManager.h"
#include "ChatPage.h"
+#include "CompletionProxyModel.h"
#include "Logging.h"
#include "MainWindow.h"
#include "MatrixClient.h"
#include "Olm.h"
#include "TimelineModel.h"
#include "UserSettingsPage.h"
+#include "UsersModel.h"
#include "Utils.h"
#include "dialogs/PlaceCall.h"
#include "dialogs/PreviewUploadOverlay.h"
@@ -166,6 +168,12 @@ InputBar::nextText()
QObject *
InputBar::completerFor(QString completerName)
{
+ if (completerName == "user") {
+ auto userModel = new UsersModel(room->roomId().toStdString());
+ auto proxy = new CompletionProxyModel(userModel);
+ userModel->setParent(proxy);
+ return proxy;
+ }
return nullptr;
}
|