/* * nheko Copyright (C) 2017 Konstantinos Sideris * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include #include #include #include #include #include #include #include "dialogs/PreviewUploadOverlay.h" #include "popups/SuggestionsPopup.h" struct SearchResult; class CompletionProxyModel; class FlatButton; class LoadingIndicator; class QCompleter; class FilteredTextEdit : public QTextEdit { Q_OBJECT public: explicit FilteredTextEdit(QWidget *parent = nullptr); QSize sizeHint() const override; QSize minimumSizeHint() const override; void submit(); signals: void heightChanged(int height); void startedUpload(); //! Trigger the suggestion popup. void showSuggestions(const QString &query); void resultsRetrieved(const std::vector &results); void selectNextSuggestion(); void selectPreviousSuggestion(); void selectHoveredSuggestion(); public slots: void showResults(const std::vector &results); protected: void keyPressEvent(QKeyEvent *event) override; void focusOutEvent(QFocusEvent *event) override { suggestionsPopup_.hide(); QTextEdit::focusOutEvent(event); } private: bool emoji_popup_open_ = false; CompletionProxyModel *emoji_completion_model_; std::deque true_history_, working_history_; int trigger_pos_; // Where emoji completer was triggered size_t history_index_; QCompleter *completer_; SuggestionsPopup suggestionsPopup_; enum class AnchorType { Tab = 0, Sigil = 1, }; AnchorType anchorType_ = AnchorType::Sigil; int anchorWidth(AnchorType anchor) { return static_cast(anchor); } void closeSuggestions() { suggestionsPopup_.hide(); } void resetAnchor() { atTriggerPosition_ = -1; } bool isAnchorValid() { return atTriggerPosition_ != -1; } bool hasAnchor(int pos, AnchorType anchor) { return pos == atTriggerPosition_ + anchorWidth(anchor); } QRect completerRect(); QString query() { auto cursor = textCursor(); cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); return cursor.selectedText(); } QString textAfterPosition(int pos) { auto tc = textCursor(); tc.setPosition(pos); tc.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); return tc.selectedText(); } dialogs::PreviewUploadOverlay previewDialog_; //! Latest position of the '@' character that triggers the username completer. int atTriggerPosition_ = -1; void insertCompletion(QString completion); void textChanged(); void afterCompletion(int); }; class TextInputWidget : public QWidget { Q_OBJECT Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor) public: TextInputWidget(QWidget *parent = nullptr); QColor borderColor() const { return borderColor_; } void setBorderColor(QColor &color) { borderColor_ = color; } void disableInput() { input_->setEnabled(false); input_->setPlaceholderText(tr("Connection lost. Nheko is trying to re-connect...")); } void enableInput() { input_->setEnabled(true); input_->setPlaceholderText(tr("Write a message...")); } public slots: void focusLineEdit() { input_->setFocus(); } signals: void heightChanged(int height); void sendJoinRoomRequest(const QString &room); void sendInviteRoomRequest(const QString &userid, const QString &reason); void sendKickRoomRequest(const QString &userid, const QString &reason); void sendBanRoomRequest(const QString &userid, const QString &reason); void sendUnbanRoomRequest(const QString &userid, const QString &reason); void changeRoomNick(const QString &displayname); protected: void focusInEvent(QFocusEvent *event) override; void paintEvent(QPaintEvent *) override; private: QHBoxLayout *topLayout_; FilteredTextEdit *input_; LoadingIndicator *spinner_; FlatButton *sendFileBtn_; FlatButton *sendMessageBtn_; QColor borderColor_; };