Add emojis to autocomplete

Improve autocomplete:
 - Add space after autocompleted item
 - Emotes starting with `:` can now be autocompleted properly (i.e. emojis)
This commit is contained in:
Rasmus Karlsson 2017-08-01 00:10:02 +02:00
parent 62a1148c02
commit ba092aa29b
6 changed files with 69 additions and 11 deletions

View file

@ -4,6 +4,12 @@
namespace chatterino {
void CompletionModel::addString(const std::string &str)
{
// Always add a space at the end of completions
this->emotes.push_back(qS(str) + " ");
}
CompletionManager::CompletionManager(EmoteManager &_emoteManager)
: emoteManager(_emoteManager)
{
@ -40,30 +46,35 @@ void CompletionManager::updateModel(CompletionModel *model, const std::string &c
for (const auto &m : this->emoteManager.twitchAccountEmotes) {
for (const auto &emoteName : m.second.emoteCodes) {
model->emotes.push_back(qS(emoteName));
model->addString(emoteName);
}
}
std::vector<std::string> &bttvGlobalEmoteCodes = this->emoteManager.bttvGlobalEmoteCodes;
for (const auto &m : bttvGlobalEmoteCodes) {
model->emotes.push_back(qS(m));
model->addString(m);
}
std::vector<std::string> &ffzGlobalEmoteCodes = this->emoteManager.ffzGlobalEmoteCodes;
for (const auto &m : ffzGlobalEmoteCodes) {
model->emotes.push_back(qS(m));
model->addString(m);
}
std::vector<std::string> &bttvChannelEmoteCodes =
this->emoteManager.bttvChannelEmoteCodes[channelName];
for (const auto &m : bttvChannelEmoteCodes) {
model->emotes.push_back(qS(m));
model->addString(m);
}
std::vector<std::string> &ffzChannelEmoteCodes =
this->emoteManager.ffzChannelEmoteCodes[channelName];
for (const auto &m : ffzChannelEmoteCodes) {
model->emotes.push_back(qS(m));
model->addString(m);
}
const auto &emojiShortCodes = this->emoteManager.emojiShortCodes;
for (const auto &m : emojiShortCodes) {
model->addString(":" + m + ":");
}
}

View file

@ -28,6 +28,8 @@ public:
return this->emotes.size();
}
void addString(const std::string &str);
QVector<QString> emotes;
};

View file

@ -199,6 +199,7 @@ void EmoteManager::loadEmojis()
};
this->emojiShortCodeToEmoji.insert(shortCode, emojiData);
this->emojiShortCodes.push_back(shortCode.toStdString());
this->emojiFirstByte[emojiData.value.at(0)].append(emojiData);

View file

@ -94,6 +94,8 @@ public:
QString replaceShortCodes(const QString &text);
std::vector<std::string> emojiShortCodes;
/// Twitch emotes
void refreshTwitchEmotes(const std::string &roomID);

View file

@ -29,11 +29,41 @@ int ResizingTextEdit::heightForWidth(int) const
return margins.top() + document()->size().height() + margins.bottom() + 5;
}
QString ResizingTextEdit::textUnderCursor() const
QString ResizingTextEdit::textUnderCursor(bool *hadSpace) const
{
QTextCursor tc = textCursor();
tc.select(QTextCursor::WordUnderCursor);
return tc.selectedText();
auto currentText = this->toPlainText();
QTextCursor tc = this->textCursor();
auto textUpToCursor = currentText.left(tc.selectionStart());
auto words = textUpToCursor.splitRef(' ');
if (words.size() == 0) {
return QString();
}
bool first = true;
QString lastWord;
for (auto it = words.crbegin(); it != words.crend(); ++it) {
auto word = *it;
if (first && word.isEmpty()) {
first = false;
if (hadSpace != nullptr) {
*hadSpace = true;
}
continue;
}
lastWord = word.toString();
break;
}
if (lastWord.isEmpty()) {
return QString();
}
return lastWord;
}
void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
@ -105,8 +135,17 @@ void ResizingTextEdit::insertCompletion(const QString &completion)
return;
}
bool hadSpace = false;
auto prefix = this->textUnderCursor(&hadSpace);
int prefixSize = prefix.size();
if (hadSpace) {
++prefixSize;
}
QTextCursor tc = this->textCursor();
tc.select(QTextCursor::SelectionType::WordUnderCursor);
tc.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, prefixSize);
tc.insertText(completion);
this->setTextCursor(tc);
}

View file

@ -25,7 +25,10 @@ protected:
private:
QCompleter *completer = nullptr;
QString textUnderCursor() const;
// hadSpace is set to true in case the "textUnderCursor" word was after a space
QString textUnderCursor(bool *hadSpace = nullptr) const;
bool nextCompletion = false;
private slots: