From 553a97c8bb5042fbef0487255af52a4a6793d0fd Mon Sep 17 00:00:00 2001 From: Konstantinos Sideris Date: Sat, 24 Mar 2018 23:16:15 +0200 Subject: Add basic support for username auto-completion fixes #40 --- include/Config.h | 5 ++++ include/SuggestionsPopup.hpp | 63 ++++++++++++++++++++++++++++++++++++++++++++ include/TextInputWidget.h | 40 ++++++++++++++++++++++++++++ include/Utils.h | 4 +++ 4 files changed, 112 insertions(+) create mode 100644 include/SuggestionsPopup.hpp (limited to 'include') diff --git a/include/Config.h b/include/Config.h index 54b2aa61..d7021d92 100644 --- a/include/Config.h +++ b/include/Config.h @@ -15,6 +15,11 @@ static constexpr int emojiSize = 14; static constexpr int headerFontSize = 21; static constexpr int typingNotificationFontSize = 11; +namespace popup { +static constexpr int font = fontSize; +static constexpr int avatar = 28; +} + namespace receipts { static constexpr int font = 12; } diff --git a/include/SuggestionsPopup.hpp b/include/SuggestionsPopup.hpp new file mode 100644 index 00000000..23549124 --- /dev/null +++ b/include/SuggestionsPopup.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include +#include +#include +#include + +class Avatar; + +struct SearchResult +{ + QString user_id; + QString display_name; +}; + +Q_DECLARE_METATYPE(SearchResult) +Q_DECLARE_METATYPE(QVector) + +class PopupItem : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(QColor hoverColor READ hoverColor WRITE setHoverColor) + +public: + PopupItem(QWidget *parent, const QString &user_id); + + QColor hoverColor() const { return hoverColor_; } + void setHoverColor(QColor &color) { hoverColor_ = color; } + +protected: + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + +signals: + void clicked(const QString &display_name); + +private: + QHBoxLayout *topLayout_; + + Avatar *avatar_; + QLabel *userName_; + QString user_id_; + + QColor hoverColor_; +}; + +class SuggestionsPopup : public QWidget +{ + Q_OBJECT + +public: + explicit SuggestionsPopup(QWidget *parent = nullptr); + +public slots: + void addUsers(const QVector &users); + +signals: + void itemSelected(const QString &user); + +private: + QVBoxLayout *layout_; +}; diff --git a/include/TextInputWidget.h b/include/TextInputWidget.h index 872773f1..95262722 100644 --- a/include/TextInputWidget.h +++ b/include/TextInputWidget.h @@ -18,7 +18,11 @@ #pragma once #include +#include +#include +#include +#include #include #include #include @@ -26,15 +30,20 @@ #include "FlatButton.h" #include "LoadingIndicator.h" +#include "SuggestionsPopup.hpp" #include "dialogs/PreviewUploadOverlay.h" #include "emoji/PickButton.h" +class RoomState; + namespace dialogs { class PreviewUploadOverlay; } +struct SearchResult; + class FilteredTextEdit : public QTextEdit { Q_OBJECT @@ -61,18 +70,45 @@ signals: void video(QSharedPointer data, const QString &filename); void file(QSharedPointer data, const QString &filename); + //! Trigger the suggestion popup. + void showSuggestions(const QString &query); + void resultsRetrieved(const QVector &results); + +public slots: + void showResults(const QVector &results); + protected: void keyPressEvent(QKeyEvent *event) override; bool canInsertFromMimeData(const QMimeData *source) const override; void insertFromMimeData(const QMimeData *source) override; + void focusOutEvent(QFocusEvent *event) override + { + popup_.hide(); + QWidget::focusOutEvent(event); + } private: std::deque true_history_, working_history_; size_t history_index_; QTimer *typingTimer_; + SuggestionsPopup popup_; + + void closeSuggestions() { popup_.hide(); } + void resetAnchor() { atTriggerPosition_ = -1; } + + QString query() + { + auto cursor = textCursor(); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + return cursor.selectedText(); + } + dialogs::PreviewUploadOverlay previewDialog_; + //! Latest position of the '@' character that triggers the username completer. + int atTriggerPosition_ = -1; + void textChanged(); void uploadData(const QByteArray data, const QString &media, const QString &filename); void afterCompletion(int); @@ -97,6 +133,7 @@ public slots: void openFileSelection(); void hideUploadSpinner(); void focusLineEdit() { input_->setFocus(); } + void setRoomState(QSharedPointer state) { currState_ = state; } private slots: void addSelectedEmoji(const QString &emoji); @@ -132,5 +169,8 @@ private: FlatButton *sendMessageBtn_; emoji::PickButton *emojiBtn_; + //! State of the current room. + QSharedPointer currState_; + QColor borderColor_; }; diff --git a/include/Utils.h b/include/Utils.h index fba9bf67..cbecb4ac 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -54,4 +54,8 @@ scaleDown(uint64_t max_width, uint64_t max_height, const ImageType &source) return source.scaled( final_width, final_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } + +//! Calculate the Levenshtein distance between two strings with character skipping. +int +levenshtein_distance(const std::string &s1, const std::string &s2); } -- cgit 1.5.1