Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add username autocompletion popup menu #2866

Merged
merged 10 commits into from
Jun 19, 2021
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unversioned

- Major: Added username autocompletion popup menu when typing usernames with an @ prefix. (#1979, #2866)
- Major: Added ability to toggle visibility of Channel Tabs - This can be done by right-clicking the tab area or pressing the keyboard shortcut (default: Ctrl+U). (#2600)
- Minor: Restore automod functionality for moderators (#2817, #2887)
- Minor: Add setting for username style (#2889, #2891)
Expand Down
8 changes: 4 additions & 4 deletions chatterino.pro
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,8 @@ SOURCES += \
src/widgets/settingspages/NotificationPage.cpp \
src/widgets/settingspages/SettingsPage.cpp \
src/widgets/splits/ClosedSplits.cpp \
src/widgets/splits/EmoteInputItem.cpp \
src/widgets/splits/EmoteInputPopup.cpp \
src/widgets/splits/InputCompletionItem.cpp \
src/widgets/splits/InputCompletionPopup.cpp \
src/widgets/splits/Split.cpp \
src/widgets/splits/SplitContainer.cpp \
src/widgets/splits/SplitHeader.cpp \
Expand Down Expand Up @@ -579,8 +579,8 @@ HEADERS += \
src/widgets/settingspages/NotificationPage.hpp \
src/widgets/settingspages/SettingsPage.hpp \
src/widgets/splits/ClosedSplits.hpp \
src/widgets/splits/EmoteInputItem.hpp \
src/widgets/splits/EmoteInputPopup.hpp \
src/widgets/splits/InputCompletionItem.hpp \
src/widgets/splits/InputCompletionPopup.hpp \
src/widgets/splits/Split.hpp \
src/widgets/splits/SplitContainer.hpp \
src/widgets/splits/SplitHeader.hpp \
Expand Down
8 changes: 4 additions & 4 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -437,10 +437,10 @@ set(SOURCE_FILES

widgets/splits/ClosedSplits.cpp
widgets/splits/ClosedSplits.hpp
widgets/splits/EmoteInputItem.cpp
widgets/splits/EmoteInputItem.hpp
widgets/splits/EmoteInputPopup.cpp
widgets/splits/EmoteInputPopup.hpp
widgets/splits/InputCompletionItem.cpp
widgets/splits/InputCompletionItem.hpp
widgets/splits/InputCompletionPopup.cpp
widgets/splits/InputCompletionPopup.hpp
widgets/splits/Split.cpp
widgets/splits/Split.hpp
widgets/splits/SplitContainer.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/singletons/Settings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ class Settings : public ABSettings, public ConcurrentSettings
"/behaviour/autocompletion/userCompletionOnlyWithAt", false};
BoolSetting emoteCompletionWithColon = {
"/behaviour/autocompletion/emoteCompletionWithColon", true};
BoolSetting showUsernameCompletionMenu = {
"/behaviour/autocompletion/showUsernameCompletionMenu", true};

FloatSetting pauseOnHoverDuration = {"/behaviour/pauseOnHoverDuration", 0};
EnumSetting<Qt::KeyboardModifier> pauseChatModifier = {
Expand Down
2 changes: 2 additions & 0 deletions src/widgets/settingspages/GeneralPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,8 @@ void GeneralPage::initLayout(GeneralPageView &layout)
layout.addCheckbox("Color @usernames", s.colorUsernames);
layout.addCheckbox("Try to find usernames without @ prefix",
s.findAllUsernames);
layout.addCheckbox("Show username autocompletion popup menu",
s.showUsernameCompletionMenu);
const QStringList usernameDisplayModes = {"Username", "Localized name",
"Username and localized name"};

Expand Down
63 changes: 0 additions & 63 deletions src/widgets/splits/EmoteInputItem.cpp

This file was deleted.

76 changes: 76 additions & 0 deletions src/widgets/splits/InputCompletionItem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include "InputCompletionItem.hpp"

namespace chatterino {

InputCompletionItem::InputCompletionItem(const EmotePtr &emote,
const QString &text,
ActionCallback action)
: emote_(emote)
, text_(text)
, action_(action)
{
}

void InputCompletionItem::action()
{
if (this->action_)
{
if (this->emote_)
this->action_(this->emote_->name.string);
else
this->action_(this->text_);
}
}

void InputCompletionItem::paint(QPainter *painter, const QRect &rect) const
{
auto margin = 4;
QRect textRect;
if (this->emote_)
{
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->setRenderHint(QPainter::Antialiasing);

auto imageHeight = ICON_SIZE.height() - margin * 2;

QRect iconRect{
rect.topLeft() + QPoint{margin, margin},
QSize{imageHeight, imageHeight},
};

if (auto image = this->emote_->images.getImage(2))
{
if (auto pixmap = image->pixmapOrLoad())
{
if (image->height() != 0)
{
auto aspectRatio =
double(image->width()) / double(image->height());

iconRect = {
rect.topLeft() + QPoint{margin, margin},
QSize(int(imageHeight * aspectRatio), imageHeight)};
painter->drawPixmap(iconRect, *pixmap);
}
}
}

textRect =
QRect(iconRect.topRight() + QPoint{margin, 0},
QSize(rect.width() - iconRect.width(), iconRect.height()));
}
else
{
textRect = QRect(rect.topLeft() + QPoint{margin, 0},
QSize(rect.width(), rect.height()));
}

painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, this->text_);
}

QSize InputCompletionItem::sizeHint(const QRect &rect) const
{
return QSize(rect.width(), ICON_SIZE.height());
}

} // namespace chatterino
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

namespace chatterino {

class EmoteInputItem : public GenericListItem
class InputCompletionItem : public GenericListItem
{
using ActionCallback = std::function<void(const QString &)>;

public:
EmoteInputItem(const EmotePtr &emote, const QString &text,
ActionCallback action);
InputCompletionItem(const EmotePtr &emote, const QString &text,
ActionCallback action);

// GenericListItem interface
public:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "EmoteInputPopup.hpp"
#include "InputCompletionPopup.hpp"

#include "Application.hpp"
#include "controllers/accounts/AccountController.hpp"
Expand All @@ -10,7 +10,7 @@
#include "singletons/Emotes.hpp"
#include "util/LayoutCreator.hpp"
#include "widgets/listview/GenericListView.hpp"
#include "widgets/splits/EmoteInputItem.hpp"
#include "widgets/splits/InputCompletionItem.hpp"

namespace chatterino {
namespace {
Expand Down Expand Up @@ -41,7 +41,7 @@ namespace {
}
} // namespace

EmoteInputPopup::EmoteInputPopup(QWidget *parent)
InputCompletionPopup::InputCompletionPopup(QWidget *parent)
: BasePopup({BasePopup::EnableCustomFrame, BasePopup::Frameless,
BasePopup::DontFocus},
parent)
Expand All @@ -56,7 +56,7 @@ EmoteInputPopup::EmoteInputPopup(QWidget *parent)
this->redrawTimer_.setInterval(33);
}

void EmoteInputPopup::initLayout()
void InputCompletionPopup::initLayout()
{
LayoutCreator creator = {this};

Expand All @@ -71,7 +71,7 @@ void EmoteInputPopup::initLayout()
});
}

void EmoteInputPopup::updateEmotes(const QString &text, ChannelPtr channel)
void InputCompletionPopup::updateEmotes(const QString &text, ChannelPtr channel)
{
std::vector<_Emote> emotes;
auto tc = dynamic_cast<TwitchChannel *>(channel.get());
Expand Down Expand Up @@ -122,11 +122,11 @@ void EmoteInputPopup::updateEmotes(const QString &text, ChannelPtr channel)
int count = 0;
for (auto &&emote : emotes)
{
this->model_.addItem(std::make_unique<EmoteInputItem>(
this->model_.addItem(std::make_unique<InputCompletionItem>(
emote.emote, emote.displayName + " - " + emote.providerName,
this->callback_));

if (count++ == maxEmoteCount)
if (count++ == maxEntryCount)
break;
}

Expand All @@ -136,22 +136,45 @@ void EmoteInputPopup::updateEmotes(const QString &text, ChannelPtr channel)
}
}

bool EmoteInputPopup::eventFilter(QObject *watched, QEvent *event)
void InputCompletionPopup::updateUsers(const QString &text, ChannelPtr channel)
{
auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
if (twitchChannel)
{
auto chatters = twitchChannel->accessChatters()->filterByPrefix(text);
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)
break;
}
if (!chatters.empty())
{
this->ui_.listView->setCurrentIndex(this->model_.index(0));
}
}
}

bool InputCompletionPopup::eventFilter(QObject *watched, QEvent *event)
{
return this->ui_.listView->eventFilter(watched, event);
}

void EmoteInputPopup::setInputAction(ActionCallback callback)
void InputCompletionPopup::setInputAction(ActionCallback callback)
{
this->callback_ = std::move(callback);
}

void EmoteInputPopup::showEvent(QShowEvent *)
void InputCompletionPopup::showEvent(QShowEvent *)
{
this->redrawTimer_.start();
}

void EmoteInputPopup::hideEvent(QHideEvent *)
void InputCompletionPopup::hideEvent(QHideEvent *)
{
this->redrawTimer_.stop();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ namespace chatterino {

class GenericListView;

class EmoteInputPopup : public BasePopup
class InputCompletionPopup : public BasePopup
{
using ActionCallback = std::function<void(const QString &)>;

constexpr static int maxEmoteCount = 200;
constexpr static int maxEntryCount = 200;

public:
EmoteInputPopup(QWidget *parent = nullptr);
InputCompletionPopup(QWidget *parent = nullptr);

void updateEmotes(const QString &text, ChannelPtr channel);
void updateUsers(const QString &text, ChannelPtr channel);
virtual bool eventFilter(QObject *, QEvent *event) override;

void setInputAction(ActionCallback callback);
Expand Down
Loading