Clean up/refactor InputCompletionPopup (#4242)

Mainly flattening anon namespaces & respecting clang-tidy
This commit is contained in:
pajlada
2022-12-18 14:25:11 +01:00
committed by GitHub
parent 2de1437bdf
commit 8830b0e01c
5 changed files with 126 additions and 75 deletions
+2
View File
@@ -51,3 +51,5 @@ CheckOptions:
value: UPPER_CASE value: UPPER_CASE
- key: readability-identifier-naming.VariableCase - key: readability-identifier-naming.VariableCase
value: camelBack value: camelBack
- key: readability-implicit-bool-conversion.AllowPointerConditions
value: true
+92 -60
View File
@@ -13,35 +13,47 @@
#include "widgets/listview/GenericListView.hpp" #include "widgets/listview/GenericListView.hpp"
#include "widgets/splits/InputCompletionItem.hpp" #include "widgets/splits/InputCompletionItem.hpp"
namespace chatterino {
namespace { namespace {
struct _Emote { using namespace chatterino;
EmotePtr emote;
QString displayName;
QString providerName;
};
void addEmotes(std::vector<_Emote> &out, const EmoteMap &map, struct CompletionEmote {
const QString &text, const QString &providerName) EmotePtr emote;
{ QString displayName;
for (auto &&emote : map) QString providerName;
if (emote.first.string.contains(text, Qt::CaseInsensitive)) };
out.push_back(
{emote.second, emote.second->name.string, providerName});
}
void addEmojis(std::vector<_Emote> &out, const EmojiMap &map, void addEmotes(std::vector<CompletionEmote> &out, const EmoteMap &map,
const QString &text) const QString &text, const QString &providerName)
{
for (auto &&emote : map)
{ {
map.each([&](const QString &, const std::shared_ptr<EmojiData> &emoji) { if (emote.first.string.contains(text, Qt::CaseInsensitive))
for (auto &&shortCode : emoji->shortCodes) {
if (shortCode.contains(text, Qt::CaseInsensitive)) out.push_back(
out.push_back({emoji->emote, shortCode, "Emoji"}); {emote.second, emote.second->name.string, providerName});
}); }
} }
}
void addEmojis(std::vector<CompletionEmote> &out, const EmojiMap &map,
const QString &text)
{
map.each([&](const QString &, const std::shared_ptr<EmojiData> &emoji) {
for (auto &&shortCode : emoji->shortCodes)
{
if (shortCode.contains(text, Qt::CaseInsensitive))
{
out.push_back({emoji->emote, shortCode, "Emoji"});
}
}
});
}
} // namespace } // namespace
namespace chatterino {
InputCompletionPopup::InputCompletionPopup(QWidget *parent) InputCompletionPopup::InputCompletionPopup(QWidget *parent)
: BasePopup({BasePopup::EnableCustomFrame, BasePopup::Frameless, : BasePopup({BasePopup::EnableCustomFrame, BasePopup::Frameless,
BasePopup::DontFocus, BaseWindow::DisableLayoutSave}, BasePopup::DontFocus, BaseWindow::DisableLayoutSave},
@@ -52,30 +64,17 @@ InputCompletionPopup::InputCompletionPopup(QWidget *parent)
QObject::connect(&this->redrawTimer_, &QTimer::timeout, this, [this] { QObject::connect(&this->redrawTimer_, &QTimer::timeout, this, [this] {
if (this->isVisible()) if (this->isVisible())
{
this->ui_.listView->doItemsLayout(); this->ui_.listView->doItemsLayout();
}
}); });
this->redrawTimer_.setInterval(33); this->redrawTimer_.setInterval(33);
} }
void InputCompletionPopup::initLayout()
{
LayoutCreator creator = {this};
auto listView =
creator.emplace<GenericListView>().assign(&this->ui_.listView);
listView->setInvokeActionOnTab(true);
listView->setModel(&this->model_);
QObject::connect(listView.getElement(), &GenericListView::closeRequested,
this, [this] {
this->close();
});
}
void InputCompletionPopup::updateEmotes(const QString &text, ChannelPtr channel) void InputCompletionPopup::updateEmotes(const QString &text, ChannelPtr channel)
{ {
std::vector<_Emote> emotes; std::vector<CompletionEmote> emotes;
auto tc = dynamic_cast<TwitchChannel *>(channel.get()); auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
// returns true also for special Twitch channels (/live, /mentions, /whispers, etc.) // returns true also for special Twitch channels (/live, /mentions, /whispers, etc.)
if (channel->isTwitchChannel()) if (channel->isTwitchChannel())
{ {
@@ -90,7 +89,7 @@ void InputCompletionPopup::updateEmotes(const QString &text, ChannelPtr channel)
if (tc && if (tc &&
localEmoteData->find(tc->roomId()) != localEmoteData->end()) localEmoteData->find(tc->roomId()) != localEmoteData->end())
{ {
if (auto localEmotes = &localEmoteData->at(tc->roomId())) if (const auto *localEmotes = &localEmoteData->at(tc->roomId()))
{ {
addEmotes(emotes, *localEmotes, text, addEmotes(emotes, *localEmotes, text,
"Local Twitch Emotes"); "Local Twitch Emotes");
@@ -102,9 +101,13 @@ void InputCompletionPopup::updateEmotes(const QString &text, ChannelPtr channel)
{ {
// TODO extract "Channel {BetterTTV,7TV,FrankerFaceZ}" text into a #define. // TODO extract "Channel {BetterTTV,7TV,FrankerFaceZ}" text into a #define.
if (auto bttv = tc->bttvEmotes()) if (auto bttv = tc->bttvEmotes())
{
addEmotes(emotes, *bttv, text, "Channel BetterTTV"); addEmotes(emotes, *bttv, text, "Channel BetterTTV");
}
if (auto ffz = tc->ffzEmotes()) if (auto ffz = tc->ffzEmotes())
{
addEmotes(emotes, *ffz, text, "Channel FrankerFaceZ"); addEmotes(emotes, *ffz, text, "Channel FrankerFaceZ");
}
if (auto seventv = tc->seventvEmotes()) if (auto seventv = tc->seventvEmotes())
{ {
addEmotes(emotes, *seventv, text, "Channel 7TV"); addEmotes(emotes, *seventv, text, "Channel 7TV");
@@ -112,9 +115,13 @@ void InputCompletionPopup::updateEmotes(const QString &text, ChannelPtr channel)
} }
if (auto bttvG = getApp()->twitch->getBttvEmotes().emotes()) if (auto bttvG = getApp()->twitch->getBttvEmotes().emotes())
{
addEmotes(emotes, *bttvG, text, "Global BetterTTV"); addEmotes(emotes, *bttvG, text, "Global BetterTTV");
}
if (auto ffzG = getApp()->twitch->getFfzEmotes().emotes()) if (auto ffzG = getApp()->twitch->getFfzEmotes().emotes())
{
addEmotes(emotes, *ffzG, text, "Global FrankerFaceZ"); addEmotes(emotes, *ffzG, text, "Global FrankerFaceZ");
}
if (auto seventvG = getApp()->twitch->getSeventvEmotes().globalEmotes()) if (auto seventvG = getApp()->twitch->getSeventvEmotes().globalEmotes())
{ {
addEmotes(emotes, *seventvG, text, "Global 7TV"); addEmotes(emotes, *seventvG, text, "Global 7TV");
@@ -148,8 +155,10 @@ void InputCompletionPopup::updateEmotes(const QString &text, ChannelPtr channel)
emote.emote, emote.displayName + " - " + emote.providerName, emote.emote, emote.displayName + " - " + emote.providerName,
this->callback_)); this->callback_));
if (count++ == maxEntryCount) if (count++ == MAX_ENTRY_COUNT)
{
break; break;
}
} }
if (!emotes.empty()) if (!emotes.empty())
@@ -160,30 +169,33 @@ void InputCompletionPopup::updateEmotes(const QString &text, ChannelPtr channel)
void InputCompletionPopup::updateUsers(const QString &text, ChannelPtr channel) void InputCompletionPopup::updateUsers(const QString &text, ChannelPtr channel)
{ {
auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get()); auto *tc = dynamic_cast<TwitchChannel *>(channel.get());
if (twitchChannel) if (!tc)
{ {
auto chatters = twitchChannel->accessChatters()->filterByPrefix(text); return;
this->model_.clear(); }
int count = 0;
for (const auto &name : chatters)
{
this->model_.addItem(std::make_unique<InputCompletionItem>(
nullptr, name, this->callback_));
if (count++ == maxEntryCount) auto chatters = tc->accessChatters()->filterByPrefix(text);
break; this->model_.clear();
}
if (!chatters.empty()) if (chatters.empty())
{
return;
}
int count = 0;
for (const auto &name : chatters)
{
this->model_.addItem(std::make_unique<InputCompletionItem>(
nullptr, name, this->callback_));
if (count++ == MAX_ENTRY_COUNT)
{ {
this->ui_.listView->setCurrentIndex(this->model_.index(0)); break;
} }
} }
}
bool InputCompletionPopup::eventFilter(QObject *watched, QEvent *event) this->ui_.listView->setCurrentIndex(this->model_.index(0));
{
return this->ui_.listView->eventFilter(watched, event);
} }
void InputCompletionPopup::setInputAction(ActionCallback callback) void InputCompletionPopup::setInputAction(ActionCallback callback)
@@ -191,14 +203,34 @@ void InputCompletionPopup::setInputAction(ActionCallback callback)
this->callback_ = std::move(callback); this->callback_ = std::move(callback);
} }
void InputCompletionPopup::showEvent(QShowEvent *) bool InputCompletionPopup::eventFilter(QObject *watched, QEvent *event)
{
return this->ui_.listView->eventFilter(watched, event);
}
void InputCompletionPopup::showEvent(QShowEvent * /*event*/)
{ {
this->redrawTimer_.start(); this->redrawTimer_.start();
} }
void InputCompletionPopup::hideEvent(QHideEvent *) void InputCompletionPopup::hideEvent(QHideEvent * /*event*/)
{ {
this->redrawTimer_.stop(); this->redrawTimer_.stop();
} }
void InputCompletionPopup::initLayout()
{
LayoutCreator creator = {this};
auto listView =
creator.emplace<GenericListView>().assign(&this->ui_.listView);
listView->setInvokeActionOnTab(true);
listView->setModel(&this->model_);
QObject::connect(listView.getElement(), &GenericListView::closeRequested,
this, [this] {
this->close();
});
}
} // namespace chatterino } // namespace chatterino
+3 -2
View File
@@ -14,17 +14,18 @@ class InputCompletionPopup : public BasePopup
{ {
using ActionCallback = std::function<void(const QString &)>; using ActionCallback = std::function<void(const QString &)>;
constexpr static int maxEntryCount = 200; constexpr static int MAX_ENTRY_COUNT = 200;
public: public:
InputCompletionPopup(QWidget *parent = nullptr); InputCompletionPopup(QWidget *parent = nullptr);
void updateEmotes(const QString &text, ChannelPtr channel); void updateEmotes(const QString &text, ChannelPtr channel);
void updateUsers(const QString &text, ChannelPtr channel); void updateUsers(const QString &text, ChannelPtr channel);
virtual bool eventFilter(QObject *, QEvent *event) override;
void setInputAction(ActionCallback callback); void setInputAction(ActionCallback callback);
bool eventFilter(QObject *watched, QEvent *event) override;
protected: protected:
void showEvent(QShowEvent *event) override; void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override; void hideEvent(QHideEvent *event) override;
+28 -12
View File
@@ -625,7 +625,7 @@ void SplitInput::installKeyPressedEvent()
{ {
this->ui_.textEdit->keyPressed.disconnectAll(); this->ui_.textEdit->keyPressed.disconnectAll();
this->ui_.textEdit->keyPressed.connect([this](QKeyEvent *event) { this->ui_.textEdit->keyPressed.connect([this](QKeyEvent *event) {
if (auto popup = this->inputCompletionPopup_.get()) if (auto *popup = this->inputCompletionPopup_.get())
{ {
if (popup->isVisible()) if (popup->isVisible())
{ {
@@ -674,11 +674,11 @@ void SplitInput::onCursorPositionChanged()
void SplitInput::updateCompletionPopup() void SplitInput::updateCompletionPopup()
{ {
auto channel = this->split_->getChannel().get(); auto *channel = this->split_->getChannel().get();
auto tc = dynamic_cast<TwitchChannel *>(channel); auto *tc = dynamic_cast<TwitchChannel *>(channel);
bool showEmoteCompletion = getSettings()->emoteCompletionWithColon; bool showEmoteCompletion = getSettings()->emoteCompletionWithColon;
bool showUsernameCompletion = bool showUsernameCompletion =
tc && getSettings()->showUsernameCompletionMenu; tc != nullptr && getSettings()->showUsernameCompletionMenu;
if (!showEmoteCompletion && !showUsernameCompletion) if (!showEmoteCompletion && !showUsernameCompletion)
{ {
this->hideCompletionPopup(); this->hideCompletionPopup();
@@ -704,22 +704,32 @@ void SplitInput::updateCompletionPopup()
this->hideCompletionPopup(); this->hideCompletionPopup();
return; return;
} }
else if (text[i] == ':' && showEmoteCompletion)
if (text[i] == ':' && showEmoteCompletion)
{ {
if (i == 0 || text[i - 1].isSpace()) if (i == 0 || text[i - 1].isSpace())
{
this->showCompletionPopup(text.mid(i, position - i + 1).mid(1), this->showCompletionPopup(text.mid(i, position - i + 1).mid(1),
true); true);
}
else else
{
this->hideCompletionPopup(); this->hideCompletionPopup();
}
return; return;
} }
else if (text[i] == '@' && showUsernameCompletion)
if (text[i] == '@' && showUsernameCompletion)
{ {
if (i == 0 || text[i - 1].isSpace()) if (i == 0 || text[i - 1].isSpace())
{
this->showCompletionPopup(text.mid(i, position - i + 1).mid(1), this->showCompletionPopup(text.mid(i, position - i + 1).mid(1),
false); false);
}
else else
{
this->hideCompletionPopup(); this->hideCompletionPopup();
}
return; return;
} }
} }
@@ -734,7 +744,7 @@ void SplitInput::showCompletionPopup(const QString &text, bool emoteCompletion)
this->inputCompletionPopup_ = new InputCompletionPopup(this); this->inputCompletionPopup_ = new InputCompletionPopup(this);
this->inputCompletionPopup_->setInputAction( this->inputCompletionPopup_->setInputAction(
[that = QObjectRef(this)](const QString &text) mutable { [that = QObjectRef(this)](const QString &text) mutable {
if (auto this2 = that.get()) if (auto *this2 = that.get())
{ {
this2->insertCompletionText(text); this2->insertCompletionText(text);
this2->hideCompletionPopup(); this2->hideCompletionPopup();
@@ -742,13 +752,17 @@ void SplitInput::showCompletionPopup(const QString &text, bool emoteCompletion)
}); });
} }
auto popup = this->inputCompletionPopup_.get(); auto *popup = this->inputCompletionPopup_.get();
assert(popup); assert(popup);
if (emoteCompletion) // autocomplete emotes if (emoteCompletion)
{
popup->updateEmotes(text, this->split_->getChannel()); popup->updateEmotes(text, this->split_->getChannel());
else // autocomplete usernames }
else
{
popup->updateUsers(text, this->split_->getChannel()); popup->updateUsers(text, this->split_->getChannel());
}
auto pos = this->mapToGlobal({0, 0}) - QPoint(0, popup->height()) + auto pos = this->mapToGlobal({0, 0}) - QPoint(0, popup->height()) +
QPoint((this->width() - popup->width()) / 2, 0); QPoint((this->width() - popup->width()) / 2, 0);
@@ -759,11 +773,13 @@ void SplitInput::showCompletionPopup(const QString &text, bool emoteCompletion)
void SplitInput::hideCompletionPopup() void SplitInput::hideCompletionPopup()
{ {
if (auto popup = this->inputCompletionPopup_.get()) if (auto *popup = this->inputCompletionPopup_.get())
{
popup->hide(); popup->hide();
}
} }
void SplitInput::insertCompletionText(const QString &input_) void SplitInput::insertCompletionText(const QString &input_) const
{ {
auto &edit = *this->ui_.textEdit; auto &edit = *this->ui_.textEdit;
auto input = input_ + ' '; auto input = input_ + ' ';
+1 -1
View File
@@ -112,7 +112,7 @@ protected:
void updateCompletionPopup(); void updateCompletionPopup();
void showCompletionPopup(const QString &text, bool emoteCompletion); void showCompletionPopup(const QString &text, bool emoteCompletion);
void hideCompletionPopup(); void hideCompletionPopup();
void insertCompletionText(const QString &text); void insertCompletionText(const QString &input_) const;
void openEmotePopup(); void openEmotePopup();
void updateCancelReplyButton(); void updateCancelReplyButton();