Custom completer filtering

pull/335/head
Nicolas Werner 4 years ago
parent add5903fb0
commit ecc7759973
  1. 3
      resources/qml/MessageInput.qml
  2. 96
      src/CompletionProxyModel.h
  3. 9
      src/UsersModel.cpp
  4. 2
      src/UsersModel.h

@ -128,6 +128,9 @@ Rectangle {
textArea.clear(); textArea.clear();
event.accepted = true; event.accepted = true;
} }
if (popup.opened)
popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition));
} }
Connections { Connections {

@ -5,6 +5,7 @@
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include "CompletionModelRoles.h" #include "CompletionModelRoles.h"
#include "Utils.h"
class CompletionProxyModel : public QSortFilterProxyModel class CompletionProxyModel : public QSortFilterProxyModel
{ {
@ -15,6 +16,20 @@ public:
: QSortFilterProxyModel(parent) : QSortFilterProxyModel(parent)
{ {
setSourceModel(model); setSourceModel(model);
sort(0, Qt::AscendingOrder);
setFilterRole(CompletionModel::SearchRole);
connect(
this,
&CompletionProxyModel::newSearchString,
this,
[this](QString s) {
s.remove(":");
s.remove("@");
searchString = s.toLower();
invalidate();
},
Qt::QueuedConnection);
} }
QHash<int, QByteArray> roleNames() const override QHash<int, QByteArray> roleNames() const override
@ -28,6 +43,79 @@ public:
return (row_count < 7) ? row_count : 7; return (row_count < 7) ? row_count : 7;
} }
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (searchString.size() < 1)
return true;
auto source_index = sourceModel()->index(source_row, 0, source_parent);
auto role1 = sourceModel()
->data(source_index, CompletionModel::SearchRole)
.toString()
.toLower();
if (role1.contains(searchString))
return true;
// auto score =
// utils::levenshtein_distance(searchString, role1.toLower().toStdString());
// if ((size_t)role1.size() >= searchString.size() &&
// ((size_t)score) < (size_t)role1.size() - searchString.size() + 2)
// return true;
auto role2 = sourceModel()
->data(source_index, CompletionModel::SearchRole2)
.toString()
.toLower();
if (role2.contains(searchString))
return true;
// if (!role2.isEmpty()) {
// score =
// utils::levenshtein_distance(searchString,
// role2.toLower().toStdString());
// if ((size_t)role2.size() >= searchString.size() &&
// ((size_t)score) < (size_t)role2.size() - searchString.size() + 2)
// return true;
//}
return false;
}
bool lessThan(const QModelIndex &source_left,
const QModelIndex &source_right) const override
{
if (searchString.size() < 1)
return false;
auto left1 =
sourceModel()->data(source_left, CompletionModel::SearchRole).toString();
auto left2 =
sourceModel()->data(source_left, CompletionModel::SearchRole2).toString();
auto left = left1.toLower().indexOf(searchString);
// utils::levenshtein_distance(searchString, left1.toLower().toStdString());
if (!left2.isEmpty()) {
// left = std::min(
// utils::levenshtein_distance(searchString,
// left2.toLower().toStdString()), left);
left = std::min(left2.toLower().indexOf(searchString), left);
}
auto right1 =
sourceModel()->data(source_right, CompletionModel::SearchRole).toString();
auto right2 =
sourceModel()->data(source_right, CompletionModel::SearchRole2).toString();
auto right = right1.toLower().indexOf(searchString);
// auto right =
// utils::levenshtein_distance(searchString, right1.toLower().toStdString());
if (!right2.isEmpty()) {
// right = std::min(
// utils::levenshtein_distance(searchString,
// right2.toLower().toStdString()), right);
right = std::min(right2.toLower().indexOf(searchString), right);
}
return left < right;
}
public slots: public slots:
QVariant completionAt(int i) const QVariant completionAt(int i) const
{ {
@ -36,4 +124,12 @@ public slots:
else else
return {}; return {};
} }
void setSearchString(QString s) { emit newSearchString(s); }
signals:
void newSearchString(QString);
private:
QString searchString;
}; };

@ -8,6 +8,10 @@ UsersModel::UsersModel(const std::string &roomId, QObject *parent)
, room_id(roomId) , room_id(roomId)
{ {
roomMembers_ = cache::roomMembers(roomId); roomMembers_ = cache::roomMembers(roomId);
for (const auto &m : roomMembers_) {
displayNames.push_back(QString::fromStdString(cache::displayName(room_id, m)));
userids.push_back(QString::fromStdString(m));
}
} }
QHash<int, QByteArray> QHash<int, QByteArray>
@ -31,10 +35,9 @@ UsersModel::data(const QModelIndex &index, int role) const
case CompletionModel::SearchRole: case CompletionModel::SearchRole:
case Qt::DisplayRole: case Qt::DisplayRole:
case Roles::DisplayName: case Roles::DisplayName:
return QString::fromStdString( return displayNames[index.row()];
cache::displayName(room_id, roomMembers_[index.row()]));
case CompletionModel::SearchRole2: case CompletionModel::SearchRole2:
return QString::fromStdString(roomMembers_[index.row()]); return userids[index.row()];
case Roles::AvatarUrl: case Roles::AvatarUrl:
return cache::avatarUrl(QString::fromStdString(room_id), return cache::avatarUrl(QString::fromStdString(room_id),
QString::fromStdString(roomMembers_[index.row()])); QString::fromStdString(roomMembers_[index.row()]));

@ -23,4 +23,6 @@ public:
private: private:
std::string room_id; std::string room_id;
std::vector<std::string> roomMembers_; std::vector<std::string> roomMembers_;
std::vector<QString> displayNames;
std::vector<QString> userids;
}; };

Loading…
Cancel
Save