Merge branch '4tf'
This commit is contained in:
@@ -29,6 +29,8 @@ Notebook::Notebook(QWidget *parent)
|
||||
: BaseWidget(parent)
|
||||
, addButton_(this)
|
||||
{
|
||||
this->addButton_.setIcon(NotebookButton::Icon::Plus);
|
||||
|
||||
this->addButton_.setHidden(true);
|
||||
|
||||
auto *shortcut_next = new QShortcut(QKeySequence("Ctrl+Tab"), this);
|
||||
@@ -425,8 +427,7 @@ void SplitNotebook::addCustomButtons()
|
||||
settingsBtn->setVisible(!getApp()->settings->hidePreferencesButton.getValue());
|
||||
|
||||
getApp()->settings->hidePreferencesButton.connect(
|
||||
[settingsBtn](bool hide, auto) { settingsBtn->setVisible(!hide); },
|
||||
this->connections_);
|
||||
[settingsBtn](bool hide, auto) { settingsBtn->setVisible(!hide); }, this->connections_);
|
||||
|
||||
settingsBtn->setIcon(NotebookButton::Settings);
|
||||
|
||||
|
||||
@@ -159,8 +159,8 @@ void Window::addLayout()
|
||||
|
||||
void Window::addCustomTitlebarButtons()
|
||||
{
|
||||
return_unless(this->hasCustomWindowFrame());
|
||||
return_unless(this->type_ == Type::Main);
|
||||
if (!this->hasCustomWindowFrame()) return;
|
||||
if (this->type_ != Type::Main) return;
|
||||
|
||||
// settings
|
||||
this->addTitleBarButton(TitleBarButton::Settings, [] {
|
||||
|
||||
@@ -46,7 +46,7 @@ EmotePopup::EmotePopup()
|
||||
|
||||
void EmotePopup::loadChannel(ChannelPtr _channel)
|
||||
{
|
||||
this->setWindowTitle("Emotes from " + _channel->name);
|
||||
this->setWindowTitle("Emotes from " + _channel->getName());
|
||||
|
||||
TwitchChannel *channel = dynamic_cast<TwitchChannel *>(_channel.get());
|
||||
|
||||
@@ -70,21 +70,19 @@ void EmotePopup::loadChannel(ChannelPtr _channel)
|
||||
builder2.getMessage()->flags |= Message::Centered;
|
||||
builder2.getMessage()->flags |= Message::DisableCompactEmotes;
|
||||
|
||||
map.each([&](const QString &key, const EmoteData &value) {
|
||||
builder2.append((new EmoteElement(value, MessageElement::Flags::AlwaysShow))
|
||||
->setLink(Link(Link::InsertText, key)));
|
||||
});
|
||||
for (auto emote : map) {
|
||||
builder2.append((new EmoteElement(emote.second, MessageElement::Flags::AlwaysShow))
|
||||
->setLink(Link(Link::InsertText, emote.first.string)));
|
||||
}
|
||||
|
||||
emoteChannel->addMessage(builder2.getMessage());
|
||||
};
|
||||
|
||||
auto app = getApp();
|
||||
|
||||
QString userID = app->accounts->twitch.getCurrent()->getUserId();
|
||||
|
||||
// fourtf: the entire emote manager needs to be refactored so there's no point in trying to
|
||||
// fix this pile of garbage
|
||||
for (const auto &set : app->emotes->twitch.emotes[userID].emoteSets) {
|
||||
for (const auto &set : app->accounts->twitch.getCurrent()->accessEmotes()->emoteSets) {
|
||||
// TITLE
|
||||
MessageBuilder builder1;
|
||||
|
||||
@@ -110,20 +108,22 @@ void EmotePopup::loadChannel(ChannelPtr _channel)
|
||||
builder2.getMessage()->flags |= Message::DisableCompactEmotes;
|
||||
|
||||
for (const auto &emote : set->emotes) {
|
||||
[&](const QString &key, const EmoteData &value) {
|
||||
builder2.append((new EmoteElement(value, MessageElement::Flags::AlwaysShow))
|
||||
->setLink(Link(Link::InsertText, key)));
|
||||
}(emote.code, app->emotes->twitch.getEmoteById(emote.id, emote.code));
|
||||
builder2.append(
|
||||
(new EmoteElement(app->emotes->twitch.getOrCreateEmote(emote.id, emote.name),
|
||||
MessageElement::Flags::AlwaysShow))
|
||||
->setLink(Link(Link::InsertText, emote.name.string)));
|
||||
}
|
||||
|
||||
emoteChannel->addMessage(builder2.getMessage());
|
||||
}
|
||||
|
||||
addEmotes(app->emotes->bttv.globalEmotes, "BetterTTV Global Emotes", "BetterTTV Global Emote");
|
||||
addEmotes(channel->getBttvEmotes(), "BetterTTV Channel Emotes", "BetterTTV Channel Emote");
|
||||
addEmotes(app->emotes->ffz.globalEmotes, "FrankerFaceZ Global Emotes",
|
||||
"FrankerFaceZ Global Emote");
|
||||
addEmotes(channel->getFfzEmotes(), "FrankerFaceZ Channel Emotes", "FrankerFaceZ Channel Emote");
|
||||
addEmotes(*app->emotes->bttv.accessGlobalEmotes(), "BetterTTV Global Emotes",
|
||||
"BetterTTV Global Emote");
|
||||
addEmotes(*channel->accessBttvEmotes(), "BetterTTV Channel Emotes", "BetterTTV Channel Emote");
|
||||
// addEmotes(*app->emotes->ffz.accessGlobalEmotes(), "FrankerFaceZ Global Emotes",
|
||||
// "FrankerFaceZ Global Emote");
|
||||
addEmotes(*channel->accessFfzEmotes(), "FrankerFaceZ Channel Emotes",
|
||||
"FrankerFaceZ Channel Emote");
|
||||
|
||||
this->viewEmotes_->setChannel(emoteChannel);
|
||||
}
|
||||
@@ -146,9 +146,9 @@ void EmotePopup::loadEmojis()
|
||||
builder.getMessage()->flags |= Message::Centered;
|
||||
builder.getMessage()->flags |= Message::DisableCompactEmotes;
|
||||
|
||||
emojis.each([&builder](const QString &key, const auto &value) {
|
||||
emojis.each([&builder](const auto &key, const auto &value) {
|
||||
builder.append(
|
||||
(new EmoteElement(value->emoteData, MessageElement::Flags::AlwaysShow))
|
||||
(new EmoteElement(value->emote, MessageElement::Flags::AlwaysShow))
|
||||
->setLink(Link(Link::Type::InsertText, ":" + value->shortCodes[0] + ":")));
|
||||
});
|
||||
emojiChannel->addMessage(builder.getMessage());
|
||||
|
||||
@@ -34,8 +34,9 @@ void LogsPopup::setInfo(ChannelPtr channel, QString userName)
|
||||
{
|
||||
this->channel_ = channel;
|
||||
this->userName_ = userName;
|
||||
this->setWindowTitle(this->userName_ + "'s logs in #" + this->channel_->name);
|
||||
this->getRoomID();
|
||||
this->setWindowTitle(this->userName_ + "'s logs in #" + this->channel_->getName());
|
||||
this->getLogviewerLogs();
|
||||
}
|
||||
|
||||
void LogsPopup::setMessages(std::vector<MessagePtr> &messages)
|
||||
@@ -53,7 +54,7 @@ void LogsPopup::getRoomID()
|
||||
return;
|
||||
}
|
||||
|
||||
QString channelName = twitchChannel->name;
|
||||
QString channelName = twitchChannel->getName();
|
||||
|
||||
QString url = QString("https://cbenni.com/api/channel/%1").arg(channelName);
|
||||
|
||||
@@ -65,11 +66,11 @@ void LogsPopup::getRoomID()
|
||||
return true;
|
||||
});
|
||||
|
||||
req.onSuccess([this, channelName](auto result) {
|
||||
req.onSuccess([this, channelName](auto result) -> Outcome {
|
||||
auto data = result.parseJson();
|
||||
this->roomID_ = data.value("channel")["id"].toInt();
|
||||
this->roomID_ = data.value("channel").toObject()["id"].toInt();
|
||||
this->getLogviewerLogs();
|
||||
return true;
|
||||
return Success;
|
||||
});
|
||||
|
||||
req.execute();
|
||||
@@ -82,7 +83,7 @@ void LogsPopup::getLogviewerLogs()
|
||||
return;
|
||||
}
|
||||
|
||||
QString channelName = twitchChannel->name;
|
||||
QString channelName = twitchChannel->getName();
|
||||
|
||||
auto url = QString("https://cbenni.com/api/logs/%1/?nick=%2&before=500")
|
||||
.arg(channelName, this->userName_);
|
||||
@@ -95,7 +96,7 @@ void LogsPopup::getLogviewerLogs()
|
||||
return true;
|
||||
});
|
||||
|
||||
req.onSuccess([this, channelName](auto result) {
|
||||
req.onSuccess([this, channelName](auto result) -> Outcome {
|
||||
auto data = result.parseJson();
|
||||
std::vector<MessagePtr> messages;
|
||||
|
||||
@@ -118,7 +119,7 @@ void LogsPopup::getLogviewerLogs()
|
||||
};
|
||||
this->setMessages(messages);
|
||||
|
||||
return true;
|
||||
return Success;
|
||||
});
|
||||
|
||||
req.execute();
|
||||
@@ -131,7 +132,7 @@ void LogsPopup::getOverrustleLogs()
|
||||
return;
|
||||
}
|
||||
|
||||
QString channelName = twitchChannel->name;
|
||||
QString channelName = twitchChannel->getName();
|
||||
|
||||
QString url = QString("https://overrustlelogs.net/api/v1/stalk/%1/%2.json?limit=500")
|
||||
.arg(channelName, this->userName_);
|
||||
@@ -149,7 +150,7 @@ void LogsPopup::getOverrustleLogs()
|
||||
return true;
|
||||
});
|
||||
|
||||
req.onSuccess([this, channelName](auto result) {
|
||||
req.onSuccess([this, channelName](auto result) -> Outcome {
|
||||
auto data = result.parseJson();
|
||||
std::vector<MessagePtr> messages;
|
||||
if (data.contains("lines")) {
|
||||
@@ -170,7 +171,7 @@ void LogsPopup::getOverrustleLogs()
|
||||
}
|
||||
this->setMessages(messages);
|
||||
|
||||
return true;
|
||||
return Success;
|
||||
});
|
||||
|
||||
req.execute();
|
||||
|
||||
@@ -154,7 +154,7 @@ void SelectChannelDialog::setSelectedChannel(IndirectChannel _channel)
|
||||
case Channel::Type::Twitch: {
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
this->ui_.twitch.channel->setFocus();
|
||||
this->ui_.twitch.channelName->setText(channel->name);
|
||||
this->ui_.twitch.channelName->setText(channel->getName());
|
||||
} break;
|
||||
case Channel::Type::TwitchWatching: {
|
||||
this->ui_.notebook->selectIndex(TAB_TWITCH);
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <QCheckBox>
|
||||
#include <QDesktopServices>
|
||||
#include <QLabel>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#define TEXT_FOLLOWERS "Followers: "
|
||||
#define TEXT_VIEWS "Views: "
|
||||
@@ -281,7 +283,7 @@ void UserInfoPopup::updateUserData()
|
||||
auto request = NetworkRequest::twitchRequest(url);
|
||||
request.setCaller(this);
|
||||
|
||||
request.onSuccess([this](auto result) {
|
||||
request.onSuccess([this](auto result) -> Outcome {
|
||||
auto obj = result.parseJson();
|
||||
this->ui_.followerCountLabel->setText(TEXT_FOLLOWERS +
|
||||
QString::number(obj.value("followers").toInt()));
|
||||
@@ -292,7 +294,7 @@ void UserInfoPopup::updateUserData()
|
||||
|
||||
this->loadAvatar(QUrl(obj.value("logo").toString()));
|
||||
|
||||
return true;
|
||||
return Success;
|
||||
});
|
||||
|
||||
request.execute();
|
||||
|
||||
@@ -32,6 +32,58 @@
|
||||
#define CHAT_HOVER_PAUSE_DURATION 1000
|
||||
|
||||
namespace chatterino {
|
||||
namespace {
|
||||
void addEmoteContextMenuItems(const Emote &emote, MessageElement::Flags creatorFlags, QMenu &menu)
|
||||
{
|
||||
auto openAction = menu.addAction("Open");
|
||||
auto openMenu = new QMenu;
|
||||
openAction->setMenu(openMenu);
|
||||
|
||||
auto copyAction = menu.addAction("Copy");
|
||||
auto copyMenu = new QMenu;
|
||||
copyAction->setMenu(copyMenu);
|
||||
|
||||
// see if the QMenu actually gets destroyed
|
||||
QObject::connect(openMenu, &QMenu::destroyed, [] {
|
||||
QMessageBox(QMessageBox::Information, "xD", "the menu got deleted").exec();
|
||||
});
|
||||
|
||||
// Add copy and open links for 1x, 2x, 3x
|
||||
auto addImageLink = [&](const ImagePtr &image, char scale) {
|
||||
if (!image->empty()) {
|
||||
copyMenu->addAction(QString(scale) + "x link", [url = image->url()] {
|
||||
QApplication::clipboard()->setText(url.string);
|
||||
});
|
||||
openMenu->addAction(QString(scale) + "x link", [url = image->url()] {
|
||||
QDesktopServices::openUrl(QUrl(url.string));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
addImageLink(emote.images.getImage1(), '1');
|
||||
addImageLink(emote.images.getImage2(), '2');
|
||||
addImageLink(emote.images.getImage3(), '3');
|
||||
|
||||
// Copy and open emote page link
|
||||
auto addPageLink = [&](const QString &name) {
|
||||
copyMenu->addSeparator();
|
||||
openMenu->addSeparator();
|
||||
|
||||
copyMenu->addAction("Copy " + name + " emote link", [url = emote.homePage] {
|
||||
QApplication::clipboard()->setText(url.string); //
|
||||
});
|
||||
openMenu->addAction("Open " + name + " emote link", [url = emote.homePage] {
|
||||
QDesktopServices::openUrl(QUrl(url.string)); //
|
||||
});
|
||||
};
|
||||
|
||||
if (creatorFlags & MessageElement::Flags::BttvEmote) {
|
||||
addPageLink("BTTV");
|
||||
} else if (creatorFlags & MessageElement::Flags::FfzEmote) {
|
||||
addPageLink("FFZ");
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ChannelView::ChannelView(BaseWidget *parent)
|
||||
: BaseWidget(parent)
|
||||
@@ -988,74 +1040,8 @@ void ChannelView::addContextMenuItems(const MessageLayoutElement *hoveredElement
|
||||
|
||||
// Emote actions
|
||||
if (creatorFlags & (MessageElement::Flags::EmoteImages | MessageElement::Flags::EmojiImage)) {
|
||||
const auto &emoteElement = static_cast<const EmoteElement &>(creator);
|
||||
|
||||
// TODO: We might want to add direct "Open image" variants alongside the Copy
|
||||
// actions
|
||||
if (emoteElement.data.image1x != nullptr) {
|
||||
QAction *addEntry = menu->addAction("Copy emote link...");
|
||||
|
||||
QMenu *procmenu = new QMenu;
|
||||
addEntry->setMenu(procmenu);
|
||||
procmenu->addAction("Copy 1x link", [url = emoteElement.data.image1x->getUrl()] {
|
||||
QApplication::clipboard()->setText(url); //
|
||||
});
|
||||
if (emoteElement.data.image2x != nullptr) {
|
||||
procmenu->addAction("Copy 2x link", [url = emoteElement.data.image2x->getUrl()] {
|
||||
QApplication::clipboard()->setText(url); //
|
||||
});
|
||||
}
|
||||
if (emoteElement.data.image3x != nullptr) {
|
||||
procmenu->addAction("Copy 3x link", [url = emoteElement.data.image3x->getUrl()] {
|
||||
QApplication::clipboard()->setText(url); //
|
||||
});
|
||||
}
|
||||
if ((creatorFlags & MessageElement::Flags::BttvEmote) != 0) {
|
||||
procmenu->addSeparator();
|
||||
QString emotePageLink = emoteElement.data.pageLink;
|
||||
procmenu->addAction("Copy BTTV emote link", [emotePageLink] {
|
||||
QApplication::clipboard()->setText(emotePageLink); //
|
||||
});
|
||||
} else if ((creatorFlags & MessageElement::Flags::FfzEmote) != 0) {
|
||||
procmenu->addSeparator();
|
||||
QString emotePageLink = emoteElement.data.pageLink;
|
||||
procmenu->addAction("Copy FFZ emote link", [emotePageLink] {
|
||||
QApplication::clipboard()->setText(emotePageLink); //
|
||||
});
|
||||
}
|
||||
}
|
||||
if (emoteElement.data.image1x != nullptr) {
|
||||
QAction *addEntry = menu->addAction("Open emote link...");
|
||||
|
||||
QMenu *procmenu = new QMenu;
|
||||
addEntry->setMenu(procmenu);
|
||||
procmenu->addAction("Open 1x link", [url = emoteElement.data.image1x->getUrl()] {
|
||||
QDesktopServices::openUrl(QUrl(url)); //
|
||||
});
|
||||
if (emoteElement.data.image2x != nullptr) {
|
||||
procmenu->addAction("Open 2x link", [url = emoteElement.data.image2x->getUrl()] {
|
||||
QDesktopServices::openUrl(QUrl(url)); //
|
||||
});
|
||||
}
|
||||
if (emoteElement.data.image3x != nullptr) {
|
||||
procmenu->addAction("Open 3x link", [url = emoteElement.data.image3x->getUrl()] {
|
||||
QDesktopServices::openUrl(QUrl(url)); //
|
||||
});
|
||||
}
|
||||
if ((creatorFlags & MessageElement::Flags::BttvEmote) != 0) {
|
||||
procmenu->addSeparator();
|
||||
QString emotePageLink = emoteElement.data.pageLink;
|
||||
procmenu->addAction("Open BTTV emote link", [emotePageLink] {
|
||||
QDesktopServices::openUrl(QUrl(emotePageLink)); //
|
||||
});
|
||||
} else if ((creatorFlags & MessageElement::Flags::FfzEmote) != 0) {
|
||||
procmenu->addSeparator();
|
||||
QString emotePageLink = emoteElement.data.pageLink;
|
||||
procmenu->addAction("Open FFZ emote link", [emotePageLink] {
|
||||
QDesktopServices::openUrl(QUrl(emotePageLink)); //
|
||||
});
|
||||
}
|
||||
}
|
||||
const auto emoteElement = dynamic_cast<const EmoteElement *>(&creator);
|
||||
if (emoteElement) addEmoteContextMenuItems(*emoteElement->getEmote(), creatorFlags, *menu);
|
||||
}
|
||||
|
||||
// add seperator
|
||||
@@ -1204,8 +1190,7 @@ bool ChannelView::tryGetMessageAt(QPoint p, std::shared_ptr<MessageLayout> &_mes
|
||||
|
||||
int ChannelView::getLayoutWidth() const
|
||||
{
|
||||
if (this->scrollBar_.isVisible())
|
||||
return int(this->width() - 8 * this->getScale());
|
||||
if (this->scrollBar_.isVisible()) return int(this->width() - 8 * this->getScale());
|
||||
|
||||
return this->width();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ DebugPopup::DebugPopup()
|
||||
auto *text = new QLabel(this);
|
||||
auto *timer = new QTimer(this);
|
||||
|
||||
timer->setInterval(1000);
|
||||
timer->setInterval(300);
|
||||
QObject::connect(timer, &QTimer::timeout,
|
||||
[text] { text->setText(DebugCount::getDebugText()); });
|
||||
timer->start();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWindow>
|
||||
#include <QWidget>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ void SearchPopup::setChannel(ChannelPtr channel)
|
||||
this->snapshot_ = channel->getMessageSnapshot();
|
||||
this->performSearch();
|
||||
|
||||
this->setWindowTitle("Searching in " + channel->name + "s history");
|
||||
this->setWindowTitle("Searching in " + channel->getName() + "s history");
|
||||
}
|
||||
|
||||
void SearchPopup::performSearch()
|
||||
|
||||
@@ -28,7 +28,7 @@ AboutPage::AboutPage()
|
||||
auto layout = widget.setLayoutType<QVBoxLayout>();
|
||||
{
|
||||
QPixmap pixmap;
|
||||
pixmap.load(":/images/aboutlogo.png");
|
||||
pixmap.load(":/settings/aboutlogo.png");
|
||||
|
||||
auto logo = layout.emplace<QLabel>().assign(&this->logo_);
|
||||
logo->setPixmap(pixmap);
|
||||
|
||||
@@ -24,6 +24,8 @@ FeelPage::FeelPage()
|
||||
|
||||
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
|
||||
|
||||
// layout.append(this->createCheckBox("Use a seperate write connection.",
|
||||
// getSettings()->twitchSeperateWriteConnection));
|
||||
layout.append(this->createCheckBox(SCROLL_SMOOTH, getSettings()->enableSmoothScrolling));
|
||||
layout.append(
|
||||
this->createCheckBox(SCROLL_NEWMSG, getSettings()->enableSmoothScrollingNewMessages));
|
||||
|
||||
@@ -293,15 +293,18 @@ ChannelPtr LookPage::createPreviewChannel()
|
||||
{
|
||||
auto message = MessagePtr(new Message());
|
||||
message->addElement(new TimestampElement(QTime(8, 13, 42)));
|
||||
message->addElement(new ImageElement(getApp()->resources->badgeModerator,
|
||||
MessageElement::BadgeChannelAuthority));
|
||||
message->addElement(new ImageElement(getApp()->resources->badgeSubscriber,
|
||||
MessageElement::BadgeSubscription));
|
||||
message->addElement(
|
||||
new ImageElement(Image::fromNonOwningPixmap(&getApp()->resources->twitch.moderator),
|
||||
MessageElement::BadgeChannelAuthority));
|
||||
message->addElement(
|
||||
new ImageElement(Image::fromNonOwningPixmap(&getApp()->resources->twitch.subscriber),
|
||||
MessageElement::BadgeSubscription));
|
||||
message->addElement(new TextElement("username1:", MessageElement::Username,
|
||||
QColor("#0094FF"), FontStyle::ChatMediumBold));
|
||||
message->addElement(new TextElement("This is a preview message", MessageElement::Text));
|
||||
message->addElement(new EmoteElement(EmoteData(getApp()->resources->pajaDank),
|
||||
MessageElement::Flags::AlwaysShow));
|
||||
message->addElement(
|
||||
new ImageElement(Image::fromNonOwningPixmap(&getApp()->resources->pajaDank),
|
||||
MessageElement::Flags::AlwaysShow));
|
||||
message->addElement(new TextElement("@fourtf", TextElement::BoldUsername,
|
||||
MessageColor::Text, FontStyle::ChatMediumBold));
|
||||
message->addElement(new TextElement("@fourtf", TextElement::NonBoldUsername));
|
||||
@@ -310,13 +313,14 @@ ChannelPtr LookPage::createPreviewChannel()
|
||||
{
|
||||
auto message = MessagePtr(new Message());
|
||||
message->addElement(new TimestampElement(QTime(8, 15, 21)));
|
||||
message->addElement(new ImageElement(getApp()->resources->badgePremium,
|
||||
MessageElement::BadgeChannelAuthority));
|
||||
message->addElement(
|
||||
new ImageElement(Image::fromNonOwningPixmap(&getApp()->resources->twitch.broadcaster),
|
||||
MessageElement::BadgeChannelAuthority));
|
||||
message->addElement(new TextElement("username2:", MessageElement::Username,
|
||||
QColor("#FF6A00"), FontStyle::ChatMediumBold));
|
||||
message->addElement(new TextElement("This is another one", MessageElement::Text));
|
||||
message->addElement(
|
||||
new EmoteElement(EmoteData(getApp()->resources->ppHop), MessageElement::BttvEmote));
|
||||
// message->addElement(new ImageElement(
|
||||
// Image::fromNonOwningPixmap(&getApp()->resources->ppHop), MessageElement::BttvEmote));
|
||||
message->addElement(
|
||||
(new TextElement("www.fourtf.com", MessageElement::LowercaseLink, MessageColor::Link))
|
||||
->setLink(Link(Link::Url, "https://www.fourtf.com")));
|
||||
|
||||
@@ -76,7 +76,7 @@ Split::Split(QWidget *parent)
|
||||
createShortcut(this, "CTRL+R", &Split::doChangeChannel);
|
||||
|
||||
// CTRL+F: Search
|
||||
createShortcut(this, "CTRL+F", &Split::doSearch);
|
||||
createShortcut(this, "CTRL+F", &Split::showSearchPopup);
|
||||
|
||||
// F12
|
||||
createShortcut(this, "F10", [] {
|
||||
@@ -378,7 +378,7 @@ void Split::doChangeChannel()
|
||||
auto popup = this->findChildren<QDockWidget *>();
|
||||
if (popup.size() && popup.at(0)->isVisible() && !popup.at(0)->isFloating()) {
|
||||
popup.at(0)->hide();
|
||||
doOpenViewerList();
|
||||
showViewerList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,36 +401,33 @@ void Split::doClearChat()
|
||||
this->view_.clearMessages();
|
||||
}
|
||||
|
||||
void Split::doOpenChannel()
|
||||
void Split::openInBrowser()
|
||||
{
|
||||
ChannelPtr _channel = this->getChannel();
|
||||
TwitchChannel *tc = dynamic_cast<TwitchChannel *>(_channel.get());
|
||||
auto channel = this->getChannel();
|
||||
|
||||
if (tc != nullptr) {
|
||||
QDesktopServices::openUrl("https://twitch.tv/" + tc->name);
|
||||
if (auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get())) {
|
||||
QDesktopServices::openUrl("https://twitch.tv/" + twitchChannel->getName());
|
||||
}
|
||||
}
|
||||
|
||||
void Split::doOpenPopupPlayer()
|
||||
void Split::openInPopupPlayer()
|
||||
{
|
||||
ChannelPtr _channel = this->getChannel();
|
||||
TwitchChannel *tc = dynamic_cast<TwitchChannel *>(_channel.get());
|
||||
|
||||
if (tc != nullptr) {
|
||||
QDesktopServices::openUrl("https://player.twitch.tv/?channel=" + tc->name);
|
||||
ChannelPtr channel = this->getChannel();
|
||||
if (auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get())) {
|
||||
QDesktopServices::openUrl("https://player.twitch.tv/?channel=" + twitchChannel->getName());
|
||||
}
|
||||
}
|
||||
|
||||
void Split::doOpenStreamlink()
|
||||
void Split::openInStreamlink()
|
||||
{
|
||||
try {
|
||||
openStreamlinkForChannel(this->getChannel()->name);
|
||||
openStreamlinkForChannel(this->getChannel()->getName());
|
||||
} catch (const Exception &ex) {
|
||||
Log("Error in doOpenStreamlink: {}", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
void Split::doOpenViewerList()
|
||||
void Split::showViewerList()
|
||||
{
|
||||
auto viewerDock = new QDockWidget("Viewer List", this);
|
||||
viewerDock->setAllowedAreas(Qt::LeftDockWidgetArea);
|
||||
@@ -458,10 +455,10 @@ void Split::doOpenViewerList()
|
||||
auto loadingLabel = new QLabel("Loading...");
|
||||
|
||||
auto request = NetworkRequest::twitchRequest("https://tmi.twitch.tv/group/user/" +
|
||||
this->getChannel()->name + "/chatters");
|
||||
this->getChannel()->getName() + "/chatters");
|
||||
|
||||
request.setCaller(this);
|
||||
request.onSuccess([=](auto result) {
|
||||
request.onSuccess([=](auto result) -> Outcome {
|
||||
auto obj = result.parseJson();
|
||||
QJsonObject chattersObj = obj.value("chatters").toObject();
|
||||
|
||||
@@ -472,7 +469,7 @@ void Split::doOpenViewerList()
|
||||
chattersList->addItem(v.toString());
|
||||
}
|
||||
|
||||
return true;
|
||||
return Success;
|
||||
});
|
||||
|
||||
request.execute();
|
||||
@@ -485,8 +482,7 @@ void Split::doOpenViewerList()
|
||||
chattersList->hide();
|
||||
resultList->clear();
|
||||
for (auto &item : results) {
|
||||
if (!labels.contains(item->text()))
|
||||
resultList->addItem(item->text());
|
||||
if (!labels.contains(item->text())) resultList->addItem(item->text());
|
||||
}
|
||||
resultList->show();
|
||||
} else {
|
||||
@@ -500,13 +496,13 @@ void Split::doOpenViewerList()
|
||||
|
||||
QObject::connect(chattersList, &QListWidget::doubleClicked, this, [=]() {
|
||||
if (!labels.contains(chattersList->currentItem()->text())) {
|
||||
doOpenUserInfoPopup(chattersList->currentItem()->text());
|
||||
showUserInfoPopup(chattersList->currentItem()->text());
|
||||
}
|
||||
});
|
||||
|
||||
QObject::connect(resultList, &QListWidget::doubleClicked, this, [=]() {
|
||||
if (!labels.contains(resultList->currentItem()->text())) {
|
||||
doOpenUserInfoPopup(resultList->currentItem()->text());
|
||||
showUserInfoPopup(resultList->currentItem()->text());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -522,22 +518,22 @@ void Split::doOpenViewerList()
|
||||
viewerDock->show();
|
||||
}
|
||||
|
||||
void Split::doOpenUserInfoPopup(const QString &user)
|
||||
void Split::showUserInfoPopup(const UserName &user)
|
||||
{
|
||||
auto *userPopup = new UserInfoPopup;
|
||||
userPopup->setData(user, this->getChannel());
|
||||
userPopup->setData(user.string, this->getChannel());
|
||||
userPopup->setAttribute(Qt::WA_DeleteOnClose);
|
||||
userPopup->move(QCursor::pos() -
|
||||
QPoint(int(150 * this->getScale()), int(70 * this->getScale())));
|
||||
userPopup->show();
|
||||
}
|
||||
|
||||
void Split::doCopy()
|
||||
void Split::copyToClipboard()
|
||||
{
|
||||
QApplication::clipboard()->setText(this->view_.getSelectedText());
|
||||
}
|
||||
|
||||
void Split::doSearch()
|
||||
void Split::showSearchPopup()
|
||||
{
|
||||
SearchPopup *popup = new SearchPopup();
|
||||
|
||||
@@ -563,26 +559,19 @@ static Iter select_randomly(Iter start, Iter end)
|
||||
|
||||
void Split::drag()
|
||||
{
|
||||
auto container = dynamic_cast<SplitContainer *>(this->parentWidget());
|
||||
|
||||
if (container != nullptr) {
|
||||
if (auto container = dynamic_cast<SplitContainer *>(this->parentWidget())) {
|
||||
SplitContainer::isDraggingSplit = true;
|
||||
SplitContainer::draggingSplit = this;
|
||||
|
||||
auto originalLocation = container->releaseSplit(this);
|
||||
|
||||
QDrag *drag = new QDrag(this);
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
auto drag = new QDrag(this);
|
||||
auto mimeData = new QMimeData;
|
||||
|
||||
mimeData->setData("chatterino/split", "xD");
|
||||
|
||||
drag->setMimeData(mimeData);
|
||||
|
||||
Qt::DropAction dropAction = drag->exec(Qt::MoveAction);
|
||||
|
||||
if (dropAction == Qt::IgnoreAction) {
|
||||
container->insertSplit(this,
|
||||
originalLocation); // SplitContainer::dragOriginalPosition);
|
||||
if (drag->exec(Qt::MoveAction) == Qt::IgnoreAction) {
|
||||
container->insertSplit(this, originalLocation);
|
||||
}
|
||||
|
||||
SplitContainer::isDraggingSplit = false;
|
||||
|
||||
@@ -90,7 +90,11 @@ protected:
|
||||
void focusInEvent(QFocusEvent *event) override;
|
||||
|
||||
private:
|
||||
void doOpenUserInfoPopup(const QString &user);
|
||||
void showUserInfoPopup(const QString &userName)
|
||||
{
|
||||
this->showUserInfoPopup(UserName{userName});
|
||||
}
|
||||
void showUserInfoPopup(const UserName &user);
|
||||
void channelNameUpdated(const QString &newChannelName);
|
||||
void handleModifiers(Qt::KeyboardModifiers modifiers);
|
||||
|
||||
@@ -137,22 +141,22 @@ public slots:
|
||||
void doClearChat();
|
||||
|
||||
// Open link to twitch channel in default browser
|
||||
void doOpenChannel();
|
||||
void openInBrowser();
|
||||
|
||||
// Open popup player of twitch channel in default browser
|
||||
void doOpenPopupPlayer();
|
||||
void openInPopupPlayer();
|
||||
|
||||
// Open twitch channel stream through streamlink
|
||||
void doOpenStreamlink();
|
||||
void openInStreamlink();
|
||||
|
||||
// Copy text from chat
|
||||
void doCopy();
|
||||
void copyToClipboard();
|
||||
|
||||
// Open a search popup
|
||||
void doSearch();
|
||||
void showSearchPopup();
|
||||
|
||||
// Open viewer list of the channel
|
||||
void doOpenViewerList();
|
||||
void showViewerList();
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -464,11 +464,9 @@ void SplitContainer::paintEvent(QPaintEvent *)
|
||||
|
||||
void SplitContainer::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
if (!event->mimeData()->hasFormat("chatterino/split"))
|
||||
return;
|
||||
if (!event->mimeData()->hasFormat("chatterino/split")) return;
|
||||
|
||||
if (!SplitContainer::isDraggingSplit)
|
||||
return;
|
||||
if (!SplitContainer::isDraggingSplit) return;
|
||||
|
||||
this->isDragging_ = true;
|
||||
this->layout();
|
||||
@@ -516,7 +514,7 @@ void SplitContainer::refreshTabTitle()
|
||||
bool first = true;
|
||||
|
||||
for (const auto &chatWidget : this->splits_) {
|
||||
auto channelName = chatWidget->getChannel()->name;
|
||||
auto channelName = chatWidget->getChannel()->getName();
|
||||
if (channelName.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
@@ -851,10 +849,8 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<Dro
|
||||
std::vector<ResizeRect> &resizeRects)
|
||||
{
|
||||
for (std::unique_ptr<Node> &node : this->children_) {
|
||||
if (node->flexH_ <= 0)
|
||||
node->flexH_ = 0;
|
||||
if (node->flexV_ <= 0)
|
||||
node->flexV_ = 0;
|
||||
if (node->flexH_ <= 0) node->flexH_ = 0;
|
||||
if (node->flexV_ <= 0) node->flexV_ = 0;
|
||||
}
|
||||
|
||||
switch (this->type_) {
|
||||
|
||||
@@ -129,8 +129,8 @@ void SplitHeader::addDropdownItems(RippleEffectButton *)
|
||||
this->dropdownMenu_.addAction("Close split", this->split_, &Split::doCloseSplit, QKeySequence(tr("Ctrl+W")));
|
||||
this->dropdownMenu_.addAction("Change channel", this->split_, &Split::doChangeChannel, QKeySequence(tr("Ctrl+R")));
|
||||
this->dropdownMenu_.addSeparator();
|
||||
this->dropdownMenu_.addAction("Viewer list", this->split_, &Split::doOpenViewerList);
|
||||
this->dropdownMenu_.addAction("Search", this->split_, &Split::doSearch, QKeySequence(tr("Ctrl+F")));
|
||||
this->dropdownMenu_.addAction("Viewer list", this->split_, &Split::showViewerList);
|
||||
this->dropdownMenu_.addAction("Search", this->split_, &Split::showSearchPopup, QKeySequence(tr("Ctrl+F")));
|
||||
this->dropdownMenu_.addSeparator();
|
||||
this->dropdownMenu_.addAction("Popup", this->split_, &Split::doPopup);
|
||||
#ifdef USEWEBENGINE
|
||||
@@ -145,11 +145,11 @@ void SplitHeader::addDropdownItems(RippleEffectButton *)
|
||||
}
|
||||
});
|
||||
#endif
|
||||
this->dropdownMenu_.addAction("Open browser", this->split_, &Split::doOpenChannel);
|
||||
this->dropdownMenu_.addAction("Open browser", this->split_, &Split::openInBrowser);
|
||||
#ifndef USEWEBENGINE
|
||||
this->dropdownMenu_.addAction("Open browser popup", this->split_, &Split::doOpenPopupPlayer);
|
||||
this->dropdownMenu_.addAction("Open browser popup", this->split_, &Split::openInPopupPlayer);
|
||||
#endif
|
||||
this->dropdownMenu_.addAction("Open streamlink", this->split_, &Split::doOpenStreamlink);
|
||||
this->dropdownMenu_.addAction("Open streamlink", this->split_, &Split::openInStreamlink);
|
||||
this->dropdownMenu_.addSeparator();
|
||||
this->dropdownMenu_.addAction("Reload channel emotes", this, SLOT(menuReloadChannelEmotes()));
|
||||
this->dropdownMenu_.addAction("Reconnect", this, SLOT(menuManualReconnect()));
|
||||
@@ -317,7 +317,7 @@ void SplitHeader::updateChannelText()
|
||||
auto indirectChannel = this->split_->getIndirectChannel();
|
||||
auto channel = this->split_->getChannel();
|
||||
|
||||
QString title = channel->name;
|
||||
QString title = channel->getName();
|
||||
|
||||
if (indirectChannel.getType() == Channel::Type::TwitchWatching) {
|
||||
title = "watching: " + (title.isEmpty() ? "none" : title);
|
||||
@@ -375,8 +375,8 @@ void SplitHeader::updateModerationModeIcon()
|
||||
auto app = getApp();
|
||||
|
||||
this->moderationButton_->setPixmap(this->split_->getModerationMode()
|
||||
? *app->resources->moderationmode_enabled->getPixmap()
|
||||
: *app->resources->moderationmode_disabled->getPixmap());
|
||||
? app->resources->buttons.modModeEnabled
|
||||
: app->resources->buttons.modModeDisabled);
|
||||
|
||||
bool modButtonVisible = false;
|
||||
ChannelPtr channel = this->split_->getChannel();
|
||||
@@ -499,9 +499,9 @@ void SplitHeader::themeChangedEvent()
|
||||
}
|
||||
|
||||
if (this->theme->isLightTheme()) {
|
||||
this->dropdownButton_->setPixmap(QPixmap(":/images/menu_black.png"));
|
||||
this->dropdownButton_->setPixmap(getApp()->resources->buttons.menuDark);
|
||||
} else {
|
||||
this->dropdownButton_->setPixmap(QPixmap(":/images/menu_white.png"));
|
||||
this->dropdownButton_->setPixmap(getApp()->resources->buttons.menuLight);
|
||||
}
|
||||
|
||||
this->titleLabel->setPalette(palette);
|
||||
|
||||
@@ -130,7 +130,7 @@ void SplitInput::updateEmoteButton()
|
||||
{
|
||||
float scale = this->getScale();
|
||||
|
||||
QString text = "<img src=':/images/emote.svg' width='xD' height='xD' />";
|
||||
QString text = "<img src=':/buttons/emote.svg' width='xD' height='xD' />";
|
||||
text.replace("xD", QString::number(int(12 * scale)));
|
||||
|
||||
if (this->theme->isLightTheme()) {
|
||||
@@ -254,7 +254,7 @@ void SplitInput::installKeyPressedEvent()
|
||||
}
|
||||
} else if (event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier) {
|
||||
if (this->split_->view_.hasSelection()) {
|
||||
this->split_->doCopy();
|
||||
this->split_->copyToClipboard();
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,12 +29,11 @@ SplitOverlay::SplitOverlay(Split *parent)
|
||||
layout->setColumnStretch(1, 1);
|
||||
layout->setColumnStretch(3, 1);
|
||||
|
||||
QPushButton *move = new QPushButton(getApp()->resources->split.move, QString());
|
||||
QPushButton *left = this->left_ = new QPushButton(getApp()->resources->split.left, QString());
|
||||
QPushButton *right = this->right_ =
|
||||
new QPushButton(getApp()->resources->split.right, QString());
|
||||
QPushButton *up = this->up_ = new QPushButton(getApp()->resources->split.up, QString());
|
||||
QPushButton *down = this->down_ = new QPushButton(getApp()->resources->split.down, QString());
|
||||
auto *move = new QPushButton(getApp()->resources->split.move, QString());
|
||||
auto *left = this->left_ = new QPushButton(getApp()->resources->split.left, QString());
|
||||
auto *right = this->right_ = new QPushButton(getApp()->resources->split.right, QString());
|
||||
auto *up = this->up_ = new QPushButton(getApp()->resources->split.up, QString());
|
||||
auto *down = this->down_ = new QPushButton(getApp()->resources->split.down, QString());
|
||||
|
||||
move->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
left->setGraphicsEffect(new QGraphicsOpacityEffect(this));
|
||||
|
||||
Reference in New Issue
Block a user