Merge branch 'master' into apa-bits

This commit is contained in:
fourtf
2019-09-08 18:02:58 +02:00
committed by GitHub
94 changed files with 1178 additions and 1640 deletions
@@ -1,4 +1,4 @@
#include "widgets/AccountSwitchPopupWidget.hpp"
#include "widgets/AccountSwitchPopup.hpp"
#include "debug/Log.hpp"
#include "widgets/dialogs/SettingsDialog.hpp"
@@ -10,10 +10,10 @@
namespace chatterino {
AccountSwitchPopupWidget::AccountSwitchPopupWidget(QWidget *parent)
: QWidget(parent)
AccountSwitchPopup::AccountSwitchPopup(QWidget *parent)
: BaseWindow(parent,
BaseWindow::Flags(BaseWindow::TopMost | BaseWindow::Frameless))
{
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
#ifdef Q_OS_LINUX
this->setWindowFlag(Qt::Popup);
#endif
@@ -38,22 +38,22 @@ AccountSwitchPopupWidget::AccountSwitchPopupWidget(QWidget *parent)
SettingsDialog::showDialog(SettingsDialogPreference::Accounts); //
});
this->setLayout(vbox);
this->getLayoutContainer()->setLayout(vbox);
// this->setStyleSheet("background: #333");
this->setScaleIndependantSize(200, 200);
}
void AccountSwitchPopupWidget::refresh()
void AccountSwitchPopup::refresh()
{
this->ui_.accountSwitchWidget->refresh();
}
void AccountSwitchPopupWidget::focusOutEvent(QFocusEvent *)
void AccountSwitchPopup::focusOutEvent(QFocusEvent *)
{
this->hide();
}
void AccountSwitchPopupWidget::paintEvent(QPaintEvent *)
void AccountSwitchPopup::paintEvent(QPaintEvent *)
{
QPainter painter(this);
@@ -1,17 +1,18 @@
#pragma once
#include "widgets/AccountSwitchWidget.hpp"
#include "widgets/BaseWindow.hpp"
#include <QWidget>
namespace chatterino {
class AccountSwitchPopupWidget : public QWidget
class AccountSwitchPopup : public BaseWindow
{
Q_OBJECT
public:
AccountSwitchPopupWidget(QWidget *parent = nullptr);
AccountSwitchPopup(QWidget *parent = nullptr);
void refresh();
+7 -7
View File
@@ -10,7 +10,7 @@
#include "singletons/WindowManager.hpp"
#include "util/InitUpdateButton.hpp"
#include "util/Shortcut.hpp"
#include "widgets/AccountSwitchPopupWidget.hpp"
#include "widgets/AccountSwitchPopup.hpp"
#include "widgets/Notebook.hpp"
#include "widgets/dialogs/SettingsDialog.hpp"
#include "widgets/dialogs/UpdateDialog.hpp"
@@ -377,13 +377,13 @@ void Window::onAccountSelected()
{
auto user = getApp()->accounts->twitch.getCurrent();
#ifdef CHATTERINO_NIGHTLY_VERSION_STRING
auto windowTitleEnd =
QString("Chatterino Nightly " CHATTERINO_VERSION
" (" UGLYMACROHACK(CHATTERINO_NIGHTLY_VERSION_STRING) ")");
#else
//#ifdef CHATTERINO_NIGHTLY_VERSION_STRING
// auto windowTitleEnd =
// QString("Chatterino Nightly " CHATTERINO_VERSION
// " (" UGLYMACROHACK(CHATTERINO_NIGHTLY_VERSION_STRING) ")");
//#else
auto windowTitleEnd = QString("Chatterino " CHATTERINO_VERSION);
#endif
//#endif
this->setWindowTitle(windowTitleEnd);
+24 -25
View File
@@ -4,6 +4,7 @@
#include "common/Channel.hpp"
#include "common/NetworkRequest.hpp"
#include "debug/Log.hpp"
#include "messages/Message.hpp"
#include "providers/twitch/PartialTwitchUser.hpp"
#include "providers/twitch/TwitchChannel.hpp"
#include "providers/twitch/TwitchMessageBuilder.hpp"
@@ -20,34 +21,30 @@ namespace chatterino {
LogsPopup::LogsPopup()
: channel_(Channel::getEmpty())
{
this->initLayout();
this->resize(400, 600);
}
void LogsPopup::initLayout()
{
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setMargin(0);
this->channelView_ = new ChannelView(this);
layout->addWidget(this->channelView_);
this->setLayout(layout);
}
void LogsPopup::setChannelName(QString channelName)
{
this->channelName_ = channelName;
}
void LogsPopup::setChannel(std::shared_ptr<Channel> channel)
void LogsPopup::setChannel(const ChannelPtr &channel)
{
this->channel_ = channel;
this->updateWindowTitle();
}
void LogsPopup::setTargetUserName(QString userName)
void LogsPopup::setChannelName(const QString &channelName)
{
this->channelName_ = channelName;
this->updateWindowTitle();
}
void LogsPopup::setTargetUserName(const QString &userName)
{
this->userName_ = userName;
this->updateWindowTitle();
}
void LogsPopup::updateWindowTitle()
{
this->setWindowTitle(this->userName_ + "'s logs in #" + this->channelName_);
}
void LogsPopup::getLogs()
@@ -60,8 +57,6 @@ void LogsPopup::getLogs()
this->channelName_ = twitchChannel->getName();
this->getLogviewerLogs(twitchChannel->roomId());
this->setWindowTitle(this->userName_ + "'s logs in #" +
this->channelName_);
return;
}
}
@@ -83,7 +78,7 @@ void LogsPopup::setMessages(std::vector<MessagePtr> &messages)
ChannelPtr logsChannel(new Channel("logs", Channel::Type::Misc));
logsChannel->addMessagesAtStart(messages);
this->channelView_->setChannel(logsChannel);
SearchPopup::setChannel(logsChannel);
}
void LogsPopup::getLogviewerLogs(const QString &roomID)
@@ -121,6 +116,8 @@ void LogsPopup::getLogviewerLogs(const QString &roomID)
static_cast<Communi::IrcPrivateMessage *>(ircMessage);
TwitchMessageBuilder builder(this->channel_.get(), privMsg,
args);
builder.message().searchText = message;
messages.push_back(builder.build());
}
@@ -165,6 +162,7 @@ void LogsPopup::getOverrustleLogs()
for (auto i : dataMessages)
{
QJsonObject singleMessage = i.toObject();
auto text = singleMessage.value("text").toString();
QTime timeStamp =
QDateTime::fromSecsSinceEpoch(
singleMessage.value("timestamp").toInt())
@@ -175,9 +173,9 @@ void LogsPopup::getOverrustleLogs()
builder.emplace<TextElement>(this->userName_,
MessageElementFlag::Username,
MessageColor::System);
builder.emplace<TextElement>(
singleMessage.value("text").toString(),
MessageElementFlag::Text, MessageColor::Text);
builder.emplace<TextElement>(text, MessageElementFlag::Text,
MessageColor::Text);
builder.message().searchText = text;
messages.push_back(builder.release());
}
}
@@ -191,4 +189,5 @@ void LogsPopup::getOverrustleLogs()
})
.execute();
}
} // namespace chatterino
+8 -16
View File
@@ -1,37 +1,29 @@
#pragma once
#include "widgets/BaseWindow.hpp"
#include "widgets/helper/SearchPopup.hpp"
namespace chatterino {
class Channel;
class ChannelView;
class Channel;
using ChannelPtr = std::shared_ptr<Channel>;
struct Message;
using MessagePtr = std::shared_ptr<const Message>;
class LogsPopup : public BaseWindow
class LogsPopup : public SearchPopup
{
public:
LogsPopup();
void setChannelName(QString channelName);
void setChannel(std::shared_ptr<Channel> channel);
void setTargetUserName(QString userName);
void setChannel(const ChannelPtr &channel) override;
void setChannelName(const QString &channelName);
void setTargetUserName(const QString &userName);
void getLogs();
protected:
void updateWindowTitle() override;
private:
ChannelView *channelView_ = nullptr;
ChannelPtr channel_;
QString userName_;
QString channelName_;
void initLayout();
void setMessages(std::vector<MessagePtr> &messages);
void getOverrustleLogs();
void getLogviewerLogs(const QString &roomID);
+93 -43
View File
@@ -1,27 +1,23 @@
#include "widgets/dialogs/SettingsDialog.hpp"
#include "Application.hpp"
#include "singletons/Resources.hpp"
#include "util/LayoutCreator.hpp"
#include "widgets/helper/Button.hpp"
#include "widgets/helper/SettingsDialogTab.hpp"
#include "widgets/settingspages/AboutPage.hpp"
#include "widgets/settingspages/AccountsPage.hpp"
#include "widgets/settingspages/AdvancedPage.hpp"
#include "widgets/settingspages/BrowserExtensionPage.hpp"
#include "widgets/settingspages/CommandPage.hpp"
#include "widgets/settingspages/EmotesPage.hpp"
#include "widgets/settingspages/ExternalToolsPage.hpp"
#include "widgets/settingspages/FeelPage.hpp"
#include "widgets/settingspages/GeneralPage.hpp"
#include "widgets/settingspages/HighlightingPage.hpp"
#include "widgets/settingspages/IgnoresPage.hpp"
#include "widgets/settingspages/KeyboardSettingsPage.hpp"
#include "widgets/settingspages/LogsPage.hpp"
#include "widgets/settingspages/LookPage.hpp"
#include "widgets/settingspages/ModerationPage.hpp"
#include "widgets/settingspages/NotificationPage.hpp"
#include "widgets/settingspages/SpecialChannelsPage.hpp"
#include <QDialogButtonBox>
#include <QLineEdit>
namespace chatterino {
@@ -30,6 +26,8 @@ SettingsDialog *SettingsDialog::handle = nullptr;
SettingsDialog::SettingsDialog()
: BaseWindow(nullptr, BaseWindow::DisableCustomScaling)
{
this->setWindowTitle("Chatterino Settings");
this->initUi();
this->addTabs();
@@ -43,39 +41,55 @@ SettingsDialog::SettingsDialog()
void SettingsDialog::initUi()
{
LayoutCreator<SettingsDialog> layoutCreator(this);
auto outerBox = LayoutCreator<SettingsDialog>(this)
.setLayoutType<QVBoxLayout>()
.withoutSpacing();
// tab pages
layoutCreator.setLayoutType<QHBoxLayout>()
.withoutSpacing()
.emplace<QWidget>()
// TOP
auto title = outerBox.emplace<PageHeader>();
auto edit = LayoutCreator<PageHeader>(title.getElement())
.setLayoutType<QHBoxLayout>()
.withoutMargin()
.emplace<QLineEdit>()
.assign(&this->ui_.search);
edit->setPlaceholderText("Find in settings...");
QObject::connect(edit.getElement(), &QLineEdit::textChanged, this,
&SettingsDialog::filterElements);
// CENTER
auto centerBox =
outerBox.emplace<QHBoxLayout>().withoutMargin().withoutSpacing();
// left side (tabs)
centerBox.emplace<QWidget>()
.assign(&this->ui_.tabContainerContainer)
.emplace<QVBoxLayout>()
.setLayoutType<QVBoxLayout>()
.withoutMargin()
.assign(&this->ui_.tabContainer);
this->ui_.tabContainerContainer->layout()->setContentsMargins(8, 8, 0, 39);
this->layout()->setSpacing(0);
// right side layout
auto right = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
// right side (pages)
auto right =
centerBox.emplace<QVBoxLayout>().withoutMargin().withoutSpacing();
{
right.emplace<QStackedLayout>()
.assign(&this->ui_.pageStack)
.withoutMargin();
auto buttons = right.emplace<QDialogButtonBox>(Qt::Horizontal);
{
this->ui_.okButton =
buttons->addButton("Ok", QDialogButtonBox::YesRole);
this->ui_.cancelButton =
buttons->addButton("Cancel", QDialogButtonBox::NoRole);
}
}
this->ui_.pageStack->setMargin(0);
outerBox->addSpacing(12);
// BOTTOM
auto buttons = outerBox.emplace<QDialogButtonBox>(Qt::Horizontal);
{
this->ui_.okButton =
buttons->addButton("Ok", QDialogButtonBox::YesRole);
this->ui_.cancelButton =
buttons->addButton("Cancel", QDialogButtonBox::NoRole);
}
// ---- misc
this->ui_.tabContainerContainer->setObjectName("tabWidget");
this->ui_.pageStack->setObjectName("pages");
@@ -86,6 +100,50 @@ void SettingsDialog::initUi()
&SettingsDialog::onCancelClicked);
}
void SettingsDialog::filterElements(const QString &text)
{
// filter elements and hide pages
for (auto &&page : this->pages_)
{
// filterElements returns true if anything on the page matches the search query
page->tab()->setVisible(page->filterElements(text));
}
// find next visible page
if (this->lastSelectedByUser_ && this->lastSelectedByUser_->isVisible())
{
this->selectTab(this->lastSelectedByUser_, false);
}
else if (!this->selectedTab_->isVisible())
{
for (auto &&tab : this->tabs_)
{
if (tab->isVisible())
{
this->selectTab(tab, false);
break;
}
}
}
// remove duplicate spaces
bool shouldShowSpace = false;
for (int i = 0; i < this->ui_.tabContainer->count(); i++)
{
auto item = this->ui_.tabContainer->itemAt(i);
if (auto x = dynamic_cast<QSpacerItem *>(item); x)
{
x->changeSize(10, shouldShowSpace ? int(16 * this->scale()) : 0);
shouldShowSpace = false;
}
else if (item->widget())
{
shouldShowSpace |= item->widget()->isVisible();
}
}
}
SettingsDialog *SettingsDialog::getHandle()
{
return SettingsDialog::handle;
@@ -96,7 +154,7 @@ void SettingsDialog::addTabs()
this->ui_.tabContainer->setMargin(0);
this->ui_.tabContainer->setSpacing(0);
this->ui_.tabContainer->addSpacing(16);
this->ui_.tabContainer->setContentsMargins(0, 20, 0, 20);
this->addTab(new GeneralPage);
@@ -104,32 +162,21 @@ void SettingsDialog::addTabs()
this->addTab(new AccountsPage);
// this->ui_.tabContainer->addSpacing(16);
// this->addTab(new LookPage);
// this->addTab(new FeelPage);
this->ui_.tabContainer->addSpacing(16);
this->addTab(new CommandPage);
// this->addTab(new EmotesPage);
this->addTab(new HighlightingPage);
this->addTab(new IgnoresPage);
this->ui_.tabContainer->addSpacing(16);
this->addTab(new KeyboardSettingsPage);
// this->addTab(new LogsPage);
this->addTab(this->ui_.moderationPage = new ModerationPage);
this->addTab(new NotificationPage);
// this->addTab(new SpecialChannelsPage);
// this->addTab(new BrowserExtensionPage);
this->addTab(new ExternalToolsPage);
this->addTab(new AdvancedPage);
this->ui_.tabContainer->addStretch(1);
this->addTab(new AboutPage, Qt::AlignBottom);
this->ui_.tabContainer->addSpacing(16);
}
void SettingsDialog::addTab(SettingsPage *page, Qt::Alignment alignment)
@@ -140,6 +187,7 @@ void SettingsDialog::addTab(SettingsPage *page, Qt::Alignment alignment)
this->ui_.pageStack->addWidget(page);
this->ui_.tabContainer->addWidget(tab, 0, alignment);
this->tabs_.push_back(tab);
this->pages_.push_back(page);
if (this->tabs_.size() == 1)
{
@@ -147,7 +195,7 @@ void SettingsDialog::addTab(SettingsPage *page, Qt::Alignment alignment)
}
}
void SettingsDialog::selectTab(SettingsDialogTab *tab)
void SettingsDialog::selectTab(SettingsDialogTab *tab, bool byUser)
{
this->ui_.pageStack->setCurrentWidget(tab->getSettingsPage());
@@ -159,10 +207,12 @@ void SettingsDialog::selectTab(SettingsDialogTab *tab)
tab->setSelected(true);
tab->setStyleSheet("background: #222; color: #4FC3F7;"
"border-left: 1px solid #444;"
"border-top: 1px solid #444;"
"border-bottom: 1px solid #444;");
"/*border: 1px solid #555; border-right: none;*/");
this->selectedTab_ = tab;
if (byUser)
{
this->lastSelectedByUser_ = tab;
}
}
void SettingsDialog::selectPage(SettingsPage *page)
+12 -1
View File
@@ -8,12 +8,19 @@
#include <QWidget>
#include <pajlada/settings/setting.hpp>
class QLineEdit;
namespace chatterino {
class SettingsPage;
class SettingsDialogTab;
class ModerationPage;
class PageHeader : public QFrame
{
Q_OBJECT
};
enum class SettingsDialogPreference {
NoPreference,
Accounts,
@@ -41,8 +48,9 @@ private:
void initUi();
void addTabs();
void addTab(SettingsPage *page, Qt::Alignment alignment = Qt::AlignTop);
void selectTab(SettingsDialogTab *tab);
void selectTab(SettingsDialogTab *tab, bool byUser = true);
void selectPage(SettingsPage *page);
void filterElements(const QString &query);
void onOkClicked();
void onCancelClicked();
@@ -54,9 +62,12 @@ private:
QPushButton *okButton{};
QPushButton *cancelButton{};
ModerationPage *moderationPage{};
QLineEdit *search{};
} ui_;
std::vector<SettingsDialogTab *> tabs_;
std::vector<SettingsPage *> pages_;
SettingsDialogTab *selectedTab_{};
SettingsDialogTab *lastSelectedByUser_{};
friend class SettingsDialogTab;
};
+44 -6
View File
@@ -24,8 +24,23 @@
#define TEXT_FOLLOWERS "Followers: "
#define TEXT_VIEWS "Views: "
#define TEXT_CREATED "Created: "
#define TEXT_USER_ID "ID: "
namespace chatterino {
namespace {
void addCopyableLabel(LayoutCreator<QHBoxLayout> box, Label **assign)
{
auto label = box.emplace<Label>().assign(assign);
auto button = box.emplace<Button>();
button->setPixmap(getApp()->resources->buttons.copyDark);
button->setScaleIndependantSize(18, 18);
button->setDim(Button::Dim::Lots);
QObject::connect(button.getElement(), &Button::leftClicked,
[label = label.getElement()] {
qApp->clipboard()->setText(label->getText());
});
};
} // namespace
UserInfoPopup::UserInfoPopup()
: BaseWindow(nullptr, BaseWindow::Flags(BaseWindow::Frameless |
@@ -50,6 +65,7 @@ UserInfoPopup::UserInfoPopup()
auto avatar =
head.emplace<Button>(nullptr).assign(&this->ui_.avatarButton);
avatar->setScaleIndependantSize(100, 100);
avatar->setDim(Button::Dim::None);
QObject::connect(avatar.getElement(), &Button::leftClicked, [this] {
QDesktopServices::openUrl(
QUrl("https://twitch.tv/" + this->userName_.toLower()));
@@ -58,11 +74,19 @@ UserInfoPopup::UserInfoPopup()
// items on the right
auto vbox = head.emplace<QVBoxLayout>();
{
auto name = vbox.emplace<Label>().assign(&this->ui_.nameLabel);
{
auto box = vbox.emplace<QHBoxLayout>()
.withoutMargin()
.withoutSpacing();
addCopyableLabel(box, &this->ui_.nameLabel);
this->ui_.nameLabel->setFontStyle(FontStyle::UiMediumBold);
box->addStretch(1);
addCopyableLabel(box, &this->ui_.userIDLabel);
auto palette = QPalette();
palette.setColor(QPalette::WindowText, QColor("#aaa"));
this->ui_.userIDLabel->setPalette(palette);
}
auto font = name->font();
font.setBold(true);
name->setFont(font);
vbox.emplace<Label>(TEXT_VIEWS).assign(&this->ui_.viewCountLabel);
vbox.emplace<Label>(TEXT_FOLLOWERS)
.assign(&this->ui_.followerCountLabel);
@@ -199,7 +223,7 @@ UserInfoPopup::UserInfoPopup()
});
}
this->setStyleSheet("font-size: 11pt;");
// this->setStyleSheet("font-size: 11pt;");
this->installEvents();
}
@@ -208,7 +232,17 @@ void UserInfoPopup::themeChangedEvent()
{
BaseWindow::themeChangedEvent();
this->setStyleSheet("background: #333");
this->setStyleSheet(
"background: #333; font-size: " +
QString::number(getFonts()
->getFont(FontStyle::UiMediumBold, this->scale())
.pixelSize()) +
"px;");
}
void UserInfoPopup::scaleChangedEvent(float /*scale*/)
{
themeChangedEvent();
}
void UserInfoPopup::installEvents()
@@ -348,6 +382,10 @@ void UserInfoPopup::updateUserData()
this->userId_ = id;
this->ui_.userIDLabel->setText(TEXT_USER_ID + this->userId_);
// don't wait for the request to complete, just put the user id in the card
// right away
QString url("https://api.twitch.tv/kraken/channels/" + id);
NetworkRequest::twitchRequest(url)
+2
View File
@@ -23,6 +23,7 @@ public:
protected:
virtual void themeChangedEvent() override;
virtual void scaleChangedEvent(float scale) override;
private:
void installEvents();
@@ -48,6 +49,7 @@ private:
Label *viewCountLabel = nullptr;
Label *followerCountLabel = nullptr;
Label *createdDateLabel = nullptr;
Label *userIDLabel = nullptr;
QCheckBox *follow = nullptr;
QCheckBox *ignore = nullptr;
+8 -9
View File
@@ -133,6 +133,8 @@ ChannelView::ChannelView(BaseWidget *parent)
this->clickTimer_ = new QTimer(this);
this->clickTimer_->setSingleShot(true);
this->clickTimer_->setInterval(500);
this->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
}
void ChannelView::initializeLayout()
@@ -1526,14 +1528,8 @@ void ChannelView::addContextMenuItems(
QString url = hoveredElement->getLink().value;
// open link
bool incognitoByDefault = supportsIncognitoLinks() &&
layout->getMessage()->loginName == "hemirt";
menu->addAction("Open link", [url, incognitoByDefault] {
if (incognitoByDefault)
openLinkIncognito(url);
else
QDesktopServices::openUrl(QUrl(url));
});
menu->addAction("Open link",
[url] { QDesktopServices::openUrl(QUrl(url)); });
// open link default
if (supportsIncognitoLinks())
{
@@ -1699,7 +1695,10 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link,
case Link::Url:
{
QDesktopServices::openUrl(QUrl(link.value));
if (getSettings()->openLinksIncognito && supportsIncognitoLinks())
openLinkIncognito(link.value);
else
QDesktopServices::openUrl(QUrl(link.value));
}
break;
+39 -27
View File
@@ -10,6 +10,26 @@
#include "widgets/helper/ChannelView.hpp"
namespace chatterino {
namespace {
ChannelPtr filter(const QString &text, const QString &channelName,
const LimitedQueueSnapshot<MessagePtr> &snapshot)
{
ChannelPtr channel(new Channel(channelName, Channel::Type::None));
for (size_t i = 0; i < snapshot.size(); i++)
{
MessagePtr message = snapshot[i];
if (text.isEmpty() ||
message->searchText.indexOf(text, 0, Qt::CaseInsensitive) != -1)
{
channel->addMessage(message);
}
}
return channel;
}
} // namespace
SearchPopup::SearchPopup()
{
@@ -17,13 +37,24 @@ SearchPopup::SearchPopup()
this->resize(400, 600);
}
void SearchPopup::setChannel(ChannelPtr channel)
void SearchPopup::setChannel(const ChannelPtr &channel)
{
this->channelName_ = channel->getName();
this->snapshot_ = channel->getMessageSnapshot();
this->performSearch();
this->search();
this->setWindowTitle("Searching in " + channel->getName() + "s history");
this->updateWindowTitle();
}
void SearchPopup::updateWindowTitle()
{
this->setWindowTitle("Searching in " + this->channelName_ + "s history");
}
void SearchPopup::search()
{
this->channelView_->setChannel(filter(this->searchInput_->text(),
this->channelName_, this->snapshot_));
}
void SearchPopup::keyPressEvent(QKeyEvent *e)
@@ -43,18 +74,20 @@ void SearchPopup::initLayout()
{
QVBoxLayout *layout1 = new QVBoxLayout(this);
layout1->setMargin(0);
layout1->setSpacing(0);
// HBOX
{
QHBoxLayout *layout2 = new QHBoxLayout(this);
layout2->setMargin(6);
layout2->setMargin(8);
layout2->setSpacing(8);
// SEARCH INPUT
{
this->searchInput_ = new QLineEdit(this);
layout2->addWidget(this->searchInput_);
QObject::connect(this->searchInput_, &QLineEdit::returnPressed,
[this] { this->performSearch(); });
[this] { this->search(); });
}
// SEARCH BUTTON
@@ -63,7 +96,7 @@ void SearchPopup::initLayout()
searchButton->setText("Search");
layout2->addWidget(searchButton);
QObject::connect(searchButton, &QPushButton::clicked,
[this] { this->performSearch(); });
[this] { this->search(); });
}
layout1->addLayout(layout2);
@@ -80,25 +113,4 @@ void SearchPopup::initLayout()
}
}
void SearchPopup::performSearch()
{
QString text = searchInput_->text();
ChannelPtr channel(new Channel(this->channelName_, Channel::Type::None));
for (size_t i = 0; i < this->snapshot_.size(); i++)
{
MessagePtr message = this->snapshot_[i];
if (text.isEmpty() ||
message->searchText.indexOf(this->searchInput_->text(), 0,
Qt::CaseInsensitive) != -1)
{
channel->addMessage(message);
}
}
this->channelView_->setChannel(channel);
}
} // namespace chatterino
+8 -11
View File
@@ -1,5 +1,6 @@
#pragma once
#include "ForwardDecl.hpp"
#include "messages/LimitedQueueSnapshot.hpp"
#include "widgets/BaseWindow.hpp"
@@ -9,30 +10,26 @@ class QLineEdit;
namespace chatterino {
class Channel;
class ChannelView;
struct Message;
using MessagePtr = std::shared_ptr<const Message>;
class SearchPopup : public BaseWindow
{
public:
SearchPopup();
void setChannel(std::shared_ptr<Channel> channel);
virtual void setChannel(const ChannelPtr &channel);
protected:
void keyPressEvent(QKeyEvent *e) override;
virtual void updateWindowTitle();
private:
void initLayout();
void performSearch();
void search();
LimitedQueueSnapshot<MessagePtr> snapshot_;
QLineEdit *searchInput_;
ChannelView *channelView_;
QString channelName_;
QLineEdit *searchInput_{};
ChannelView *channelView_{};
QString channelName_{};
};
} // namespace chatterino
+2
View File
@@ -68,6 +68,8 @@ void SettingsDialogTab::mousePressEvent(QMouseEvent *event)
}
this->dialog_->selectTab(this);
this->setFocus();
}
} // namespace chatterino
@@ -1,78 +0,0 @@
#include "AdvancedPage.hpp"
#include "Application.hpp"
#include "controllers/taggedusers/TaggedUsersController.hpp"
#include "controllers/taggedusers/TaggedUsersModel.hpp"
#include "singletons/Logging.hpp"
#include "singletons/Paths.hpp"
#include "util/Helpers.hpp"
#include "util/LayoutCreator.hpp"
#include <QFileDialog>
#include <QFormLayout>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QLabel>
#include <QListView>
#include <QPushButton>
#include <QTableView>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QtConcurrent/QtConcurrent>
namespace chatterino {
AdvancedPage::AdvancedPage()
: SettingsPage("Advanced", ":/settings/advanced.svg")
{
LayoutCreator<AdvancedPage> layoutCreator(this);
auto tabs = layoutCreator.emplace<QTabWidget>();
{
auto layout = tabs.appendTab(new QVBoxLayout, "Cache");
auto folderLabel = layout.emplace<QLabel>();
folderLabel->setTextFormat(Qt::RichText);
folderLabel->setTextInteractionFlags(Qt::TextBrowserInteraction |
Qt::LinksAccessibleByKeyboard |
Qt::LinksAccessibleByKeyboard);
folderLabel->setOpenExternalLinks(true);
getSettings()->cachePath.connect([folderLabel](const auto &,
auto) mutable {
QString newPath = getPaths()->cacheDirectory();
QString pathShortened = "Cache saved at <a href=\"file:///" +
newPath +
"\"><span style=\"color: white;\">" +
shortenString(newPath, 50) + "</span></a>";
folderLabel->setText(pathShortened);
folderLabel->setToolTip(newPath);
});
layout->addStretch(1);
auto selectDir = layout.emplace<QPushButton>("Set custom cache folder");
QObject::connect(
selectDir.getElement(), &QPushButton::clicked, this, [this] {
auto dirName = QFileDialog::getExistingDirectory(this);
getSettings()->cachePath = dirName;
});
auto resetDir =
layout.emplace<QPushButton>("Reset custom cache folder");
QObject::connect(resetDir.getElement(), &QPushButton::clicked, this,
[]() mutable {
getSettings()->cachePath = ""; //
});
// Logs end
}
}
} // namespace chatterino
@@ -1,13 +0,0 @@
#pragma once
#include "widgets/settingspages/SettingsPage.hpp"
namespace chatterino {
class AdvancedPage : public SettingsPage
{
public:
AdvancedPage();
};
} // namespace chatterino
@@ -1,36 +0,0 @@
#include "BrowserExtensionPage.hpp"
#include "util/LayoutCreator.hpp"
#include <QLabel>
#define CHROME_EXTENSION_LINK \
"https://chrome.google.com/webstore/detail/chatterino-native-host/" \
"glknmaideaikkmemifbfkhnomoknepka"
#define FIREFOX_EXTENSION_LINK \
"https://addons.mozilla.org/en-US/firefox/addon/chatterino-native-host/"
namespace chatterino {
BrowserExtensionPage::BrowserExtensionPage()
: SettingsPage("Browser integration", ":/settings/browser.svg")
{
auto layout =
LayoutCreator<BrowserExtensionPage>(this).setLayoutType<QVBoxLayout>();
auto label = layout.emplace<QLabel>(
"The browser extension will replace the default Twitch.tv chat with "
"chatterino while chatterino is running.");
label->setWordWrap(true);
auto chrome = layout.emplace<QLabel>("<a href=\"" CHROME_EXTENSION_LINK
"\">Download for Google Chrome</a>");
chrome->setOpenExternalLinks(true);
auto firefox =
layout.emplace<QLabel>("<a href=\"" FIREFOX_EXTENSION_LINK
"\">Download for Mozilla Firefox</a>");
firefox->setOpenExternalLinks(true);
layout->addStretch(1);
}
} // namespace chatterino
@@ -1,13 +0,0 @@
#pragma once
#include "widgets/settingspages/SettingsPage.hpp"
namespace chatterino {
class BrowserExtensionPage : public SettingsPage
{
public:
BrowserExtensionPage();
};
} // namespace chatterino
+1 -1
View File
@@ -38,7 +38,7 @@ CommandPage::CommandPage()
auto app = getApp();
LayoutCreator<CommandPage> layoutCreator(this);
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
EditableModelView *view =
layout.emplace<EditableModelView>(app->commands->createModel(nullptr))
-29
View File
@@ -1,29 +0,0 @@
#include "EmotesPage.hpp"
#include "util/LayoutCreator.hpp"
namespace chatterino {
EmotesPage::EmotesPage()
: SettingsPage("Emotes", ":/settings/emote.svg")
{
// SettingManager &settings = SettingManager::getInstance();
// LayoutCreator<EmotesPage> layoutCreator(this);
// auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
// // clang-format off
// layout.append(this->createCheckBox("Enable Twitch emotes",
// settings.enableTwitchEmotes));
// layout.append(this->createCheckBox("Enable BetterTTV emotes",
// settings.enableBttvEmotes));
// layout.append(this->createCheckBox("Enable FrankerFaceZ emotes",
// settings.enableFfzEmotes)); layout.append(this->createCheckBox("Enable
// emojis", settings.enableEmojis));
// layout.append(this->createCheckBox("Enable gif animations",
// settings.enableGifAnimations));
// // clang-format on
// layout->addStretch(1);
}
} // namespace chatterino
-13
View File
@@ -1,13 +0,0 @@
#pragma once
#include "widgets/settingspages/SettingsPage.hpp"
namespace chatterino {
class EmotesPage : public SettingsPage
{
public:
EmotesPage();
};
} // namespace chatterino
-103
View File
@@ -1,103 +0,0 @@
#include "FeelPage.hpp"
#include "Application.hpp"
#include "util/LayoutCreator.hpp"
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QVBoxLayout>
#define PAUSE_HOVERING "When hovering"
#define SCROLL_SMOOTH "Smooth scrolling"
#define SCROLL_NEWMSG "Smooth scrolling for new messages"
#define LIMIT_CHATTERS_FOR_SMALLER_STREAMERS \
"Only fetch chatters list for viewers under X viewers"
namespace chatterino {
FeelPage::FeelPage()
: SettingsPage("Feel", ":/settings/behave.svg")
{
LayoutCreator<FeelPage> layoutCreator(this);
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));
auto form = layout.emplace<QFormLayout>().withoutMargin();
{
form->addRow(
"", this->createCheckBox(
"Show which users joined the channel (up to 1000 chatters)",
getSettings()->showJoins));
form->addRow(
"", this->createCheckBox(
"Show which users parted the channel (up to 1000 chatters)",
getSettings()->showParts));
form->addRow("Pause chat:",
this->createCheckBox(PAUSE_HOVERING,
getSettings()->pauseChatOnHover));
form->addRow("Mouse scroll speed:", this->createMouseScrollSlider());
form->addRow("Links:",
this->createCheckBox("Open links only on double click",
getSettings()->linksDoubleClickOnly));
form->addRow("", this->createCheckBox("Show link info in tooltips",
getSettings()->linkInfoTooltip));
form->addRow(
"", this->createCheckBox("Auto unshort links (requires restart)",
getSettings()->unshortLinks));
}
layout->addSpacing(16);
{
auto group = layout.emplace<QGroupBox>("Auto-completion");
auto groupLayout = group.setLayoutType<QFormLayout>();
groupLayout->addRow(
LIMIT_CHATTERS_FOR_SMALLER_STREAMERS,
this->createCheckBox(
"", getSettings()->onlyFetchChattersForSmallerStreamers));
groupLayout->addRow(
"What viewer count counts as a \"smaller streamer\"",
this->createSpinBox(getSettings()->smallStreamerLimit, 10, 50000));
}
{
auto group = layout.emplace<QGroupBox>("Misc");
auto groupLayout = group.setLayoutType<QVBoxLayout>();
groupLayout.append(this->createCheckBox("Show whispers inline",
getSettings()->inlineWhispers));
}
layout->addStretch(1);
}
QSlider *FeelPage::createMouseScrollSlider()
{
auto slider = new QSlider(Qt::Horizontal);
float currentValue = getSettings()->mouseScrollMultiplier;
int sliderValue = int(((currentValue - 0.1f) / 2.f) * 99.f);
slider->setValue(sliderValue);
QObject::connect(slider, &QSlider::valueChanged, [=](int newValue) {
float mul = static_cast<float>(newValue) / 99.f;
float newSliderValue = (mul * 2.1f) + 0.1f;
getSettings()->mouseScrollMultiplier = newSliderValue;
});
return slider;
}
} // namespace chatterino
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#include <QSlider>
#include "widgets/settingspages/SettingsPage.hpp"
namespace chatterino {
class FeelPage : public SettingsPage
{
public:
FeelPage();
private:
QSlider *createMouseScrollSlider();
};
} // namespace chatterino
+166 -45
View File
@@ -11,6 +11,7 @@
#include "singletons/WindowManager.hpp"
#include "util/FuzzyConvert.hpp"
#include "util/Helpers.hpp"
#include "util/IncognitoBrowser.hpp"
#include "widgets/BaseWindow.hpp"
#include "widgets/helper/Line.hpp"
@@ -20,36 +21,21 @@
#define FIREFOX_EXTENSION_LINK \
"https://addons.mozilla.org/en-US/firefox/addon/chatterino-native-host/"
#define addTitle addTitle
namespace chatterino {
namespace {
QPushButton *makeOpenSettingDirButton()
{
auto button = new QPushButton("Open settings directory");
QObject::connect(button, &QPushButton::clicked, [] {
QDesktopServices::openUrl(getPaths()->rootAppDataDirectory);
});
return button;
}
} // namespace
TitleLabel *SettingsLayout::addTitle(const QString &title)
{
auto label = new TitleLabel(title + ":");
if (this->count() != 0)
this->addSpacing(16);
if (this->count() == 0)
label->setStyleSheet("margin-top: 0");
this->addWidget(label);
return label;
}
TitleLabel2 *SettingsLayout::addTitle2(const QString &title)
{
auto label = new TitleLabel2(title + ":");
// groups
this->groups_.push_back(Group{title, label, {}});
this->addSpacing(16);
this->addWidget(label);
return label;
}
@@ -71,6 +57,10 @@ QCheckBox *SettingsLayout::addCheckbox(const QString &text,
[&setting, inverse](bool state) { setting = inverse ^ state; });
this->addWidget(check);
// groups
this->groups_.back().widgets.push_back({check, {text}});
return check;
}
@@ -82,11 +72,17 @@ ComboBox *SettingsLayout::addDropdown(const QString &text,
combo->setFocusPolicy(Qt::StrongFocus);
combo->addItems(list);
layout->addWidget(new QLabel(text + ":"));
auto label = new QLabel(text + ":");
layout->addWidget(label);
layout->addStretch(1);
layout->addWidget(combo);
this->addLayout(layout);
// groups
this->groups_.back().widgets.push_back({combo, {text}});
this->groups_.back().widgets.push_back({label, {text}});
return combo;
}
@@ -124,6 +120,9 @@ DescriptionLabel *SettingsLayout::addDescription(const QString &text)
this->addWidget(label);
// groups
this->groups_.back().widgets.push_back({label, {text}});
return label;
}
@@ -132,6 +131,64 @@ void SettingsLayout::addSeperator()
this->addWidget(new Line(false));
}
bool SettingsLayout::filterElements(const QString &query)
{
bool any{};
for (auto &&group : this->groups_)
{
// if a description in a group matches `query` then show the entire group
bool descriptionMatches{};
for (auto &&widget : group.widgets)
{
if (auto x = dynamic_cast<DescriptionLabel *>(widget.element); x)
{
if (x->text().contains(query, Qt::CaseInsensitive))
{
descriptionMatches = true;
break;
}
}
}
// if group name matches then all should be visible
if (group.name.contains(query, Qt::CaseInsensitive) ||
descriptionMatches)
{
for (auto &&widget : group.widgets)
widget.element->show();
group.title->show();
any = true;
}
// check if any match
else
{
auto groupAny = false;
for (auto &&widget : group.widgets)
{
for (auto &&keyword : widget.keywords)
{
if (keyword.contains(query, Qt::CaseInsensitive))
{
widget.element->show();
groupAny = true;
}
else
{
widget.element->hide();
}
}
}
group.title->setVisible(groupAny);
any |= groupAny;
}
}
return any;
}
GeneralPage::GeneralPage()
: SettingsPage("General", ":/settings/about.svg")
{
@@ -141,6 +198,7 @@ GeneralPage::GeneralPage()
y->addWidget(scroll);
auto x = new QHBoxLayout;
auto layout = new SettingsLayout;
this->settingsLayout_ = layout;
x->addLayout(layout, 0);
x->addStretch(1);
auto z = new QFrame;
@@ -155,6 +213,16 @@ GeneralPage::GeneralPage()
this->initExtra();
}
bool GeneralPage::filterElements(const QString &query)
{
if (this->settingsLayout_)
return this->settingsLayout_->filterElements(query) ||
this->name_.contains(query, Qt::CaseInsensitive) ||
query.isEmpty();
else
return false;
}
void GeneralPage::initLayout(SettingsLayout &layout)
{
auto &s = *getSettings();
@@ -220,10 +288,6 @@ void GeneralPage::initLayout(SettingsLayout &layout)
// layout.addCheckbox("Mark last message you read");
// layout.addDropdown("Last read message style", {"Default"});
layout.addCheckbox("Show deleted messages", s.hideModerated, true);
layout.addCheckbox("Show moderation messages", s.hideModerationActions,
true);
layout.addCheckbox("Random username color for users who never set a color",
s.colorizeNicknames);
layout.addDropdown<QString>(
"Timestamps", {"Disable", "h:mm", "hh:mm", "h:mm a", "hh:mm a"},
s.timestampFormat,
@@ -268,6 +332,11 @@ void GeneralPage::initLayout(SettingsLayout &layout)
return QString::number(val) + "x";
},
[](auto args) { return fuzzyToFloat(args.value, 1.f); });
layout.addDropdown<int>(
"Preview on hover", {"Don't show", "Always show", "Hold shift"},
s.emotesTooltipPreview, [](int index) { return index; },
[](auto args) { return args.index; }, false);
layout.addDropdown("Emoji set",
{"EmojiOne 2", "EmojiOne 3", "Twitter", "Facebook",
"Apple", "Google", "Messenger"},
@@ -284,15 +353,40 @@ void GeneralPage::initLayout(SettingsLayout &layout)
layout.addCheckbox("Chatterino", getSettings()->showBadgesChatterino);
layout.addTitle("Chat title");
layout.addWidget(new QLabel("In live channels show:"));
layout.addDescription("In live channels show:");
layout.addCheckbox("Uptime", s.headerUptime);
layout.addCheckbox("Viewer count", s.headerViewerCount);
layout.addCheckbox("Category", s.headerGame);
layout.addCheckbox("Title", s.headerStreamTitle);
layout.addTitle("Beta");
layout.addDescription(
"You can receive updates earlier by ticking the box below. Report "
"issues <a href='https://chatterino.com/link/issues'>here</a>.");
layout.addCheckbox("Receive beta updates", s.betaUpdates);
#ifdef Q_OS_WIN
layout.addTitle("Browser Integration");
layout.addDescription("The browser extension replaces the default "
"Twitch.tv chat with chatterino.");
layout.addDescription(
createNamedLink(CHROME_EXTENSION_LINK, "Download for Google Chrome"));
layout.addDescription(
createNamedLink(FIREFOX_EXTENSION_LINK, "Download for Firefox"));
#endif
layout.addTitle("Miscellaneous");
//layout.addWidget(makeOpenSettingDirButton());
if (supportsIncognitoLinks())
{
layout.addCheckbox("Open links in incognito/private mode",
s.openLinksIncognito);
}
layout.addCheckbox("Show moderation messages", s.hideModerationActions,
true);
layout.addCheckbox("Random username color for users who never set a color",
s.colorizeNicknames);
layout.addCheckbox("Mention users with a comma (User,)",
s.mentionUsersWithComma);
layout.addCheckbox("Show joined users (< 1000 chatters)", s.showJoins);
@@ -314,11 +408,6 @@ void GeneralPage::initLayout(SettingsLayout &layout)
s.linksDoubleClickOnly);
layout.addCheckbox("Unshorten links", s.unshortLinks);
layout.addCheckbox("Show live indicator in tabs", s.showTabLive);
layout.addDropdown<int>("Show emote preview in tooltip on hover",
{"Don't show", "Always show", "Hold shift"},
s.emotesTooltipPreview,
[](int index) { return index; },
[](auto args) { return args.index; }, false);
layout.addCheckbox(
"Only search for emote autocompletion at the start of emote names",
@@ -330,25 +419,57 @@ void GeneralPage::initLayout(SettingsLayout &layout)
layout.addCheckbox("Load message history on connect",
s.loadTwitchMessageHistoryOnConnect);
#ifdef Q_OS_WIN
layout.addTitle("Browser Integration");
layout.addDescription("The browser extension replaces the default "
"Twitch.tv chat with chatterino.");
layout.addTitle("Cache");
layout.addDescription(
"Files that are used often (such as emotes) are saved to disk to "
"reduce bandwidth usage and tho speed up loading.");
layout.addDescription(
createNamedLink(CHROME_EXTENSION_LINK, "Download for Google Chrome"));
layout.addDescription(
createNamedLink(FIREFOX_EXTENSION_LINK, "Download for Firefox"));
#endif
} // namespace chatterino
auto cachePathLabel = layout.addDescription("placeholder :D");
getSettings()->cachePath.connect([cachePathLabel](const auto &,
auto) mutable {
QString newPath = getPaths()->cacheDirectory();
QString pathShortened = "Cache saved at <a href=\"file:///" + newPath +
"\"><span style=\"color: white;\">" +
shortenString(newPath, 50) + "</span></a>";
cachePathLabel->setText(pathShortened);
cachePathLabel->setToolTip(newPath);
});
// Choose and reset buttons
{
auto box = new QHBoxLayout;
box->addWidget(layout.makeButton("Choose cache path", [this]() {
getSettings()->cachePath = QFileDialog::getExistingDirectory(this);
}));
box->addWidget(layout.makeButton(
"Reset", []() { getSettings()->cachePath = ""; }));
box->addStretch(1);
layout.addLayout(box);
}
layout.addTitle("AppData");
layout.addDescription("All local files like settings and cache files are "
"store in this directory.");
layout.addButton("Open AppData directory", [] {
QDesktopServices::openUrl(getPaths()->rootAppDataDirectory);
});
// invisible element for width
auto inv = new BaseWidget(this);
inv->setScaleIndependantWidth(500);
layout.addWidget(inv);
}
void GeneralPage::initExtra()
{
/// update cache path
if (this->cachePath)
if (this->cachePath_)
{
getSettings()->cachePath.connect(
[cachePath = this->cachePath](const auto &, auto) mutable {
[cachePath = this->cachePath_](const auto &, auto) mutable {
QString newPath = getPaths()->cacheDirectory();
QString pathShortened = "Current location: <a href=\"file:///" +
+38 -13
View File
@@ -28,17 +28,6 @@ public:
}
};
class TitleLabel2 : public QLabel
{
Q_OBJECT
public:
TitleLabel2(const QString &text)
: QLabel(text)
{
}
};
class DescriptionLabel : public QLabel
{
Q_OBJECT
@@ -71,7 +60,6 @@ class SettingsLayout : public QVBoxLayout
public:
TitleLabel *addTitle(const QString &text);
TitleLabel2 *addTitle2(const QString &text);
/// @param inverse Inverses true to false and vice versa
QCheckBox *addCheckbox(const QString &text, BoolSetting &setting,
bool inverse = false);
@@ -80,6 +68,26 @@ public:
pajlada::Settings::Setting<QString> &setting,
bool editable = false);
template <typename OnClick>
QPushButton *makeButton(const QString &text, OnClick onClick)
{
auto button = new QPushButton(text);
this->groups_.back().widgets.push_back({button, {text}});
QObject::connect(button, &QPushButton::clicked, onClick);
return button;
}
template <typename OnClick>
QPushButton *addButton(const QString &text, OnClick onClick)
{
auto button = makeButton(text, onClick);
auto layout = new QHBoxLayout();
layout->addWidget(button);
layout->addStretch(1);
this->addLayout(layout);
return button;
}
template <typename T>
ComboBox *addDropdown(
const QString &text, const QStringList &items,
@@ -141,9 +149,23 @@ public:
return combo;
}
DescriptionLabel *addDescription(const QString &text);
void addSeperator();
bool filterElements(const QString &query);
private:
struct Widget {
QWidget *element;
QStringList keywords;
};
struct Group {
QString name;
QWidget *title{};
std::vector<Widget> widgets;
};
std::vector<Group> groups_;
std::vector<pajlada::Signals::ScopedConnection> managedConnections_;
};
@@ -154,13 +176,16 @@ class GeneralPage : public SettingsPage
public:
GeneralPage();
bool filterElements(const QString &query);
private:
void initLayout(SettingsLayout &layout);
void initExtra();
QString getFont(const DropdownArgs &args) const;
DescriptionLabel *cachePath{};
DescriptionLabel *cachePath_{};
SettingsLayout *settingsLayout_{};
};
} // namespace chatterino
@@ -57,7 +57,7 @@ HighlightingPage::HighlightingPage()
view->addRegexHelpLink();
view->setTitles({"Pattern", "Flash\ntaskbar", "Play\nsound",
"Enable\nregex"});
"Enable\nregex", "Case-\nsensitive"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(
QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
@@ -71,8 +71,8 @@ HighlightingPage::HighlightingPage()
});
view->addButtonPressed.connect([] {
getApp()->highlights->phrases.appendItem(
HighlightPhrase{"my phrase", true, false, false});
getApp()->highlights->phrases.appendItem(HighlightPhrase{
"my phrase", true, false, false, false});
});
}
@@ -87,6 +87,10 @@ HighlightingPage::HighlightingPage()
.getElement();
view->addRegexHelpLink();
view->getTableView()->horizontalHeader()->hideSection(4);
// Case-sensitivity doesn't make sense for user names so it is
// set to "false" by default & no checkbox is shown
view->setTitles({"Username", "Flash\ntaskbar", "Play\nsound",
"Enable\nregex"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(
@@ -103,7 +107,7 @@ HighlightingPage::HighlightingPage()
view->addButtonPressed.connect([] {
getApp()->highlights->highlightedUsers.appendItem(
HighlightPhrase{"highlighted user", true, false,
HighlightPhrase{"highlighted user", true, false, false,
false});
});
}
@@ -13,7 +13,7 @@ KeyboardSettingsPage::KeyboardSettingsPage()
auto layout =
LayoutCreator<KeyboardSettingsPage>(this).setLayoutType<QVBoxLayout>();
auto form = layout.emplace<QFormLayout>();
auto form = layout.emplace<QFormLayout>().withoutMargin();
form->addRow(new QLabel("Hold Ctrl"), new QLabel("Show resize handles"));
form->addRow(new QLabel("Hold Ctrl + Alt"),
-53
View File
@@ -1,53 +0,0 @@
//#include "LogsPage.hpp"
//#include "Application.hpp"
//#include "singletons/PathManager.hpp"
//#include <QFormLayout>
//#include <QVBoxLayout>
//#include "util/LayoutCreator.hpp"
// namespace chatterino {
// namespace widgets {
// namespace settingspages {
// inline QString CreateLink(const QString &url, bool file = false)
//{
// if (file) {
// return QString("<a href=\"file:///" + url + "\"><span style=\"color:
// white;\">" + url +
// "</span></a>");
// }
// return QString("<a href=\"" + url + "\"><span style=\"color: white;\">" +
// url +
// "</span></a>");
//}
// LogsPage::LogsPage()
// : SettingsPage("Logs", "")
//{
// auto app = getApp();
// LayoutCreator<LogsPage> layoutCreator(this);
// auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
// auto logPath = getPaths()->logsFolderPath;
// auto created = layout.emplace<QLabel>();
// created->setText("Logs are saved to " + CreateLink(logPath, true));
// created->setTextFormat(Qt::RichText);
// created->setTextInteractionFlags(Qt::TextBrowserInteraction |
// Qt::LinksAccessibleByKeyboard |
// Qt::LinksAccessibleByKeyboard);
// created->setOpenExternalLinks(true);
// layout.append(this->createCheckBox("Enable logging",
// getSettings()->enableLogging));
// layout->addStretch(1);
//}
//} // namespace settingspages
//} // namespace widgets
//} // namespace chatterino
-17
View File
@@ -1,17 +0,0 @@
//#pragma once
//#include "widgets/settingspages/SettingsPage.hpp"
// namespace chatterino {
// namespace widgets {
// namespace settingspages {
// class LogsPage : public SettingsPage
//{
// public:
// LogsPage();
//};
//} // namespace settingspages
//} // namespace widgets
//} // namespace chatterino
-596
View File
@@ -1,596 +0,0 @@
#include "LookPage.hpp"
#include "Application.hpp"
#include "messages/Image.hpp"
#include "messages/MessageBuilder.hpp"
#include "singletons/Resources.hpp"
#include "singletons/Theme.hpp"
#include "singletons/WindowManager.hpp"
#include "util/LayoutCreator.hpp"
#include "util/RemoveScrollAreaBackground.hpp"
#include "widgets/helper/ChannelView.hpp"
#include "widgets/helper/Line.hpp"
#include <QColorDialog>
#include <QFontDialog>
#include <QFormLayout>
#include <QGroupBox>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QSlider>
#include <QVBoxLayout>
#define THEME_ITEMS "White", "Light", "Dark", "Black", "Custom"
#define TAB_X "Show tab close button"
#define TAB_PREF "Hide preferences button (ctrl+p to show)"
#define TAB_USER "Hide user button"
// clang-format off
#define TIMESTAMP_FORMATS "hh:mm a", "h:mm a", "hh:mm:ss a", "h:mm:ss a", "HH:mm", "H:mm", "HH:mm:ss", "H:mm:ss"
// clang-format on
#ifdef USEWINSDK
# define WINDOW_TOPMOST "Window always on top"
#else
# define WINDOW_TOPMOST "Window always on top (requires restart)"
#endif
#define INPUT_EMPTY "Show input box when empty"
#define LAST_MSG "Mark the last message you read"
namespace chatterino {
LookPage::LookPage()
: SettingsPage("Look", ":/settings/theme.svg")
{
this->initializeUi();
}
void LookPage::initializeUi()
{
LayoutCreator<LookPage> layoutCreator(this);
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
// settings
auto tabs = layout.emplace<QTabWidget>();
this->addInterfaceTab(tabs.appendTab(new QVBoxLayout, "Interface"));
this->addMessageTab(tabs.appendTab(new QVBoxLayout, "Messages"));
this->addEmoteTab(tabs.appendTab(new QVBoxLayout, "Emotes"));
this->addSplitHeaderTab(tabs.appendTab(new QVBoxLayout, "Split header"));
this->addBadgesTab(tabs.appendTab(new QVBoxLayout, "Badges"));
layout->addStretch(1);
// preview
layout.emplace<Line>(false);
auto channelView = layout.emplace<ChannelView>();
auto channel = this->createPreviewChannel();
channelView->setChannel(channel);
channelView->setScaleIndependantHeight(74);
}
void LookPage::addInterfaceTab(LayoutCreator<QVBoxLayout> layout)
{
// theme
{
auto *theme =
this->createComboBox({THEME_ITEMS}, getApp()->themes->themeName);
QDoubleSpinBox *w = new QDoubleSpinBox;
QObject::connect(theme, &QComboBox::currentTextChanged,
[w](const QString &themeName) {
if (themeName == "Custom")
{
w->show();
}
else
{
w->hide();
}
getApp()->windows->forceLayoutChannelViews();
});
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
box.emplace<QLabel>("Theme: ");
box.append(theme);
{
w->setButtonSymbols(QDoubleSpinBox::NoButtons);
if (getApp()->themes->themeName.getValue() != "Custom")
{
w->hide();
}
else
{
w->show();
}
w->setRange(-1.0, 1.0);
w->setSingleStep(0.05);
w->setValue(getSettings()->customThemeMultiplier.getValue());
QObject::connect(
w, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
[](double value) {
getSettings()->customThemeMultiplier.setValue(float(value));
getApp()->themes->update();
getApp()->windows->forceLayoutChannelViews();
});
box.append(w);
}
box->addStretch(1);
}
layout.append(
this->createCheckBox(WINDOW_TOPMOST, getSettings()->windowTopMost));
// --
layout.emplace<Line>(false);
// tab x
layout.append(
this->createCheckBox(TAB_X, getSettings()->showTabCloseButton));
// show buttons
#ifndef USEWINSDK
layout.append(
this->createCheckBox(TAB_PREF, getSettings()->hidePreferencesButton));
layout.append(
this->createCheckBox(TAB_USER, getSettings()->hideUserButton));
#endif
// empty input
layout.append(
this->createCheckBox(INPUT_EMPTY, getSettings()->showEmptyInput));
layout.append(this->createCheckBox("Show message length while typing",
getSettings()->showMessageLength));
layout->addStretch(1);
}
void LookPage::addMessageTab(LayoutCreator<QVBoxLayout> layout)
{
// font
layout.append(this->createFontChanger());
// --
layout.emplace<Line>(false);
// timestamps
{
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
box.append(this->createCheckBox("Show timestamps",
getSettings()->showTimestamps));
box.append(this->createComboBox({TIMESTAMP_FORMATS},
getSettings()->timestampFormat));
box->addStretch(1);
}
// --
layout.emplace<Line>(false);
// separate
layout.append(this->createCheckBox("Lines between messages",
getSettings()->separateMessages));
// alternate
layout.append(this->createCheckBox("Alternate background",
getSettings()->alternateMessages));
layout.append(
this->createCheckBox("Compact emotes", getSettings()->compactEmotes));
layout.emplace<Line>(false);
// bold-slider
{
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
box.emplace<QLabel>("Username boldness: ");
box.append(this->createBoldScaleSlider());
}
// bold usernames
layout.append(this->createCheckBox("Bold mentions (@username)",
getSettings()->boldUsernames));
// --
layout.emplace<Line>(false);
// lowercase links
layout.append(this->createCheckBox("Lowercase domains",
getSettings()->lowercaseDomains));
// collapsing
{
auto *combo = new QComboBox(this);
combo->addItems({"Never", "2", "3", "4", "5", "6", "7", "8", "9", "10",
"11", "12", "13", "14", "15"});
const auto currentIndex = []() -> int {
auto val = getSettings()->collpseMessagesMinLines.getValue();
if (val > 0)
{
--val;
}
return val;
}();
combo->setCurrentIndex(currentIndex);
QObject::connect(
combo, &QComboBox::currentTextChanged, [](const QString &str) {
getSettings()->collpseMessagesMinLines = str.toInt();
});
auto hbox = layout.emplace<QHBoxLayout>().withoutMargin();
hbox.emplace<QLabel>("Collapse messages longer than");
hbox.append(combo);
hbox.emplace<QLabel>("lines");
}
// last read message
this->addLastReadMessageIndicatorPatternSelector(layout);
// --
layout->addStretch(1);
}
void LookPage::addEmoteTab(LayoutCreator<QVBoxLayout> layout)
{
layout.append(
this->createCheckBox("Animations", getSettings()->animateEmotes));
layout.append(
this->createCheckBox("Animations only when chatterino has focus",
getSettings()->animationsWhenFocused));
auto scaleBox = layout.emplace<QHBoxLayout>().withoutMargin();
{
scaleBox.emplace<QLabel>("Size:");
auto emoteScale = scaleBox.emplace<QSlider>(Qt::Horizontal);
emoteScale->setMinimum(5);
emoteScale->setMaximum(50);
auto scaleLabel = scaleBox.emplace<QLabel>("1.0");
scaleLabel->setFixedWidth(100);
QObject::connect(emoteScale.getElement(), &QSlider::valueChanged,
[scaleLabel](int value) mutable {
float f = float(value) / 10.f;
scaleLabel->setText(QString::number(f));
getSettings()->emoteScale.setValue(f);
});
emoteScale->setValue(std::max<int>(
5, std::min<int>(
50, int(getSettings()->emoteScale.getValue() * 10.f))));
scaleLabel->setText(
QString::number(getSettings()->emoteScale.getValue()));
}
{
auto *combo = new QComboBox(this);
combo->addItems({"EmojiOne 2", "EmojiOne 3", "Twitter", "Facebook",
"Apple", "Google", "Messenger"});
combo->setCurrentText(getSettings()->emojiSet);
QObject::connect(combo, &QComboBox::currentTextChanged,
[](const QString &str) {
getSettings()->emojiSet = str; //
});
auto hbox = layout.emplace<QHBoxLayout>().withoutMargin();
hbox.emplace<QLabel>("Emoji set:");
hbox.append(combo);
}
layout->addStretch(1);
}
void LookPage::addSplitHeaderTab(LayoutCreator<QVBoxLayout> layout)
{
layout.append(
this->createCheckBox("Show uptime", getSettings()->headerUptime));
layout.append(this->createCheckBox("Show viewer count",
getSettings()->headerViewerCount));
layout.append(this->createCheckBox("Show game", getSettings()->headerGame));
layout.append(
this->createCheckBox("Show title", getSettings()->headerStreamTitle));
layout->addStretch(1);
}
void LookPage::addBadgesTab(LayoutCreator<QVBoxLayout> layout)
{
// layout.append(
// this->createCheckBox(("Show all badges"), getSettings()->showBadges));
auto fastSelection = layout.emplace<QHBoxLayout>();
{
auto addAll = fastSelection.emplace<QPushButton>("Enable all");
QObject::connect(addAll.getElement(), &QPushButton::clicked, this, [] {
getSettings()->showBadgesGlobalAuthority = true;
getSettings()->showBadgesChannelAuthority = true;
getSettings()->showBadgesSubscription = true;
getSettings()->showBadgesVanity = true;
getSettings()->showBadgesChatterino = true;
});
auto removeAll = fastSelection.emplace<QPushButton>("Disable all");
QObject::connect(removeAll.getElement(), &QPushButton::clicked, this,
[] {
getSettings()->showBadgesGlobalAuthority = false;
getSettings()->showBadgesChannelAuthority = false;
getSettings()->showBadgesSubscription = false;
getSettings()->showBadgesVanity = false;
getSettings()->showBadgesChatterino = false;
});
}
layout.emplace<Line>(false);
layout.append(this->createCheckBox(
("Show authority badges (staff, admin, turbo, etc)"),
getSettings()->showBadgesGlobalAuthority));
layout.append(this->createCheckBox(
("Show channel badges (broadcaster, moderator, VIP)"),
getSettings()->showBadgesChannelAuthority));
layout.append(this->createCheckBox(("Show subscriber badges "),
getSettings()->showBadgesSubscription));
layout.append(
this->createCheckBox(("Show vanity badges (prime, bits, subgifter)"),
getSettings()->showBadgesVanity));
layout.append(this->createCheckBox(("Show chatterino badges"),
getSettings()->showBadgesChatterino));
layout->addStretch(1);
}
void LookPage::addLastReadMessageIndicatorPatternSelector(
LayoutCreator<QVBoxLayout> layout)
{
// combo
auto *combo = new QComboBox(this);
combo->addItems({"Dotted line", "Solid line"});
const auto currentIndex = []() -> int {
switch (getSettings()->lastMessagePattern.getValue())
{
case Qt::SolidLine:
return 1;
case Qt::VerPattern:
default:
return 0;
}
}();
combo->setCurrentIndex(currentIndex);
QObject::connect(
combo,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
[](int index) {
getSettings()->lastMessagePattern = [&] {
switch (index)
{
case 1:
return Qt::SolidPattern;
case 0:
default:
return Qt::VerPattern;
}
}();
});
// color picker
QLabel *colorPreview = new QLabel();
auto updatePreviewColor = [colorPreview](QColor newColor) {
QPixmap pixmap(16, 16);
pixmap.fill(QColor(0, 0, 0, 255));
QPainter painter(&pixmap);
QBrush brush(newColor);
painter.fillRect(1, 1, pixmap.width() - 2, pixmap.height() - 2, brush);
colorPreview->setPixmap(pixmap);
};
auto getCurrentColor = []() {
return getSettings()->lastMessageColor != ""
? QColor(getSettings()->lastMessageColor.getValue())
: getApp()
->themes->tabs.selected.backgrounds.regular.color();
};
updatePreviewColor(getCurrentColor());
QPushButton *button = new QPushButton("Select Color");
button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed);
QObject::connect(
button, &QPushButton::clicked, [updatePreviewColor, getCurrentColor]() {
QColor newColor = QColorDialog::getColor(getCurrentColor());
if (newColor.isValid())
{
updatePreviewColor(newColor);
getSettings()->lastMessageColor = newColor.name();
}
});
QPushButton *resetButton = new QPushButton("Reset Color");
resetButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed);
QObject::connect(
resetButton, &QPushButton::clicked, [updatePreviewColor]() {
QColor defaultColor =
getApp()->themes->tabs.selected.backgrounds.regular.color();
updatePreviewColor(defaultColor);
getSettings()->lastMessageColor = "";
});
// layout
auto hbox = layout.emplace<QHBoxLayout>().withoutMargin();
hbox.append(this->createCheckBox(LAST_MSG,
getSettings()->showLastMessageIndicator));
hbox.append(combo);
hbox.append(colorPreview);
hbox.append(button);
hbox.append(resetButton);
hbox->addStretch(1);
}
ChannelPtr LookPage::createPreviewChannel()
{
auto channel = ChannelPtr(new Channel("preview", Channel::Type::Misc));
// clang-format off
{
MessageBuilder builder;
builder.emplace<TimestampElement>(QTime(8, 13, 42));
builder.emplace<ImageElement>(Image::fromPixmap(getApp()->resources->twitch.moderator), MessageElementFlag::BadgeChannelAuthority);
builder.emplace<ImageElement>(Image::fromPixmap(getApp()->resources->twitch.subscriber, 0.25), MessageElementFlag::BadgeSubscription);
builder.emplace<TextElement>("username1:", MessageElementFlag::Username, QColor("#0094FF"), FontStyle::ChatMediumBold);
builder.emplace<TextElement>("This is a preview message", MessageElementFlag::Text);
builder.emplace<ImageElement>(Image::fromPixmap(getApp()->resources->pajaDank, 0.25), MessageElementFlag::AlwaysShow);
builder.emplace<TextElement>("@fourtf", MessageElementFlag::BoldUsername, MessageColor::Text, FontStyle::ChatMediumBold);
builder.emplace<TextElement>("@fourtf", MessageElementFlag::NonBoldUsername);
channel->addMessage(builder.release());
}
{
MessageBuilder message;
message.emplace<TimestampElement>(QTime(8, 15, 21));
message.emplace<ImageElement>(Image::fromPixmap(getApp()->resources->twitch.broadcaster), MessageElementFlag::BadgeChannelAuthority);
message.emplace<TextElement>("username2:", MessageElementFlag::Username, QColor("#FF6A00"), FontStyle::ChatMediumBold);
message.emplace<TextElement>("This is another one", MessageElementFlag::Text);
// message.emplace<ImageElement>(Image::fromNonOwningPixmap(&getApp()->resources->ppHop), MessageElementFlag::BttvEmote);
message.emplace<TextElement>("www.fourtf.com", MessageElementFlag::LowercaseLink, MessageColor::Link)->setLink(Link(Link::Url, "https://www.fourtf.com"));
message.emplace<TextElement>("wWw.FoUrTf.CoM", MessageElementFlag::OriginalLink, MessageColor::Link)->setLink(Link(Link::Url, "https://www.fourtf.com"));
channel->addMessage(message.release());
}
// clang-format on
return channel;
}
QLayout *LookPage::createThemeColorChanger()
{
auto app = getApp();
QHBoxLayout *layout = new QHBoxLayout;
auto &themeHue = app->themes->themeHue;
// SLIDER
QSlider *slider = new QSlider(Qt::Horizontal);
layout->addWidget(slider);
slider->setValue(
int(std::min(std::max(themeHue.getValue(), 0.0), 1.0) * 100));
// BUTTON
QPushButton *button = new QPushButton;
layout->addWidget(button);
button->setFlat(true);
button->setFixedWidth(64);
auto setButtonColor = [button, app](int value) mutable {
double newValue = value / 100.0;
app->themes->themeHue.setValue(newValue);
QPalette pal = button->palette();
QColor color;
color.setHsvF(newValue, 1.0, 1.0, 1.0);
pal.setColor(QPalette::Button, color);
button->setAutoFillBackground(true);
button->setPalette(pal);
button->update();
};
// SIGNALS
QObject::connect(slider, &QSlider::valueChanged, this, setButtonColor);
setButtonColor(themeHue * 100);
return layout;
}
QLayout *LookPage::createFontChanger()
{
auto app = getApp();
QHBoxLayout *layout = new QHBoxLayout;
layout->setMargin(0);
// LABEL
QLabel *label = new QLabel();
layout->addWidget(label);
auto updateFontFamilyLabel = [=]() {
label->setText("Font (" + app->fonts->chatFontFamily.getValue() + ", " +
QString::number(app->fonts->chatFontSize) + "pt)");
};
app->fonts->chatFontFamily.connect(updateFontFamilyLabel,
this->managedConnections_);
app->fonts->chatFontSize.connect(updateFontFamilyLabel,
this->managedConnections_);
// BUTTON
QPushButton *button = new QPushButton("Select");
layout->addWidget(button);
button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed);
QObject::connect(button, &QPushButton::clicked, [=]() {
QFontDialog dialog(app->fonts->getFont(FontStyle::ChatMedium, 1.));
dialog.setWindowFlag(Qt::WindowStaysOnTopHint);
dialog.connect(&dialog, &QFontDialog::fontSelected,
[=](const QFont &font) {
app->fonts->chatFontFamily = font.family();
app->fonts->chatFontSize = font.pointSize();
});
dialog.show();
dialog.exec();
});
layout->addStretch(1);
return layout;
}
QLayout *LookPage::createBoldScaleSlider()
{
auto layout = new QHBoxLayout();
auto slider = new QSlider(Qt::Horizontal);
auto label = new QLabel();
layout->addWidget(slider);
layout->addWidget(label);
slider->setMinimum(50);
slider->setMaximum(100);
slider->setValue(getSettings()->boldScale.getValue());
label->setMinimumWidth(100);
QObject::connect(slider, &QSlider::valueChanged, [](auto value) {
getSettings()->boldScale.setValue(value);
});
// show value
// getSettings()->boldScale.connect(
// [label](auto, auto) {
// label->setText(QString::number(getSettings()->boldScale.getValue()));
// },
// this->connections_);
// QPushButton *button = new QPushButton("Reset");
// layout->addWidget(button);
// button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Policy::Fixed);
// QObject::connect(button, &QPushButton::clicked, [=]() {
// getSettings()->boldScale.setValue(57);
// slider->setValue(57);
//});
return layout;
}
} // namespace chatterino
-40
View File
@@ -1,40 +0,0 @@
#pragma once
#include "common/Channel.hpp"
#include "util/LayoutCreator.hpp"
#include "widgets/settingspages/SettingsPage.hpp"
#include <QScrollArea>
#include <pajlada/signals/signalholder.hpp>
class QVBoxLayout;
namespace chatterino {
class LookPage : public SettingsPage
{
public:
LookPage();
private:
void initializeUi();
void addInterfaceTab(LayoutCreator<QVBoxLayout> layout);
void addMessageTab(LayoutCreator<QVBoxLayout> layout);
void addEmoteTab(LayoutCreator<QVBoxLayout> layout);
void addSplitHeaderTab(LayoutCreator<QVBoxLayout> layout);
void addBadgesTab(LayoutCreator<QVBoxLayout> layout);
void addLastReadMessageIndicatorPatternSelector(
LayoutCreator<QVBoxLayout> layout);
QLayout *createThemeColorChanger();
QLayout *createFontChanger();
QLayout *createBoldScaleSlider();
ChannelPtr createPreviewChannel();
std::vector<pajlada::Signals::ScopedConnection> connections_;
};
} // namespace chatterino
+23 -12
View File
@@ -83,13 +83,10 @@ ModerationPage::ModerationPage()
auto logs = tabs.appendTab(new QVBoxLayout, "Logs");
{
logs.append(this->createCheckBox("Enable logging",
getSettings()->enableLogging));
auto logsPathLabel = logs.emplace<QLabel>();
// Show how big (size-wise) the logs are
auto logsPathSizeLabel = logs.emplace<QLabel>();
logsPathSizeLabel->setText(
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
// Logs (copied from LoggingMananger)
getSettings()->logPath.connect([logsPathLabel](const QString &logPath,
auto) mutable {
@@ -109,13 +106,27 @@ ModerationPage::ModerationPage()
logsPathLabel->setTextInteractionFlags(Qt::TextBrowserInteraction |
Qt::LinksAccessibleByKeyboard);
logsPathLabel->setOpenExternalLinks(true);
logs.append(this->createCheckBox("Enable logging",
getSettings()->enableLogging));
auto buttons = logs.emplace<QHBoxLayout>().withoutMargin();
// Select and Reset
auto selectDir = buttons.emplace<QPushButton>("Select log directory ");
auto resetDir = buttons.emplace<QPushButton>("Reset");
getSettings()->logPath.connect(
[element = resetDir.getElement()](const QString &path) {
element->setEnabled(!path.isEmpty());
});
buttons->addStretch();
logs->addStretch(1);
auto selectDir = logs.emplace<QPushButton>("Set custom logpath");
// Setting custom logpath
// Show how big (size-wise) the logs are
auto logsPathSizeLabel = logs.emplace<QLabel>();
logsPathSizeLabel->setText(
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
// Select event
QObject::connect(
selectDir.getElement(), &QPushButton::clicked, this,
[this, logsPathSizeLabel]() mutable {
@@ -128,8 +139,9 @@ ModerationPage::ModerationPage()
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
});
buttons->addSpacing(16);
// Reset custom logpath
auto resetDir = logs.emplace<QPushButton>("Reset logpath");
QObject::connect(resetDir.getElement(), &QPushButton::clicked, this,
[logsPathSizeLabel]() mutable {
getSettings()->logPath = "";
@@ -139,8 +151,7 @@ ModerationPage::ModerationPage()
[] { return fetchLogDirectorySize(); }));
});
// Logs end
}
} // logs end
auto modMode = tabs.appendTab(new QVBoxLayout, "Moderation buttons");
{
+64 -2
View File
@@ -5,15 +5,77 @@
#include <QDebug>
#include <QPainter>
#include <util/FunctionEventFilter.hpp>
namespace chatterino {
bool filterItemsRec(QObject *object, const QString &query)
{
bool any{};
for (auto &&child : object->children())
{
auto setOpacity = [&](auto *widget, bool condition) {
any |= condition;
widget->greyedOut = !condition;
widget->update();
};
if (auto x = dynamic_cast<SCheckBox *>(child); x)
{
setOpacity(x, x->text().contains(query, Qt::CaseInsensitive));
}
else if (auto x = dynamic_cast<SLabel *>(child); x)
{
setOpacity(x, x->text().contains(query, Qt::CaseInsensitive));
}
else if (auto x = dynamic_cast<SComboBox *>(child); x)
{
setOpacity(x, [=]() {
for (int i = 0; i < x->count(); i++)
{
if (x->itemText(i).contains(query, Qt::CaseInsensitive))
return true;
}
return false;
}());
}
else if (auto x = dynamic_cast<QTabWidget *>(child); x)
{
for (int i = 0; i < x->count(); i++)
{
bool tabAny{};
if (x->tabText(i).contains(query, Qt::CaseInsensitive))
{
tabAny = true;
}
auto widget = x->widget(i);
tabAny |= filterItemsRec(widget, query);
any |= tabAny;
}
}
else
{
any |= filterItemsRec(child, query);
}
}
return any;
}
SettingsPage::SettingsPage(const QString &name, const QString &iconResource)
: name_(name)
, iconResource_(iconResource)
{
}
bool SettingsPage::filterElements(const QString &query)
{
return filterItemsRec(this, query) || query.isEmpty() ||
this->name_.contains(query, Qt::CaseInsensitive);
}
const QString &SettingsPage::getName()
{
return this->name_;
@@ -42,7 +104,7 @@ void SettingsPage::cancel()
QCheckBox *SettingsPage::createCheckBox(
const QString &text, pajlada::Settings::Setting<bool> &setting)
{
QCheckBox *checkbox = new QCheckBox(text);
QCheckBox *checkbox = new SCheckBox(text);
// update when setting changes
setting.connect(
@@ -64,7 +126,7 @@ QCheckBox *SettingsPage::createCheckBox(
QComboBox *SettingsPage::createComboBox(
const QStringList &items, pajlada::Settings::Setting<QString> &setting)
{
QComboBox *combo = new QComboBox();
QComboBox *combo = new SComboBox();
// update setting on toogle
combo->addItems(items);
@@ -8,8 +8,38 @@
#include "singletons/Settings.hpp"
#define SETTINGS_PAGE_WIDGET_BOILERPLATE(type, parent) \
class type : public parent \
{ \
using parent::parent; \
\
public: \
bool greyedOut{}; \
\
protected: \
void paintEvent(QPaintEvent *e) override \
{ \
parent::paintEvent(e); \
\
if (this->greyedOut) \
{ \
QPainter painter(this); \
QColor color = QColor("#222222"); \
color.setAlphaF(0.7); \
painter.fillRect(this->rect(), color); \
} \
} \
};
namespace chatterino {
// S* widgets are the same as their Q* counterparts,
// but they can be greyed out and will be if you search.
SETTINGS_PAGE_WIDGET_BOILERPLATE(SCheckBox, QCheckBox)
SETTINGS_PAGE_WIDGET_BOILERPLATE(SLabel, QLabel)
SETTINGS_PAGE_WIDGET_BOILERPLATE(SComboBox, QComboBox)
SETTINGS_PAGE_WIDGET_BOILERPLATE(SPushButton, QPushButton)
class SettingsDialogTab;
class SettingsPage : public QFrame
@@ -22,6 +52,8 @@ public:
const QString &getName();
const QString &getIconResource();
virtual bool filterElements(const QString &query);
SettingsDialogTab *tab() const;
void setTab(SettingsDialogTab *tab);
@@ -1,34 +0,0 @@
#include "SpecialChannelsPage.hpp"
#include "Application.hpp"
#include "singletons/Settings.hpp"
#include "util/LayoutCreator.hpp"
#include <QGroupBox>
#include <QLabel>
#include <QVBoxLayout>
namespace chatterino {
SpecialChannelsPage::SpecialChannelsPage()
: SettingsPage("Special channels", "")
{
LayoutCreator<SpecialChannelsPage> layoutCreator(this);
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
auto mentions = layout.emplace<QGroupBox>("Mentions channel")
.setLayoutType<QVBoxLayout>();
{
mentions.emplace<QLabel>("Join /mentions to view your mentions.");
}
auto whispers =
layout.emplace<QGroupBox>("Whispers").setLayoutType<QVBoxLayout>();
{
whispers.emplace<QLabel>("Join /whispers to view your mentions.");
}
layout->addStretch(1);
}
} // namespace chatterino
@@ -1,13 +0,0 @@
#pragma once
#include "widgets/settingspages/SettingsPage.hpp"
namespace chatterino {
class SpecialChannelsPage : public SettingsPage
{
public:
SpecialChannelsPage();
};
} // namespace chatterino
+5 -1
View File
@@ -89,6 +89,7 @@ Split::Split(QWidget *parent)
{
this->setMouseTracking(true);
this->view_->setPausable(true);
this->view_->setFocusPolicy(Qt::FocusPolicy::NoFocus);
this->vbox_->setSpacing(0);
this->vbox_->setMargin(1);
@@ -663,7 +664,10 @@ void Split::reloadChannelAndSubscriberEmotes()
auto channel = this->getChannel();
if (auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get()))
twitchChannel->refreshChannelEmotes();
{
twitchChannel->refreshBTTVChannelEmotes();
twitchChannel->refreshFFZChannelEmotes();
}
}
template <typename Iter, typename RandomGenerator>
+5 -3
View File
@@ -189,7 +189,6 @@ void SplitHeader::initializeLayout()
SettingsDialogPreference::
ModerationActions);
this->split_->setModerationMode(true);
w->setDim(true);
}
else
{
@@ -198,7 +197,7 @@ void SplitHeader::initializeLayout()
this->split_->setModerationMode(
!moderationMode);
w->setDim(moderationMode);
w->setDim(Button::Dim(moderationMode));
}
break;
@@ -713,7 +712,10 @@ void SplitHeader::reloadChannelEmotes()
auto channel = this->split_->getChannel();
if (auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get()))
twitchChannel->refreshChannelEmotes();
{
twitchChannel->refreshFFZChannelEmotes();
twitchChannel->refreshBTTVChannelEmotes();
}
}
void SplitHeader::reloadSubscriberEmotes()