summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
authorKonstantinos Sideris <sideris.konstantin@gmail.com>2018-03-24 23:16:15 +0200
committerKonstantinos Sideris <sideris.konstantin@gmail.com>2018-03-24 23:16:15 +0200
commit553a97c8bb5042fbef0487255af52a4a6793d0fd (patch)
tree637a38c762fa6847c16cc9245a795c69314941f6 /include
parentAdjust version number for the windows build (diff)
downloadnheko-553a97c8bb5042fbef0487255af52a4a6793d0fd.tar.xz
Add basic support for username auto-completion
fixes #40
Diffstat (limited to 'include')
-rw-r--r--include/Config.h5
-rw-r--r--include/SuggestionsPopup.hpp63
-rw-r--r--include/TextInputWidget.h40
-rw-r--r--include/Utils.h4
4 files changed, 112 insertions, 0 deletions
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 <QHBoxLayout> +#include <QLabel> +#include <QPoint> +#include <QWidget> + +class Avatar; + +struct SearchResult +{ + QString user_id; + QString display_name; +}; + +Q_DECLARE_METATYPE(SearchResult) +Q_DECLARE_METATYPE(QVector<SearchResult>) + +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<SearchResult> &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 <deque> +#include <iterator> +#include <map> +#include <QApplication> +#include <QDebug> #include <QHBoxLayout> #include <QPaintEvent> #include <QTextEdit> @@ -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<QIODevice> data, const QString &filename); void file(QSharedPointer<QIODevice> data, const QString &filename); + //! Trigger the suggestion popup. + void showSuggestions(const QString &query); + void resultsRetrieved(const QVector<SearchResult> &results); + +public slots: + void showResults(const QVector<SearchResult> &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<QString> 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<RoomState> 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<RoomState> 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); }