changed to 80 max column

This commit is contained in:
fourtf
2018-08-06 21:17:03 +02:00
parent defa7e41fa
commit f71ff08e68
203 changed files with 3792 additions and 2405 deletions
+6 -3
View File
@@ -39,10 +39,12 @@ AccountSwitchWidget::AccountSwitchWidget(QWidget *parent)
QObject::connect(this, &QListWidget::clicked, [=] {
if (!this->selectedItems().isEmpty()) {
QString newUsername = this->currentItem()->text();
if (newUsername.compare(ANONYMOUS_USERNAME_LABEL, Qt::CaseInsensitive) == 0) {
if (newUsername.compare(ANONYMOUS_USERNAME_LABEL,
Qt::CaseInsensitive) == 0) {
app->accounts->twitch.currentUsername = "";
} else {
app->accounts->twitch.currentUsername = newUsername.toStdString();
app->accounts->twitch.currentUsername =
newUsername.toStdString();
}
}
});
@@ -70,7 +72,8 @@ void AccountSwitchWidget::refreshSelection()
for (int i = 0; i < this->count(); ++i) {
QString itemText = this->item(i)->text();
if (itemText.compare(currentUsername, Qt::CaseInsensitive) == 0) {
if (itemText.compare(currentUsername, Qt::CaseInsensitive) ==
0) {
this->setCurrentRow(i);
break;
}
+21 -14
View File
@@ -129,14 +129,17 @@ void AttachedWindow::attachToHwnd(void *_attachedPtr)
DWORD processId;
::GetWindowThreadProcessId(attached, &processId);
HANDLE process =
::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId);
HANDLE process = ::OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId);
std::unique_ptr<TCHAR[]> filename(new TCHAR[512]);
DWORD filenameLength = ::GetModuleFileNameEx(process, nullptr, filename.get(), 512);
QString qfilename = QString::fromWCharArray(filename.get(), filenameLength);
DWORD filenameLength =
::GetModuleFileNameEx(process, nullptr, filename.get(), 512);
QString qfilename =
QString::fromWCharArray(filename.get(), filenameLength);
if (!qfilename.endsWith("chrome.exe") && !qfilename.endsWith("firefox.exe")) {
if (!qfilename.endsWith("chrome.exe") &&
!qfilename.endsWith("firefox.exe")) {
qDebug() << "NM Illegal caller" << qfilename;
this->timer_.stop();
this->deleteLater();
@@ -157,9 +160,9 @@ void AttachedWindow::updateWindowRect(void *_attachedPtr)
auto hwnd = HWND(this->winId());
auto attached = HWND(_attachedPtr);
// We get the window rect first so we can close this window when it returns an error.
// If we query the process first and check the filename then it will return and empty string
// that doens't match.
// We get the window rect first so we can close this window when it returns
// an error. If we query the process first and check the filename then it
// will return and empty string that doens't match.
::SetLastError(0);
RECT rect;
::GetWindowRect(attached, &rect);
@@ -189,21 +192,25 @@ void AttachedWindow::updateWindowRect(void *_attachedPtr)
}
if (this->height_ == -1) {
// ::MoveWindow(hwnd, rect.right - this->width_ - 8, rect.top + this->yOffset_ - 8,
// this->width_, rect.bottom - rect.top - this->yOffset_, false);
// ::MoveWindow(hwnd, rect.right - this->width_ - 8, rect.top +
// this->yOffset_ - 8,
// this->width_, rect.bottom - rect.top - this->yOffset_,
// false);
} else {
::MoveWindow(hwnd, //
int(rect.right - this->width_ * scale - 8), //
int(rect.bottom - this->height_ * scale - 8), //
int(this->width_ * scale), int(this->height_ * scale), true);
int(this->width_ * scale), int(this->height_ * scale),
true);
}
// ::MoveWindow(hwnd, rect.right - 360, rect.top + 82, 360 - 8, rect.bottom -
// rect.top - 82 - 8, false);
// ::MoveWindow(hwnd, rect.right - 360, rect.top + 82, 360 - 8,
// rect.bottom - rect.top - 82 - 8, false);
#endif
}
// void AttachedWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
// void AttachedWindow::nativeEvent(const QByteArray &eventType, void *message,
// long *result)
//{
// MSG *msg = reinterpret_cast
+2 -2
View File
@@ -28,8 +28,8 @@ public:
protected:
virtual void showEvent(QShowEvent *) override;
// virtual void nativeEvent(const QByteArray &eventType, void *message, long *result)
// override;
// virtual void nativeEvent(const QByteArray &eventType, void *message,
// long *result) override;
private:
struct {
+6 -3
View File
@@ -97,12 +97,14 @@ void BaseWidget::setScaleIndependantSize(QSize size)
void BaseWidget::setScaleIndependantWidth(int value)
{
this->setScaleIndependantSize(QSize(value, this->scaleIndependantSize_.height()));
this->setScaleIndependantSize(
QSize(value, this->scaleIndependantSize_.height()));
}
void BaseWidget::setScaleIndependantHeight(int value)
{
this->setScaleIndependantSize(QSize(this->scaleIndependantSize_.height(), value));
this->setScaleIndependantSize(
QSize(this->scaleIndependantSize_.height(), value));
}
void BaseWidget::childEvent(QChildEvent *event)
@@ -114,7 +116,8 @@ void BaseWidget::childEvent(QChildEvent *event)
this->widgets_.push_back(widget);
}
} else if (event->removed()) {
for (auto it = this->widgets_.begin(); it != this->widgets_.end(); it++) {
for (auto it = this->widgets_.begin(); it != this->widgets_.end();
it++) {
if (*it == event->child()) {
this->widgets_.erase(it);
break;
+72 -49
View File
@@ -41,7 +41,8 @@ namespace chatterino {
BaseWindow::BaseWindow(QWidget *parent, Flags _flags)
: BaseWidget(parent,
Qt::Window | ((_flags & TopMost) ? Qt::WindowStaysOnTopHint : Qt::WindowFlags()))
Qt::Window | ((_flags & TopMost) ? Qt::WindowStaysOnTopHint
: Qt::WindowFlags()))
, enableCustomFrame_(_flags & EnableCustomFrame)
, frameless_(_flags & Frameless)
, flags_(_flags)
@@ -59,7 +60,8 @@ BaseWindow::BaseWindow(QWidget *parent, Flags _flags)
this->updateScale();
createWindowShortcut(this, "CTRL+0", [] { getApp()->settings->uiScale.setValue(0); });
createWindowShortcut(this, "CTRL+0",
[] { getApp()->settings->uiScale.setValue(0); });
// QTimer::this->scaleChangedEvent(this->getScale());
}
@@ -88,16 +90,19 @@ void BaseWindow::init()
this->setLayout(layout);
{
if (!this->frameless_) {
QHBoxLayout *buttonLayout = this->ui_.titlebarBox = new QHBoxLayout();
QHBoxLayout *buttonLayout = this->ui_.titlebarBox =
new QHBoxLayout();
buttonLayout->setMargin(0);
layout->addLayout(buttonLayout);
// title
Label *title = new Label("Chatterino");
QObject::connect(this, &QWidget::windowTitleChanged,
[title](const QString &text) { title->setText(text); });
QObject::connect(
this, &QWidget::windowTitleChanged,
[title](const QString &text) { title->setText(text); });
QSizePolicy policy(QSizePolicy::Ignored, QSizePolicy::Preferred);
QSizePolicy policy(QSizePolicy::Ignored,
QSizePolicy::Preferred);
policy.setHorizontalStretch(1);
// title->setBaseSize(0, 0);
// title->setScaledContents(true);
@@ -113,14 +118,18 @@ void BaseWindow::init()
TitleBarButton *_exitButton = new TitleBarButton;
_exitButton->setButtonStyle(TitleBarButton::Close);
QObject::connect(_minButton, &TitleBarButton::clicked, this, [this] {
this->setWindowState(Qt::WindowMinimized | this->windowState());
});
QObject::connect(_maxButton, &TitleBarButton::clicked, this, [this] {
this->setWindowState(this->windowState() == Qt::WindowMaximized
? Qt::WindowActive
: Qt::WindowMaximized);
});
QObject::connect(_minButton, &TitleBarButton::clicked, this,
[this] {
this->setWindowState(Qt::WindowMinimized |
this->windowState());
});
QObject::connect(
_maxButton, &TitleBarButton::clicked, this, [this] {
this->setWindowState(this->windowState() ==
Qt::WindowMaximized
? Qt::WindowActive
: Qt::WindowMaximized);
});
QObject::connect(_exitButton, &TitleBarButton::clicked, this,
[this] { this->close(); });
@@ -157,8 +166,10 @@ void BaseWindow::init()
QTimer::singleShot(1, this, [this] {
getApp()->settings->windowTopMost.connect(
[this](bool topMost, auto) {
::SetWindowPos(HWND(this->winId()), topMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0,
0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
::SetWindowPos(HWND(this->winId()),
topMost ? HWND_TOPMOST : HWND_NOTOPMOST, 0,
0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
},
this->managedConnections_);
});
@@ -222,8 +233,9 @@ void BaseWindow::themeChangedEvent()
if (this->ui_.titleLabel) {
QPalette palette_title;
palette_title.setColor(QPalette::Foreground,
this->theme->isLightTheme() ? "#333" : "#ccc");
palette_title.setColor(
QPalette::Foreground,
this->theme->isLightTheme() ? "#333" : "#ccc");
this->ui_.titleLabel->setPalette(palette_title);
}
@@ -240,7 +252,8 @@ void BaseWindow::themeChangedEvent()
bool BaseWindow::event(QEvent *event)
{
if (event->type() == QEvent::WindowDeactivate /*|| event->type() == QEvent::FocusOut*/) {
if (event->type() ==
QEvent::WindowDeactivate /*|| event->type() == QEvent::FocusOut*/) {
this->onFocusLost();
}
@@ -255,11 +268,11 @@ void BaseWindow::wheelEvent(QWheelEvent *event)
if (event->modifiers() & Qt::ControlModifier) {
if (event->delta() > 0) {
getApp()->settings->uiScale.setValue(
WindowManager::clampUiScale(getApp()->settings->uiScale.getValue() + 1));
getApp()->settings->uiScale.setValue(WindowManager::clampUiScale(
getApp()->settings->uiScale.getValue() + 1));
} else {
getApp()->settings->uiScale.setValue(
WindowManager::clampUiScale(getApp()->settings->uiScale.getValue() - 1));
getApp()->settings->uiScale.setValue(WindowManager::clampUiScale(
getApp()->settings->uiScale.getValue() - 1));
}
}
}
@@ -288,7 +301,8 @@ void BaseWindow::mousePressEvent(QMouseEvent *event)
#ifndef Q_OS_WIN
if (this->flags_ & FramelessDraggable) {
this->movingRelativePos = event->localPos();
if (auto widget = this->childAt(event->localPos().x(), event->localPos().y())) {
if (auto widget =
this->childAt(event->localPos().x(), event->localPos().y())) {
std::function<bool(QWidget *)> recursiveCheckMouseTracking;
recursiveCheckMouseTracking = [&](QWidget *widget) {
if (widget == nullptr) {
@@ -341,8 +355,8 @@ void BaseWindow::mouseMoveEvent(QMouseEvent *event)
BaseWidget::mouseMoveEvent(event);
}
TitleBarButton *BaseWindow::addTitleBarButton(const TitleBarButton::Style &style,
std::function<void()> onClicked)
TitleBarButton *BaseWindow::addTitleBarButton(
const TitleBarButton::Style &style, std::function<void()> onClicked)
{
TitleBarButton *button = new TitleBarButton;
button->setScaleIndependantSize(30, 30);
@@ -351,7 +365,8 @@ TitleBarButton *BaseWindow::addTitleBarButton(const TitleBarButton::Style &style
this->ui_.titlebarBox->insertWidget(1, button);
button->setButtonStyle(style);
QObject::connect(button, &TitleBarButton::clicked, this, [onClicked] { onClicked(); });
QObject::connect(button, &TitleBarButton::clicked, this,
[onClicked] { onClicked(); });
return button;
}
@@ -364,7 +379,8 @@ RippleEffectLabel *BaseWindow::addTitleBarLabel(std::function<void()> onClicked)
this->ui_.buttons.push_back(button);
this->ui_.titlebarBox->insertWidget(1, button);
QObject::connect(button, &RippleEffectLabel::clicked, this, [onClicked] { onClicked(); });
QObject::connect(button, &RippleEffectLabel::clicked, this,
[onClicked] { onClicked(); });
return button;
}
@@ -375,7 +391,8 @@ void BaseWindow::changeEvent(QEvent *)
#ifdef USEWINSDK
if (this->ui_.maxButton) {
this->ui_.maxButton->setButtonStyle(this->windowState() & Qt::WindowMaximized
this->ui_.maxButton->setButtonStyle(this->windowState() &
Qt::WindowMaximized
? TitleBarButton::Unmaximize
: TitleBarButton::Maximize);
}
@@ -416,8 +433,7 @@ void BaseWindow::closeEvent(QCloseEvent *)
void BaseWindow::moveIntoDesktopRect(QWidget *parent)
{
if (!this->stayInScreenRect_)
return;
if (!this->stayInScreenRect_) return;
// move the widget into the screen geometry if it's not already in there
QDesktopWidget *desktop = QApplication::desktop();
@@ -438,11 +454,11 @@ void BaseWindow::moveIntoDesktopRect(QWidget *parent)
p.setY(s.bottom() - this->height());
}
if (p != this->pos())
this->move(p);
if (p != this->pos()) this->move(p);
}
bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
bool BaseWindow::nativeEvent(const QByteArray &eventType, void *message,
long *result)
{
#ifdef USEWINSDK
MSG *msg = reinterpret_cast<MSG *>(message);
@@ -503,8 +519,10 @@ void BaseWindow::paintEvent(QPaintEvent *)
void BaseWindow::updateScale()
{
auto scale = this->nativeScale_ *
(this->flags_ & DisableCustomScaling ? 1 : getApp()->windows->getUiScaleValue());
auto scale =
this->nativeScale_ * (this->flags_ & DisableCustomScaling
? 1
: getApp()->windows->getUiScaleValue());
this->setScale(scale);
for (auto child : this->findChildren<BaseWidget *>()) {
@@ -541,9 +559,11 @@ void BaseWindow::drawCustomWindowFrame(QPainter &painter)
if (this->hasCustomWindowFrame()) {
QPainter painter(this);
QColor bg = this->overrideBackgroundColor_.value_or(this->theme->window.background);
QColor bg = this->overrideBackgroundColor_.value_or(
this->theme->window.background);
painter.fillRect(QRect(0, 1, this->width() - 0, this->height() - 0), bg);
painter.fillRect(QRect(0, 1, this->width() - 0, this->height() - 0),
bg);
}
#endif
}
@@ -561,7 +581,8 @@ bool BaseWindow::handleDPICHANGED(MSG *msg)
auto *prcNewWindow = reinterpret_cast<RECT *>(msg->lParam);
SetWindowPos(msg->hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
prcNewWindow->right - prcNewWindow->left,
prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
prcNewWindow->bottom - prcNewWindow->top,
SWP_NOZORDER | SWP_NOACTIVATE);
}
firstResize = false;
@@ -605,7 +626,8 @@ bool BaseWindow::handleNCCALCSIZE(MSG *msg, long *result)
// int cy = GetSystemMetrics(SM_CYSIZEFRAME);
if (msg->wParam == TRUE) {
NCCALCSIZE_PARAMS *ncp = (reinterpret_cast<NCCALCSIZE_PARAMS *>(msg->lParam));
NCCALCSIZE_PARAMS *ncp =
(reinterpret_cast<NCCALCSIZE_PARAMS *>(msg->lParam));
ncp->lppos->flags |= SWP_NOREDRAW;
RECT *clientRect = &ncp->rgrc[0];
@@ -634,7 +656,8 @@ bool BaseWindow::handleSIZE(MSG *msg)
if (msg->wParam == SIZE_MAXIMIZED) {
auto offset = int(this->getScale() * 8);
this->ui_.windowLayout->setContentsMargins(offset, offset, offset, offset);
this->ui_.windowLayout->setContentsMargins(offset, offset,
offset, offset);
} else {
this->ui_.windowLayout->setContentsMargins(0, 1, 0, 0);
}
@@ -686,23 +709,23 @@ bool BaseWindow::handleNCHITTEST(MSG *msg, long *result)
}
if (resizeWidth && resizeHeight) {
// bottom left corner
if (x >= winrect.left && x < winrect.left + border_width && y < winrect.bottom &&
y >= winrect.bottom - border_width) {
if (x >= winrect.left && x < winrect.left + border_width &&
y < winrect.bottom && y >= winrect.bottom - border_width) {
*result = HTBOTTOMLEFT;
}
// bottom right corner
if (x < winrect.right && x >= winrect.right - border_width && y < winrect.bottom &&
y >= winrect.bottom - border_width) {
if (x < winrect.right && x >= winrect.right - border_width &&
y < winrect.bottom && y >= winrect.bottom - border_width) {
*result = HTBOTTOMRIGHT;
}
// top left corner
if (x >= winrect.left && x < winrect.left + border_width && y >= winrect.top &&
y < winrect.top + border_width) {
if (x >= winrect.left && x < winrect.left + border_width &&
y >= winrect.top && y < winrect.top + border_width) {
*result = HTTOPLEFT;
}
// top right corner
if (x < winrect.right && x >= winrect.right - border_width && y >= winrect.top &&
y < winrect.top + border_width) {
if (x < winrect.right && x >= winrect.right - border_width &&
y >= winrect.top && y < winrect.top + border_width) {
*result = HTTOPRIGHT;
}
}
+2 -1
View File
@@ -55,7 +55,8 @@ public:
pajlada::Signals::NoArgSignal closing;
protected:
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
virtual bool nativeEvent(const QByteArray &eventType, void *message,
long *result) override;
virtual void scaleChangedEvent(float) override;
virtual void paintEvent(QPaintEvent *) override;
+8 -6
View File
@@ -18,7 +18,8 @@ Label::Label(BaseWidget *parent, QString text, FontStyle style)
{
auto app = getApp();
this->connections_.managedConnect(app->fonts->fontChanged, [this] { this->updateSize(); });
this->connections_.managedConnect(app->fonts->fontChanged,
[this] { this->updateSize(); });
}
const QString &Label::getText() const
@@ -88,11 +89,11 @@ void Label::paintEvent(QPaintEvent *)
QPainter painter(this);
QFontMetrics metrics = app->fonts->getFontMetrics(
this->getFontStyle(),
this->getScale() * 96.f / this->logicalDpiX() * this->devicePixelRatioF());
this->getFontStyle(), this->getScale() * 96.f / this->logicalDpiX() *
this->devicePixelRatioF());
painter.setFont(app->fonts->getFont(
this->getFontStyle(),
this->getScale() * 96.f / this->logicalDpiX() * this->devicePixelRatioF()));
this->getFontStyle(), this->getScale() * 96.f / this->logicalDpiX() *
this->devicePixelRatioF()));
int offset = this->getOffset();
@@ -118,7 +119,8 @@ void Label::updateSize()
{
auto app = getApp();
QFontMetrics metrics = app->fonts->getFontMetrics(this->fontStyle_, this->getScale());
QFontMetrics metrics =
app->fonts->getFontMetrics(this->fontStyle_, this->getScale());
int width = metrics.width(this->text_) + (2 * this->getOffset());
int height = metrics.height();
+2 -1
View File
@@ -10,7 +10,8 @@ namespace chatterino {
class Label : public BaseWidget
{
public:
explicit Label(QString text = QString(), FontStyle style = FontStyle::UiMedium);
explicit Label(QString text = QString(),
FontStyle style = FontStyle::UiMedium);
explicit Label(BaseWidget *parent, QString text = QString(),
FontStyle style = FontStyle::UiMedium);
+37 -23
View File
@@ -34,10 +34,12 @@ Notebook::Notebook(QWidget *parent)
this->addButton_.setHidden(true);
auto *shortcut_next = new QShortcut(QKeySequence("Ctrl+Tab"), this);
QObject::connect(shortcut_next, &QShortcut::activated, [this] { this->selectNextTab(); });
QObject::connect(shortcut_next, &QShortcut::activated,
[this] { this->selectNextTab(); });
auto *shortcut_prev = new QShortcut(QKeySequence("Ctrl+Shift+Tab"), this);
QObject::connect(shortcut_prev, &QShortcut::activated, [this] { this->selectPreviousTab(); });
QObject::connect(shortcut_prev, &QShortcut::activated,
[this] { this->selectPreviousTab(); });
}
NotebookTab *Notebook::addPage(QWidget *page, QString title, bool select)
@@ -134,7 +136,8 @@ void Notebook::select(QWidget *page)
qDebug() << item.selectedWidget;
item.selectedWidget->setFocus(Qt::MouseFocusReason);
} else {
qDebug() << "Notebook: selected child of page doesn't exist anymore";
qDebug()
<< "Notebook: selected child of page doesn't exist anymore";
}
}
}
@@ -165,21 +168,23 @@ bool Notebook::containsPage(QWidget *page)
Notebook::Item &Notebook::findItem(QWidget *page)
{
auto it = std::find_if(this->items_.begin(), this->items_.end(),
[page](const auto &item) { return page == item.page; });
auto it =
std::find_if(this->items_.begin(), this->items_.end(),
[page](const auto &item) { return page == item.page; });
assert(it != this->items_.end());
return *it;
}
bool Notebook::containsChild(const QObject *obj, const QObject *child)
{
return std::any_of(obj->children().begin(), obj->children().end(), [child](const QObject *o) {
if (o == child) {
return true;
}
return std::any_of(obj->children().begin(), obj->children().end(),
[child](const QObject *o) {
if (o == child) {
return true;
}
return containsChild(o, child);
});
return containsChild(o, child);
});
}
void Notebook::selectIndex(int index)
@@ -328,8 +333,10 @@ void Notebook::performLayout(bool animated)
for (auto i = this->items_.begin(); i != this->items_.end(); i++) {
bool wrap =
!first && (((i + 1 == this->items_.end() && this->showAddButton_) ? tabHeight : 0) + x +
i->tab->width()) > width();
!first &&
(((i + 1 == this->items_.end() && this->showAddButton_) ? tabHeight
: 0) +
x + i->tab->width()) > width();
if (wrap) {
y += i->tab->height();
@@ -376,8 +383,8 @@ void Notebook::paintEvent(QPaintEvent *event)
BaseWidget::paintEvent(event);
QPainter painter(this);
painter.fillRect(0, this->lineY_, this->width(), (int)(3 * this->getScale()),
this->theme->tabs.bottomLine);
painter.fillRect(0, this->lineY_, this->width(),
(int)(3 * this->getScale()), this->theme->tabs.bottomLine);
}
NotebookButton *Notebook::getAddButton()
@@ -409,8 +416,9 @@ NotebookTab *Notebook::getTabFromPage(QWidget *page)
SplitNotebook::SplitNotebook(Window *parent)
: Notebook(parent)
{
this->connect(this->getAddButton(), &NotebookButton::clicked,
[this]() { QTimer::singleShot(80, this, [this] { this->addPage(true); }); });
this->connect(this->getAddButton(), &NotebookButton::clicked, [this]() {
QTimer::singleShot(80, this, [this] { this->addPage(true); });
});
bool customFrame = parent->hasCustomWindowFrame();
@@ -424,10 +432,12 @@ void SplitNotebook::addCustomButtons()
// settings
auto settingsBtn = this->addCustomButton();
settingsBtn->setVisible(!getApp()->settings->hidePreferencesButton.getValue());
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);
@@ -438,17 +448,20 @@ void SplitNotebook::addCustomButtons()
auto userBtn = this->addCustomButton();
userBtn->setVisible(!getApp()->settings->hideUserButton.getValue());
getApp()->settings->hideUserButton.connect(
[userBtn](bool hide, auto) { userBtn->setVisible(!hide); }, this->connections_);
[userBtn](bool hide, auto) { userBtn->setVisible(!hide); },
this->connections_);
userBtn->setIcon(NotebookButton::User);
QObject::connect(userBtn, &NotebookButton::clicked, [this, userBtn] {
getApp()->windows->showAccountSelectPopup(this->mapToGlobal(userBtn->rect().bottomRight()));
getApp()->windows->showAccountSelectPopup(
this->mapToGlobal(userBtn->rect().bottomRight()));
});
// updates
auto updateBtn = this->addCustomButton();
initUpdateButton(*updateBtn, this->updateDialogHandle_, this->signalHolder_);
initUpdateButton(*updateBtn, this->updateDialogHandle_,
this->signalHolder_);
}
SplitContainer *SplitNotebook::addPage(bool select)
@@ -465,7 +478,8 @@ SplitContainer *SplitNotebook::getOrAddSelectedPage()
{
auto *selectedPage = this->getSelectedPage();
return selectedPage != nullptr ? (SplitContainer *)selectedPage : this->addPage();
return selectedPage != nullptr ? (SplitContainer *)selectedPage
: this->addPage();
}
} // namespace chatterino
+2 -1
View File
@@ -23,7 +23,8 @@ class Notebook : public BaseWidget
public:
explicit Notebook(QWidget *parent);
NotebookTab *addPage(QWidget *page, QString title = QString(), bool select = false);
NotebookTab *addPage(QWidget *page, QString title = QString(),
bool select = false);
void removePage(QWidget *page);
void removeCurrentPage();
+39 -23
View File
@@ -21,7 +21,8 @@ Scrollbar::Scrollbar(ChannelView *parent)
{
resize(int(16 * this->getScale()), 100);
this->currentValueAnimation_.setDuration(150);
this->currentValueAnimation_.setEasingCurve(QEasingCurve(QEasingCurve::OutCubic));
this->currentValueAnimation_.setEasingCurve(
QEasingCurve(QEasingCurve::OutCubic));
setMouseTracking(true);
}
@@ -32,7 +33,8 @@ void Scrollbar::addHighlight(ScrollbarHighlight highlight)
this->highlights_.pushBack(highlight, deleted);
}
void Scrollbar::addHighlightsAtStart(const std::vector<ScrollbarHighlight> &_highlights)
void Scrollbar::addHighlightsAtStart(
const std::vector<ScrollbarHighlight> &_highlights)
{
this->highlights_.pushFront(_highlights);
}
@@ -103,28 +105,35 @@ void Scrollbar::setDesiredValue(qreal value, bool animated)
{
auto app = getApp();
animated &= app->settings->enableSmoothScrolling.getValue();
value = std::max(this->minimum_, std::min(this->maximum_ - this->largeChange_, value));
value = std::max(this->minimum_,
std::min(this->maximum_ - this->largeChange_, value));
if (std::abs(this->desiredValue_ + this->smoothScrollingOffset_ - value) > 0.0001) {
if (std::abs(this->desiredValue_ + this->smoothScrollingOffset_ - value) >
0.0001) {
if (animated) {
this->currentValueAnimation_.stop();
this->currentValueAnimation_.setStartValue(this->currentValue_ +
this->smoothScrollingOffset_);
this->currentValueAnimation_.setStartValue(
this->currentValue_ + this->smoothScrollingOffset_);
// if (((this->getMaximum() - this->getLargeChange()) - value) <= 0.01) {
// if (((this->getMaximum() - this->getLargeChange()) -
// value) <= 0.01) {
// value += 1;
// }
this->currentValueAnimation_.setEndValue(value);
this->smoothScrollingOffset_ = 0;
this->atBottom_ = ((this->getMaximum() - this->getLargeChange()) - value) <= 0.0001;
this->atBottom_ = ((this->getMaximum() - this->getLargeChange()) -
value) <= 0.0001;
this->currentValueAnimation_.start();
} else {
if (this->currentValueAnimation_.state() != QPropertyAnimation::Running) {
if (this->currentValueAnimation_.state() !=
QPropertyAnimation::Running) {
this->smoothScrollingOffset_ = 0;
this->desiredValue_ = value;
this->currentValueAnimation_.stop();
this->atBottom_ = ((this->getMaximum() - this->getLargeChange()) - value) <= 0.0001;
this->atBottom_ =
((this->getMaximum() - this->getLargeChange()) - value) <=
0.0001;
setCurrentValue(value);
}
}
@@ -187,8 +196,9 @@ pajlada::Signals::NoArgSignal &Scrollbar::getDesiredValueChanged()
void Scrollbar::setCurrentValue(qreal value)
{
value = std::max(this->minimum_, std::min(this->maximum_ - this->largeChange_,
value + this->smoothScrollingOffset_));
value = std::max(this->minimum_,
std::min(this->maximum_ - this->largeChange_,
value + this->smoothScrollingOffset_));
if (std::abs(this->currentValue_ - value) > 0.0001) {
this->currentValue_ = value;
@@ -221,15 +231,16 @@ void Scrollbar::paintEvent(QPaintEvent *)
// painter.fillRect(QRect(xOffset, 0, width(), this->buttonHeight),
// this->themeManager->ScrollbarArrow);
// painter.fillRect(QRect(xOffset, height() - this->buttonHeight, width(),
// this->buttonHeight),
// painter.fillRect(QRect(xOffset, height() - this->buttonHeight,
// width(), this->buttonHeight),
// this->themeManager->ScrollbarArrow);
this->thumbRect_.setX(xOffset);
// mouse over thumb
if (this->mouseDownIndex_ == 2) {
painter.fillRect(this->thumbRect_, this->theme->scrollbars.thumbSelected);
painter.fillRect(this->thumbRect_,
this->theme->scrollbars.thumbSelected);
}
// mouse not over thumb
else {
@@ -265,7 +276,8 @@ void Scrollbar::paintEvent(QPaintEvent *)
switch (highlight.getStyle()) {
case ScrollbarHighlight::Default: {
painter.fillRect(w / 8 * 3, int(y), w / 4, highlightHeight, color);
painter.fillRect(w / 8 * 3, int(y), w / 4, highlightHeight,
color);
} break;
case ScrollbarHighlight::Line: {
@@ -310,7 +322,8 @@ void Scrollbar::mouseMoveEvent(QMouseEvent *event)
} else if (this->mouseDownIndex_ == 2) {
int delta = event->pos().y() - this->lastMousePosition_.y();
setDesiredValue(this->desiredValue_ + qreal(delta) / this->trackHeight_ * this->maximum_);
setDesiredValue(this->desiredValue_ +
qreal(delta) / this->trackHeight_ * this->maximum_);
}
this->lastMousePosition_ = event->pos();
@@ -370,13 +383,16 @@ void Scrollbar::leaveEvent(QEvent *)
void Scrollbar::updateScroll()
{
this->trackHeight_ =
this->height() - this->buttonHeight_ - this->buttonHeight_ - MIN_THUMB_HEIGHT - 1;
this->trackHeight_ = this->height() - this->buttonHeight_ -
this->buttonHeight_ - MIN_THUMB_HEIGHT - 1;
this->thumbRect_ = QRect(
0, int(this->currentValue_ / this->maximum_ * this->trackHeight_) + 1 + this->buttonHeight_,
this->width(),
int(this->largeChange_ / this->maximum_ * this->trackHeight_) + MIN_THUMB_HEIGHT);
this->thumbRect_ =
QRect(0,
int(this->currentValue_ / this->maximum_ * this->trackHeight_) +
1 + this->buttonHeight_,
this->width(),
int(this->largeChange_ / this->maximum_ * this->trackHeight_) +
MIN_THUMB_HEIGHT);
this->update();
}
+2 -1
View File
@@ -22,7 +22,8 @@ public:
Scrollbar(ChannelView *parent = nullptr);
void addHighlight(ScrollbarHighlight highlight);
void addHighlightsAtStart(const std::vector<ScrollbarHighlight> &highlights_);
void addHighlightsAtStart(
const std::vector<ScrollbarHighlight> &highlights_);
void replaceHighlight(size_t index, ScrollbarHighlight replacement);
void pauseHighlights();
+4 -2
View File
@@ -16,9 +16,11 @@ StreamView::StreamView(ChannelPtr channel, const QUrl &url)
LayoutCreator<StreamView> layoutCreator(this);
#ifdef USEWEBENGINE
auto web = layoutCreator.emplace<QWebEngineView>(this).assign(&this->stream);
auto web =
layoutCreator.emplace<QWebEngineView>(this).assign(&this->stream);
web->setUrl(url);
web->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
web->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled,
true);
#endif
auto chat = layoutCreator.emplace<ChannelView>();
+6 -3
View File
@@ -36,7 +36,8 @@ TooltipWidget::TooltipWidget(BaseWidget *parent)
this->setStayInScreenRect(true);
this->setAttribute(Qt::WA_ShowWithoutActivating);
this->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint |
this->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint |
Qt::X11BypassWindowManagerHint |
Qt::BypassWindowManagerHint);
displayText_->setAlignment(Qt::AlignHCenter);
@@ -46,7 +47,8 @@ TooltipWidget::TooltipWidget(BaseWidget *parent)
layout->addWidget(displayText_);
this->setLayout(layout);
this->fontChangedConnection_ = app->fonts->fontChanged.connect([this] { this->updateFont(); });
this->fontChangedConnection_ =
app->fonts->fontChanged.connect([this] { this->updateFont(); });
}
TooltipWidget::~TooltipWidget()
@@ -76,7 +78,8 @@ void TooltipWidget::updateFont()
{
auto app = getApp();
this->setFont(app->fonts->getFont(Fonts::Type::ChatMediumSmall, this->getScale()));
this->setFont(
app->fonts->getFont(Fonts::Type::ChatMediumSmall, this->getScale()));
}
void TooltipWidget::setText(QString text)
+44 -27
View File
@@ -38,7 +38,8 @@ Window::Window(Type type)
this->addShortcuts();
this->addLayout();
getApp()->accounts->twitch.currentUserChanged.connect([this] { this->onAccountSelected(); });
getApp()->accounts->twitch.currentUserChanged.connect(
[this] { this->onAccountSelected(); });
this->onAccountSelected();
if (type == Type::Main) {
@@ -86,7 +87,8 @@ bool Window::event(QEvent *event)
}
}
if (SplitContainer *container = dynamic_cast<SplitContainer *>(page)) {
if (SplitContainer *container =
dynamic_cast<SplitContainer *>(page)) {
container->hideResizeHandles();
}
} break;
@@ -103,10 +105,11 @@ void Window::showEvent(QShowEvent *event)
if (getApp()->settings->startUpNotification.getValue() < 1) {
getApp()->settings->startUpNotification = 1;
auto box =
new QMessageBox(QMessageBox::Information, "Chatterino 2 Beta",
"Please note that this software is not stable yet. Things are rough "
"around the edges and everything is subject to change.");
auto box = new QMessageBox(
QMessageBox::Information, "Chatterino 2 Beta",
"Please note that this software is not stable yet. Things are "
"rough "
"around the edges and everything is subject to change.");
box->setAttribute(Qt::WA_DeleteOnClose);
box->show();
}
@@ -114,11 +117,13 @@ void Window::showEvent(QShowEvent *event)
// Show changelog
if (getApp()->settings->currentVersion.getValue() != "" &&
getApp()->settings->currentVersion.getValue() != CHATTERINO_VERSION) {
auto box = new QMessageBox(QMessageBox::Information, "Chatterino 2 Beta", "Show changelog?",
auto box = new QMessageBox(QMessageBox::Information,
"Chatterino 2 Beta", "Show changelog?",
QMessageBox::Yes | QMessageBox::No);
box->setAttribute(Qt::WA_DeleteOnClose);
if (box->exec() == QMessageBox::Yes) {
QDesktopServices::openUrl(QUrl("https://fourtf.com/chatterino-changelog/"));
QDesktopServices::openUrl(
QUrl("https://fourtf.com/chatterino-changelog/"));
}
}
@@ -174,8 +179,8 @@ void Window::addCustomTitlebarButtons()
// account
this->userLabel_ = this->addTitleBarLabel([this] {
getApp()->windows->showAccountSelectPopup(
this->userLabel_->mapToGlobal(this->userLabel_->rect().bottomLeft())); //
getApp()->windows->showAccountSelectPopup(this->userLabel_->mapToGlobal(
this->userLabel_->rect().bottomLeft())); //
});
this->userLabel_->setMinimumWidth(20 * getScale());
}
@@ -246,26 +251,36 @@ void Window::addShortcuts()
createWindowShortcut(this, "CTRL+P", [] { SettingsDialog::showDialog(); });
// Switch tab
createWindowShortcut(this, "CTRL+T",
[this] { this->notebook_.getOrAddSelectedPage()->appendNewSplit(true); });
createWindowShortcut(this, "CTRL+T", [this] {
this->notebook_.getOrAddSelectedPage()->appendNewSplit(true);
});
createWindowShortcut(this, "CTRL+1", [this] { this->notebook_.selectIndex(0); });
createWindowShortcut(this, "CTRL+2", [this] { this->notebook_.selectIndex(1); });
createWindowShortcut(this, "CTRL+3", [this] { this->notebook_.selectIndex(2); });
createWindowShortcut(this, "CTRL+4", [this] { this->notebook_.selectIndex(3); });
createWindowShortcut(this, "CTRL+5", [this] { this->notebook_.selectIndex(4); });
createWindowShortcut(this, "CTRL+6", [this] { this->notebook_.selectIndex(5); });
createWindowShortcut(this, "CTRL+7", [this] { this->notebook_.selectIndex(6); });
createWindowShortcut(this, "CTRL+8", [this] { this->notebook_.selectIndex(7); });
createWindowShortcut(this, "CTRL+9", [this] { this->notebook_.selectIndex(8); });
createWindowShortcut(this, "CTRL+1",
[this] { this->notebook_.selectIndex(0); });
createWindowShortcut(this, "CTRL+2",
[this] { this->notebook_.selectIndex(1); });
createWindowShortcut(this, "CTRL+3",
[this] { this->notebook_.selectIndex(2); });
createWindowShortcut(this, "CTRL+4",
[this] { this->notebook_.selectIndex(3); });
createWindowShortcut(this, "CTRL+5",
[this] { this->notebook_.selectIndex(4); });
createWindowShortcut(this, "CTRL+6",
[this] { this->notebook_.selectIndex(5); });
createWindowShortcut(this, "CTRL+7",
[this] { this->notebook_.selectIndex(6); });
createWindowShortcut(this, "CTRL+8",
[this] { this->notebook_.selectIndex(7); });
createWindowShortcut(this, "CTRL+9",
[this] { this->notebook_.selectIndex(8); });
// Zoom in
{
auto s = new QShortcut(QKeySequence::ZoomIn, this);
s->setContext(Qt::WindowShortcut);
QObject::connect(s, &QShortcut::activated, this, [] {
getApp()->settings->uiScale.setValue(
WindowManager::clampUiScale(getApp()->settings->uiScale.getValue() + 1));
getApp()->settings->uiScale.setValue(WindowManager::clampUiScale(
getApp()->settings->uiScale.getValue() + 1));
});
}
@@ -274,16 +289,18 @@ void Window::addShortcuts()
auto s = new QShortcut(QKeySequence::ZoomOut, this);
s->setContext(Qt::WindowShortcut);
QObject::connect(s, &QShortcut::activated, this, [] {
getApp()->settings->uiScale.setValue(
WindowManager::clampUiScale(getApp()->settings->uiScale.getValue() - 1));
getApp()->settings->uiScale.setValue(WindowManager::clampUiScale(
getApp()->settings->uiScale.getValue() - 1));
});
}
// New tab
createWindowShortcut(this, "CTRL+SHIFT+T", [this] { this->notebook_.addPage(true); });
createWindowShortcut(this, "CTRL+SHIFT+T",
[this] { this->notebook_.addPage(true); });
// Close tab
createWindowShortcut(this, "CTRL+SHIFT+W", [this] { this->notebook_.removeCurrentPage(); });
createWindowShortcut(this, "CTRL+SHIFT+W",
[this] { this->notebook_.removeCurrentPage(); });
}
void Window::onAccountSelected()
+25 -15
View File
@@ -19,9 +19,11 @@ EmotePopup::EmotePopup()
this->viewEmojis_ = new ChannelView();
this->viewEmotes_->setOverrideFlags(MessageElement::Flags(
MessageElement::Default | MessageElement::AlwaysShow | MessageElement::EmoteImages));
MessageElement::Default | MessageElement::AlwaysShow |
MessageElement::EmoteImages));
this->viewEmojis_->setOverrideFlags(MessageElement::Flags(
MessageElement::Default | MessageElement::AlwaysShow | MessageElement::EmoteImages));
MessageElement::Default | MessageElement::AlwaysShow |
MessageElement::EmoteImages));
this->viewEmotes_->setEnableScrollingToBottom(false);
this->viewEmojis_->setEnableScrollingToBottom(false);
@@ -56,7 +58,8 @@ void EmotePopup::loadChannel(ChannelPtr _channel)
ChannelPtr emoteChannel(new Channel("", Channel::Type::None));
auto addEmotes = [&](const EmoteMap &map, const QString &title, const QString &emoteDesc) {
auto addEmotes = [&](const EmoteMap &map, const QString &title,
const QString &emoteDesc) {
// TITLE
MessageBuilder builder1;
@@ -71,8 +74,10 @@ void EmotePopup::loadChannel(ChannelPtr _channel)
builder2.getMessage()->flags |= Message::DisableCompactEmotes;
for (auto emote : map) {
builder2.append((new EmoteElement(emote.second, MessageElement::Flags::AlwaysShow))
->setLink(Link(Link::InsertText, emote.first.string)));
builder2.append(
(new EmoteElement(emote.second,
MessageElement::Flags::AlwaysShow))
->setLink(Link(Link::InsertText, emote.first.string)));
}
emoteChannel->addMessage(builder2.getMessage());
@@ -80,9 +85,10 @@ void EmotePopup::loadChannel(ChannelPtr _channel)
auto app = getApp();
// 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->accounts->twitch.getCurrent()->accessEmotes()->emoteSets) {
// 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->accounts->twitch.getCurrent()->accessEmotes()->emoteSets) {
// TITLE
MessageBuilder builder1;
@@ -109,18 +115,21 @@ void EmotePopup::loadChannel(ChannelPtr _channel)
for (const auto &emote : set->emotes) {
builder2.append(
(new EmoteElement(app->emotes->twitch.getOrCreateEmote(emote.id, emote.name),
MessageElement::Flags::AlwaysShow))
(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.accessGlobalEmotes(), "BetterTTV Global Emotes",
"BetterTTV Global Emote");
addEmotes(*channel->accessBttvEmotes(), "BetterTTV Channel Emotes", "BetterTTV Channel Emote");
// addEmotes(*app->emotes->ffz.accessGlobalEmotes(), "FrankerFaceZ Global Emotes",
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");
@@ -149,7 +158,8 @@ void EmotePopup::loadEmojis()
emojis.each([&builder](const auto &key, const auto &value) {
builder.append(
(new EmoteElement(value->emote, MessageElement::Flags::AlwaysShow))
->setLink(Link(Link::Type::InsertText, ":" + value->shortCodes[0] + ":")));
->setLink(Link(Link::Type::InsertText,
":" + value->shortCodes[0] + ":")));
});
emojiChannel->addMessage(builder.getMessage());
+22 -15
View File
@@ -16,10 +16,11 @@ LastRunCrashDialog::LastRunCrashDialog()
this->setWindowFlag(Qt::WindowContextHelpButtonHint, false);
this->setWindowTitle("Chatterino");
auto layout = LayoutCreator<LastRunCrashDialog>(this).setLayoutType<QVBoxLayout>();
auto layout =
LayoutCreator<LastRunCrashDialog>(this).setLayoutType<QVBoxLayout>();
layout.emplace<QLabel>(
"The application wasn't terminated properly the last time it was executed.");
layout.emplace<QLabel>("The application wasn't terminated properly the "
"last time it was executed.");
layout->addSpacing(16);
@@ -28,7 +29,8 @@ LastRunCrashDialog::LastRunCrashDialog()
// auto *installUpdateButton = buttons->addButton("Install Update",
// QDialogButtonBox::NoRole); installUpdateButton->setEnabled(false);
// QObject::connect(installUpdateButton, &QPushButton::clicked, [this, update]() mutable {
// QObject::connect(installUpdateButton, &QPushButton::clicked, [this,
// update]() mutable {
// auto &updateManager = UpdateManager::getInstance();
// updateManager.installUpdates();
@@ -36,8 +38,10 @@ LastRunCrashDialog::LastRunCrashDialog()
// update->setText("Downloading updates...");
// });
auto *okButton = buttons->addButton("Ignore", QDialogButtonBox::ButtonRole::NoRole);
QObject::connect(okButton, &QPushButton::clicked, [this] { this->accept(); });
auto *okButton =
buttons->addButton("Ignore", QDialogButtonBox::ButtonRole::NoRole);
QObject::connect(okButton, &QPushButton::clicked,
[this] { this->accept(); });
// Updates
// auto updateUpdateLabel = [update]() mutable {
@@ -57,28 +61,31 @@ LastRunCrashDialog::LastRunCrashDialog()
// update->setText("No update abailable.");
// } break;
// case UpdateManager::SearchFailed: {
// update->setText("Error while searching for update.\nEither the update service
// is "
// "temporarily down or there is an issue with your
// installation.");
// update->setText("Error while searching for update.\nEither
// the update service is "
// "temporarily down or there is an issue
// with your installation.");
// } break;
// case UpdateManager::Downloading: {
// update->setText(
// "Downloading the update. Chatterino will close once the download is
// done.");
// "Downloading the update. Chatterino will close once
// the download is done.");
// } break;
// case UpdateManager::DownloadFailed: {
// update->setText("Download failed.");
// } break;
// case UpdateManager::WriteFileFailed: {
// update->setText("Writing the update file to the hard drive failed.");
// update->setText("Writing the update file to the hard drive
// failed.");
// } break;
// }
// };
// updateUpdateLabel();
// this->managedConnect(updateManager.statusUpdated, [updateUpdateLabel](auto) mutable {
// postToThread([updateUpdateLabel]() mutable { updateUpdateLabel(); });
// this->managedConnect(updateManager.statusUpdated,
// [updateUpdateLabel](auto) mutable {
// postToThread([updateUpdateLabel]() mutable { updateUpdateLabel();
// });
// });
}
+62 -40
View File
@@ -20,8 +20,10 @@ namespace chatterino {
namespace {
void LogInWithCredentials(const std::string &userID, const std::string &username,
const std::string &clientID, const std::string &oauthToken)
void LogInWithCredentials(const std::string &userID,
const std::string &username,
const std::string &clientID,
const std::string &oauthToken)
{
QStringList errors;
@@ -49,12 +51,16 @@ void LogInWithCredentials(const std::string &userID, const std::string &username
// QMessageBox messageBox;
// messageBox.setIcon(QMessageBox::Information);
// messageBox.setText("Successfully logged in with user <b>" + qS(username) + "</b>!");
pajlada::Settings::Setting<std::string>::set("/accounts/uid" + userID + "/username", username);
pajlada::Settings::Setting<std::string>::set("/accounts/uid" + userID + "/userID", userID);
pajlada::Settings::Setting<std::string>::set("/accounts/uid" + userID + "/clientID", clientID);
pajlada::Settings::Setting<std::string>::set("/accounts/uid" + userID + "/oauthToken",
oauthToken);
// messageBox.setText("Successfully logged in with user <b>" +
// qS(username) + "</b>!");
pajlada::Settings::Setting<std::string>::set(
"/accounts/uid" + userID + "/username", username);
pajlada::Settings::Setting<std::string>::set(
"/accounts/uid" + userID + "/userID", userID);
pajlada::Settings::Setting<std::string>::set(
"/accounts/uid" + userID + "/clientID", clientID);
pajlada::Settings::Setting<std::string>::set(
"/accounts/uid" + userID + "/oauthToken", oauthToken);
getApp()->accounts->twitch.reloadUsers();
@@ -142,46 +148,59 @@ AdvancedLoginWidget::AdvancedLoginWidget()
this->ui_.oauthTokenInput.setEchoMode(QLineEdit::Password);
connect(&this->ui_.userIDInput, &QLineEdit::textChanged, [=]() { this->refreshButtons(); });
connect(&this->ui_.usernameInput, &QLineEdit::textChanged, [=]() { this->refreshButtons(); });
connect(&this->ui_.clientIDInput, &QLineEdit::textChanged, [=]() { this->refreshButtons(); });
connect(&this->ui_.oauthTokenInput, &QLineEdit::textChanged, [=]() { this->refreshButtons(); });
connect(&this->ui_.userIDInput, &QLineEdit::textChanged,
[=]() { this->refreshButtons(); });
connect(&this->ui_.usernameInput, &QLineEdit::textChanged,
[=]() { this->refreshButtons(); });
connect(&this->ui_.clientIDInput, &QLineEdit::textChanged,
[=]() { this->refreshButtons(); });
connect(&this->ui_.oauthTokenInput, &QLineEdit::textChanged,
[=]() { this->refreshButtons(); });
/// Upper button row
this->ui_.buttonUpperRow.addUserButton.setText("Add user");
this->ui_.buttonUpperRow.clearFieldsButton.setText("Clear fields");
this->ui_.buttonUpperRow.layout.addWidget(&this->ui_.buttonUpperRow.addUserButton);
this->ui_.buttonUpperRow.layout.addWidget(&this->ui_.buttonUpperRow.clearFieldsButton);
this->ui_.buttonUpperRow.layout.addWidget(
&this->ui_.buttonUpperRow.addUserButton);
this->ui_.buttonUpperRow.layout.addWidget(
&this->ui_.buttonUpperRow.clearFieldsButton);
connect(&this->ui_.buttonUpperRow.clearFieldsButton, &QPushButton::clicked, [=]() {
this->ui_.userIDInput.clear();
this->ui_.usernameInput.clear();
this->ui_.clientIDInput.clear();
this->ui_.oauthTokenInput.clear();
});
connect(&this->ui_.buttonUpperRow.clearFieldsButton, &QPushButton::clicked,
[=]() {
this->ui_.userIDInput.clear();
this->ui_.usernameInput.clear();
this->ui_.clientIDInput.clear();
this->ui_.oauthTokenInput.clear();
});
connect(&this->ui_.buttonUpperRow.addUserButton, &QPushButton::clicked, [=]() {
std::string userID = this->ui_.userIDInput.text().toStdString();
std::string username = this->ui_.usernameInput.text().toStdString();
std::string clientID = this->ui_.clientIDInput.text().toStdString();
std::string oauthToken = this->ui_.oauthTokenInput.text().toStdString();
connect(
&this->ui_.buttonUpperRow.addUserButton, &QPushButton::clicked, [=]() {
std::string userID = this->ui_.userIDInput.text().toStdString();
std::string username = this->ui_.usernameInput.text().toStdString();
std::string clientID = this->ui_.clientIDInput.text().toStdString();
std::string oauthToken =
this->ui_.oauthTokenInput.text().toStdString();
LogInWithCredentials(userID, username, clientID, oauthToken);
});
LogInWithCredentials(userID, username, clientID, oauthToken);
});
/// Lower button row
this->ui_.buttonLowerRow.fillInUserIDButton.setText("Get user ID from username");
this->ui_.buttonLowerRow.fillInUserIDButton.setText(
"Get user ID from username");
this->ui_.buttonLowerRow.layout.addWidget(&this->ui_.buttonLowerRow.fillInUserIDButton);
this->ui_.buttonLowerRow.layout.addWidget(
&this->ui_.buttonLowerRow.fillInUserIDButton);
connect(&this->ui_.buttonLowerRow.fillInUserIDButton, &QPushButton::clicked, [=]() {
const auto onIdFetched = [=](const QString &userID) {
this->ui_.userIDInput.setText(userID); //
};
PartialTwitchUser::byName(this->ui_.usernameInput.text()).getId(onIdFetched, this);
});
connect(&this->ui_.buttonLowerRow.fillInUserIDButton, &QPushButton::clicked,
[=]() {
const auto onIdFetched = [=](const QString &userID) {
this->ui_.userIDInput.setText(userID); //
};
PartialTwitchUser::byName(this->ui_.usernameInput.text())
.getId(onIdFetched, this);
});
}
void AdvancedLoginWidget::refreshButtons()
@@ -189,8 +208,10 @@ void AdvancedLoginWidget::refreshButtons()
this->ui_.buttonLowerRow.fillInUserIDButton.setEnabled(
!this->ui_.usernameInput.text().isEmpty());
if (this->ui_.userIDInput.text().isEmpty() || this->ui_.usernameInput.text().isEmpty() ||
this->ui_.clientIDInput.text().isEmpty() || this->ui_.oauthTokenInput.text().isEmpty()) {
if (this->ui_.userIDInput.text().isEmpty() ||
this->ui_.usernameInput.text().isEmpty() ||
this->ui_.clientIDInput.text().isEmpty() ||
this->ui_.oauthTokenInput.text().isEmpty()) {
this->ui_.buttonUpperRow.addUserButton.setEnabled(false);
} else {
this->ui_.buttonUpperRow.addUserButton.setEnabled(true);
@@ -214,9 +235,10 @@ LoginWidget::LoginWidget()
this->ui_.buttonBox.setStandardButtons(QDialogButtonBox::Close);
QObject::connect(&this->ui_.buttonBox, &QDialogButtonBox::rejected, [this]() {
this->close(); //
});
QObject::connect(&this->ui_.buttonBox, &QDialogButtonBox::rejected,
[this]() {
this->close(); //
});
this->ui_.mainLayout.addWidget(&this->ui_.buttonBox);
}
+28 -16
View File
@@ -35,7 +35,8 @@ void LogsPopup::setInfo(ChannelPtr channel, QString userName)
this->channel_ = channel;
this->userName_ = userName;
this->getRoomID();
this->setWindowTitle(this->userName_ + "'s logs in #" + this->channel_->getName());
this->setWindowTitle(this->userName_ + "'s logs in #" +
this->channel_->getName());
this->getLogviewerLogs();
}
@@ -49,7 +50,8 @@ void LogsPopup::setMessages(std::vector<MessagePtr> &messages)
void LogsPopup::getRoomID()
{
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(this->channel_.get());
TwitchChannel *twitchChannel =
dynamic_cast<TwitchChannel *>(this->channel_.get());
if (twitchChannel == nullptr) {
return;
}
@@ -78,7 +80,8 @@ void LogsPopup::getRoomID()
void LogsPopup::getLogviewerLogs()
{
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(this->channel_.get());
TwitchChannel *twitchChannel =
dynamic_cast<TwitchChannel *>(this->channel_.get());
if (twitchChannel == nullptr) {
return;
}
@@ -108,12 +111,15 @@ void LogsPopup::getLogviewerLogs()
// Hacky way to fix the timestamp
message.insert(1, "historical=1;");
message.insert(1, QString("tmi-sent-ts=%10000;").arg(messageObject["time"].toInt()));
message.insert(1, QString("tmi-sent-ts=%10000;")
.arg(messageObject["time"].toInt()));
message.insert(1, QString("room-id=%1;").arg(this->roomID_));
MessageParseArgs args;
auto ircMessage = Communi::IrcMessage::fromData(message.toUtf8(), nullptr);
auto privMsg = static_cast<Communi::IrcPrivateMessage *>(ircMessage);
auto ircMessage =
Communi::IrcMessage::fromData(message.toUtf8(), nullptr);
auto privMsg =
static_cast<Communi::IrcPrivateMessage *>(ircMessage);
TwitchMessageBuilder builder(this->channel_.get(), privMsg, args);
messages.push_back(builder.build());
};
@@ -127,22 +133,25 @@ void LogsPopup::getLogviewerLogs()
void LogsPopup::getOverrustleLogs()
{
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(this->channel_.get());
TwitchChannel *twitchChannel =
dynamic_cast<TwitchChannel *>(this->channel_.get());
if (twitchChannel == nullptr) {
return;
}
QString channelName = twitchChannel->getName();
QString url = QString("https://overrustlelogs.net/api/v1/stalk/%1/%2.json?limit=500")
.arg(channelName, this->userName_);
QString url =
QString("https://overrustlelogs.net/api/v1/stalk/%1/%2.json?limit=500")
.arg(channelName, this->userName_);
NetworkRequest req(url);
req.setCaller(QThread::currentThread());
req.onError([this, channelName](int errorCode) {
this->close();
QMessageBox *box = new QMessageBox(QMessageBox::Information, "Error getting logs",
"No logs could be found for channel " + channelName);
QMessageBox *box = new QMessageBox(
QMessageBox::Information, "Error getting logs",
"No logs could be found for channel " + channelName);
box->setAttribute(Qt::WA_DeleteOnClose);
box->show();
box->raise();
@@ -157,15 +166,18 @@ void LogsPopup::getOverrustleLogs()
QJsonArray dataMessages = data.value("lines").toArray();
for (auto i : dataMessages) {
QJsonObject singleMessage = i.toObject();
QTime timeStamp =
QDateTime::fromSecsSinceEpoch(singleMessage.value("timestamp").toInt()).time();
QTime timeStamp = QDateTime::fromSecsSinceEpoch(
singleMessage.value("timestamp").toInt())
.time();
MessagePtr message(new Message);
message->addElement(new TimestampElement(timeStamp));
message->addElement(new TextElement(this->userName_, MessageElement::Username,
message->addElement(new TextElement(this->userName_,
MessageElement::Username,
MessageColor::System));
message->addElement(new TextElement(singleMessage.value("text").toString(),
MessageElement::Text, MessageColor::Text));
message->addElement(
new TextElement(singleMessage.value("text").toString(),
MessageElement::Text, MessageColor::Text));
messages.push_back(message);
}
}
+2 -1
View File
@@ -33,7 +33,8 @@ void NotificationPopup::updatePosition()
switch (location) {
case BottomRight: {
this->move(rect.right() - this->width(), rect.bottom() - this->height());
this->move(rect.right() - this->width(),
rect.bottom() - this->height());
} break;
}
}
+2 -1
View File
@@ -15,7 +15,8 @@ QualityPopup::QualityPopup(const QString &_channelName, QStringList options)
QObject::connect(&this->ui_.cancelButton, &QPushButton::clicked, this,
&QualityPopup::cancelButtonClicked);
this->ui_.buttonBox.addButton(&this->ui_.okButton, QDialogButtonBox::ButtonRole::AcceptRole);
this->ui_.buttonBox.addButton(&this->ui_.okButton,
QDialogButtonBox::ButtonRole::AcceptRole);
this->ui_.buttonBox.addButton(&this->ui_.cancelButton,
QDialogButtonBox::ButtonRole::RejectRole);
+61 -36
View File
@@ -33,17 +33,20 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent)
auto vbox = obj.setLayoutType<QVBoxLayout>();
// channel_btn
auto channel_btn = vbox.emplace<QRadioButton>("Channel").assign(&this->ui_.twitch.channel);
auto channel_lbl = vbox.emplace<QLabel>("Join a twitch channel by its name.").hidden();
auto channel_btn = vbox.emplace<QRadioButton>("Channel").assign(
&this->ui_.twitch.channel);
auto channel_lbl =
vbox.emplace<QLabel>("Join a twitch channel by its name.").hidden();
channel_lbl->setWordWrap(true);
auto channel_edit =
vbox.emplace<QLineEdit>().hidden().assign(&this->ui_.twitch.channelName);
auto channel_edit = vbox.emplace<QLineEdit>().hidden().assign(
&this->ui_.twitch.channelName);
QObject::connect(channel_btn.getElement(), &QRadioButton::toggled,
[=](bool enabled) mutable {
if (enabled) {
channel_edit->setFocus();
channel_edit->setSelection(0, channel_edit->text().length());
channel_edit->setSelection(
0, channel_edit->text().length());
}
channel_edit->setVisible(enabled);
@@ -54,50 +57,60 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent)
channel_edit->installEventFilter(&this->tabFilter_);
// whispers_btn
auto whispers_btn =
vbox.emplace<QRadioButton>("Whispers").assign(&this->ui_.twitch.whispers);
auto whispers_btn = vbox.emplace<QRadioButton>("Whispers")
.assign(&this->ui_.twitch.whispers);
auto whispers_lbl =
vbox.emplace<QLabel>("Shows the whispers that you receive while chatterino is running.")
vbox.emplace<QLabel>("Shows the whispers that you receive while "
"chatterino is running.")
.hidden();
whispers_lbl->setWordWrap(true);
whispers_btn->installEventFilter(&this->tabFilter_);
QObject::connect(whispers_btn.getElement(), &QRadioButton::toggled,
[=](bool enabled) mutable { whispers_lbl->setVisible(enabled); });
QObject::connect(
whispers_btn.getElement(), &QRadioButton::toggled,
[=](bool enabled) mutable { whispers_lbl->setVisible(enabled); });
// mentions_btn
auto mentions_btn =
vbox.emplace<QRadioButton>("Mentions").assign(&this->ui_.twitch.mentions);
auto mentions_btn = vbox.emplace<QRadioButton>("Mentions")
.assign(&this->ui_.twitch.mentions);
auto mentions_lbl =
vbox.emplace<QLabel>("Shows all the messages that highlight you from any channel.")
vbox.emplace<QLabel>("Shows all the messages that highlight you "
"from any channel.")
.hidden();
mentions_lbl->setWordWrap(true);
mentions_btn->installEventFilter(&this->tabFilter_);
QObject::connect(mentions_btn.getElement(), &QRadioButton::toggled,
[=](bool enabled) mutable { mentions_lbl->setVisible(enabled); });
QObject::connect(
mentions_btn.getElement(), &QRadioButton::toggled,
[=](bool enabled) mutable { mentions_lbl->setVisible(enabled); });
// watching_btn
auto watching_btn =
vbox.emplace<QRadioButton>("Watching").assign(&this->ui_.twitch.watching);
auto watching_btn = vbox.emplace<QRadioButton>("Watching")
.assign(&this->ui_.twitch.watching);
auto watching_lbl =
vbox.emplace<QLabel>("Requires the chatterino browser extension.").hidden();
vbox.emplace<QLabel>("Requires the chatterino browser extension.")
.hidden();
watching_lbl->setWordWrap(true);
watching_btn->installEventFilter(&this->tabFilter_);
QObject::connect(watching_btn.getElement(), &QRadioButton::toggled,
[=](bool enabled) mutable { watching_lbl->setVisible(enabled); });
QObject::connect(
watching_btn.getElement(), &QRadioButton::toggled,
[=](bool enabled) mutable { watching_lbl->setVisible(enabled); });
vbox->addStretch(1);
// tabbing order
QWidget::setTabOrder(watching_btn.getElement(), channel_btn.getElement());
QWidget::setTabOrder(channel_btn.getElement(), whispers_btn.getElement());
QWidget::setTabOrder(whispers_btn.getElement(), mentions_btn.getElement());
QWidget::setTabOrder(mentions_btn.getElement(), watching_btn.getElement());
QWidget::setTabOrder(watching_btn.getElement(),
channel_btn.getElement());
QWidget::setTabOrder(channel_btn.getElement(),
whispers_btn.getElement());
QWidget::setTabOrder(whispers_btn.getElement(),
mentions_btn.getElement());
QWidget::setTabOrder(mentions_btn.getElement(),
watching_btn.getElement());
// tab
NotebookTab *tab = notebook->addPage(obj.getElement());
@@ -117,12 +130,15 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent)
layout->setStretchFactor(notebook.getElement(), 1);
auto buttons = layout.emplace<QHBoxLayout>().emplace<QDialogButtonBox>(this);
auto buttons =
layout.emplace<QHBoxLayout>().emplace<QDialogButtonBox>(this);
{
auto *button_ok = buttons->addButton(QDialogButtonBox::Ok);
QObject::connect(button_ok, &QPushButton::clicked, [=](bool) { this->ok(); });
QObject::connect(button_ok, &QPushButton::clicked,
[=](bool) { this->ok(); });
auto *button_cancel = buttons->addButton(QDialogButtonBox::Cancel);
QObject::connect(button_cancel, &QAbstractButton::clicked, [=](bool) { this->close(); });
QObject::connect(button_cancel, &QAbstractButton::clicked,
[=](bool) { this->close(); });
}
this->setScaleIndependantSize(300, 210);
@@ -133,7 +149,8 @@ SelectChannelDialog::SelectChannelDialog(QWidget *parent)
auto *shortcut_ok = new QShortcut(QKeySequence("Return"), this);
QObject::connect(shortcut_ok, &QShortcut::activated, [=] { this->ok(); });
auto *shortcut_cancel = new QShortcut(QKeySequence("Esc"), this);
QObject::connect(shortcut_cancel, &QShortcut::activated, [=] { this->close(); });
QObject::connect(shortcut_cancel, &QShortcut::activated,
[=] { this->close(); });
}
void SelectChannelDialog::ok()
@@ -188,7 +205,8 @@ IndirectChannel SelectChannelDialog::getSelectedChannel() const
switch (this->ui_.notebook->getSelectedIndex()) {
case TAB_TWITCH: {
if (this->ui_.twitch.channel->isChecked()) {
return app->twitch.server->getOrAddChannel(this->ui_.twitch.channelName->text());
return app->twitch.server->getOrAddChannel(
this->ui_.twitch.channelName->text());
} else if (this->ui_.twitch.watching->isChecked()) {
return app->twitch.server->watchingChannel;
} else if (this->ui_.twitch.mentions->isChecked()) {
@@ -207,7 +225,8 @@ bool SelectChannelDialog::hasSeletedChannel() const
return this->hasSelectedChannel_;
}
bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched, QEvent *event)
bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched,
QEvent *event)
{
auto *widget = (QWidget *)watched;
@@ -225,7 +244,8 @@ bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched, QEvent *eve
return false;
} else if (event->type() == QEvent::KeyPress) {
QKeyEvent *event_key = static_cast<QKeyEvent *>(event);
if ((event_key->key() == Qt::Key_Tab || event_key->key() == Qt::Key_Down) &&
if ((event_key->key() == Qt::Key_Tab ||
event_key->key() == Qt::Key_Down) &&
event_key->modifiers() == Qt::NoModifier) {
if (widget == this->dialog->ui_.twitch.channelName) {
this->dialog->ui_.twitch.whispers->setFocus();
@@ -234,9 +254,11 @@ bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched, QEvent *eve
widget->nextInFocusChain()->setFocus();
}
return true;
} else if (((event_key->key() == Qt::Key_Tab || event_key->key() == Qt::Key_Backtab) &&
} else if (((event_key->key() == Qt::Key_Tab ||
event_key->key() == Qt::Key_Backtab) &&
event_key->modifiers() == Qt::ShiftModifier) ||
((event_key->key() == Qt::Key_Up) && event_key->modifiers() == Qt::NoModifier)) {
((event_key->key() == Qt::Key_Up) &&
event_key->modifiers() == Qt::NoModifier)) {
if (widget == this->dialog->ui_.twitch.channelName) {
this->dialog->ui_.twitch.watching->setFocus();
return true;
@@ -253,7 +275,8 @@ bool SelectChannelDialog::EventFilter::eventFilter(QObject *watched, QEvent *eve
return true;
} else if (event->type() == QEvent::KeyRelease) {
QKeyEvent *event_key = static_cast<QKeyEvent *>(event);
if ((event_key->key() == Qt::Key_Backtab || event_key->key() == Qt::Key_Down) &&
if ((event_key->key() == Qt::Key_Backtab ||
event_key->key() == Qt::Key_Down) &&
event_key->modifiers() == Qt::NoModifier) {
return true;
}
@@ -272,9 +295,11 @@ void SelectChannelDialog::themeChangedEvent()
BaseWindow::themeChangedEvent();
if (this->theme->isLightTheme()) {
this->setStyleSheet("QRadioButton { color: #000 } QLabel { color: #000 }");
this->setStyleSheet(
"QRadioButton { color: #000 } QLabel { color: #000 }");
} else {
this->setStyleSheet("QRadioButton { color: #fff } QLabel { color: #fff }");
this->setStyleSheet(
"QRadioButton { color: #fff } QLabel { color: #fff }");
}
}
+9 -4
View File
@@ -49,12 +49,16 @@ void SettingsDialog::initUi()
// right side layout
auto right = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
{
right.emplace<QStackedLayout>().assign(&this->ui_.pageStack).withoutMargin();
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_.okButton =
buttons->addButton("Ok", QDialogButtonBox::YesRole);
this->ui_.cancelButton =
buttons->addButton("Cancel", QDialogButtonBox::NoRole);
}
}
@@ -62,7 +66,8 @@ void SettingsDialog::initUi()
this->ui_.tabContainerContainer->setObjectName("tabWidget");
this->ui_.pageStack->setObjectName("pages");
QObject::connect(this->ui_.okButton, &QPushButton::clicked, this, &SettingsDialog::onOkClicked);
QObject::connect(this->ui_.okButton, &QPushButton::clicked, this,
&SettingsDialog::onOkClicked);
QObject::connect(this->ui_.cancelButton, &QPushButton::clicked, this,
&SettingsDialog::onCancelClicked);
}
+2 -1
View File
@@ -25,7 +25,8 @@ public:
Accounts,
};
static void showDialog(PreferredTab preferredTab = PreferredTab::NoPreference);
static void showDialog(
PreferredTab preferredTab = PreferredTab::NoPreference);
protected:
virtual void scaleChangedEvent(float newDpi) override;
+7 -4
View File
@@ -15,13 +15,16 @@ TextInputDialog::TextInputDialog(QWidget *parent)
this->buttonBox_.addWidget(&okButton_);
this->buttonBox_.addWidget(&cancelButton_);
QObject::connect(&this->okButton_, SIGNAL(clicked()), this, SLOT(okButtonClicked()));
QObject::connect(&this->cancelButton_, SIGNAL(clicked()), this, SLOT(cancelButtonClicked()));
QObject::connect(&this->okButton_, SIGNAL(clicked()), this,
SLOT(okButtonClicked()));
QObject::connect(&this->cancelButton_, SIGNAL(clicked()), this,
SLOT(cancelButtonClicked()));
this->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
this->setWindowFlags((this->windowFlags() & ~(Qt::WindowContextHelpButtonHint)) | Qt::Dialog |
Qt::MSWindowsFixedSizeDialogHint);
this->setWindowFlags(
(this->windowFlags() & ~(Qt::WindowContextHelpButtonHint)) |
Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
}
QString TextInputDialog::getText() const
+17 -10
View File
@@ -11,27 +11,32 @@
namespace chatterino {
UpdateDialog::UpdateDialog()
: BaseWindow(nullptr, BaseWindow::Flags(BaseWindow::Frameless | BaseWindow::TopMost |
BaseWindow::EnableCustomFrame))
: BaseWindow(nullptr,
BaseWindow::Flags(BaseWindow::Frameless | BaseWindow::TopMost |
BaseWindow::EnableCustomFrame))
{
auto layout = LayoutCreator<UpdateDialog>(this).setLayoutType<QVBoxLayout>();
auto layout =
LayoutCreator<UpdateDialog>(this).setLayoutType<QVBoxLayout>();
layout.emplace<Label>("You shouldn't be seeing this dialog.").assign(&this->ui_.label);
layout.emplace<Label>("You shouldn't be seeing this dialog.")
.assign(&this->ui_.label);
auto buttons = layout.emplace<QDialogButtonBox>();
auto install = buttons->addButton("Install", QDialogButtonBox::AcceptRole);
this->ui_.installButton = install;
auto dismiss = buttons->addButton("Dismiss", QDialogButtonBox::RejectRole);
QObject::connect(install, &QPushButton::clicked, this, [this] { this->close(); });
QObject::connect(install, &QPushButton::clicked, this,
[this] { this->close(); });
QObject::connect(dismiss, &QPushButton::clicked, this, [this] {
this->buttonClicked.invoke(Dismiss);
this->close();
});
this->updateStatusChanged(Updates::getInstance().getStatus());
this->connections_.managedConnect(Updates::getInstance().statusUpdated,
[this](auto status) { this->updateStatusChanged(status); });
this->connections_.managedConnect(
Updates::getInstance().statusUpdated,
[this](auto status) { this->updateStatusChanged(status); });
}
void UpdateDialog::updateStatusChanged(Updates::Status status)
@@ -41,7 +46,8 @@ void UpdateDialog::updateStatusChanged(Updates::Status status)
switch (status) {
case Updates::UpdateAvailable: {
this->ui_.label->setText(
QString("An update (%1) is available.\n\nDo you want to download and install it?")
QString("An update (%1) is available.\n\nDo you want to "
"download and install it?")
.arg(Updates::getInstance().getOnlineVersion()));
} break;
@@ -50,8 +56,9 @@ void UpdateDialog::updateStatusChanged(Updates::Status status)
} break;
case Updates::Downloading: {
this->ui_.label->setText("Downloading updates.\n\nChatterino will restart "
"automatically when the download is done.");
this->ui_.label->setText(
"Downloading updates.\n\nChatterino will restart "
"automatically when the download is done.");
} break;
case Updates::DownloadFailed: {
+137 -99
View File
@@ -27,7 +27,8 @@
namespace chatterino {
UserInfoPopup::UserInfoPopup()
: BaseWindow(nullptr, BaseWindow::Flags(BaseWindow::Frameless | BaseWindow::FramelessDraggable))
: BaseWindow(nullptr, BaseWindow::Flags(BaseWindow::Frameless |
BaseWindow::FramelessDraggable))
, hack_(new bool)
{
this->setStayInScreenRect(true);
@@ -38,17 +39,21 @@ UserInfoPopup::UserInfoPopup()
auto app = getApp();
auto layout = LayoutCreator<UserInfoPopup>(this).setLayoutType<QVBoxLayout>();
auto layout =
LayoutCreator<UserInfoPopup>(this).setLayoutType<QVBoxLayout>();
// first line
auto head = layout.emplace<QHBoxLayout>().withoutMargin();
{
// avatar
auto avatar = head.emplace<RippleEffectButton>(nullptr).assign(&this->ui_.avatarButton);
auto avatar = head.emplace<RippleEffectButton>(nullptr).assign(
&this->ui_.avatarButton);
avatar->setScaleIndependantSize(100, 100);
QObject::connect(avatar.getElement(), &RippleEffectButton::clicked, [this] {
QDesktopServices::openUrl(QUrl("https://twitch.tv/" + this->userName_));
});
QObject::connect(avatar.getElement(), &RippleEffectButton::clicked,
[this] {
QDesktopServices::openUrl(
QUrl("https://twitch.tv/" + this->userName_));
});
// items on the right
auto vbox = head.emplace<QVBoxLayout>();
@@ -59,8 +64,10 @@ UserInfoPopup::UserInfoPopup()
font.setBold(true);
name->setFont(font);
vbox.emplace<Label>(TEXT_VIEWS).assign(&this->ui_.viewCountLabel);
vbox.emplace<Label>(TEXT_FOLLOWERS).assign(&this->ui_.followerCountLabel);
vbox.emplace<Label>(TEXT_CREATED).assign(&this->ui_.createdDateLabel);
vbox.emplace<Label>(TEXT_FOLLOWERS)
.assign(&this->ui_.followerCountLabel);
vbox.emplace<Label>(TEXT_CREATED)
.assign(&this->ui_.createdDateLabel);
}
}
@@ -73,7 +80,8 @@ UserInfoPopup::UserInfoPopup()
user.emplace<QCheckBox>("Follow").assign(&this->ui_.follow);
user.emplace<QCheckBox>("Ignore").assign(&this->ui_.ignore);
user.emplace<QCheckBox>("Ignore highlights").assign(&this->ui_.ignoreHighlights);
user.emplace<QCheckBox>("Ignore highlights")
.assign(&this->ui_.ignoreHighlights);
auto viewLogs = user.emplace<RippleEffectLabel2>(this);
viewLogs->getLabel().setText("Logs");
@@ -86,32 +94,39 @@ UserInfoPopup::UserInfoPopup()
user->addStretch(1);
QObject::connect(viewLogs.getElement(), &RippleEffectButton::clicked, [this] {
auto logs = new LogsPopup();
logs->setInfo(this->channel_, this->userName_);
logs->setAttribute(Qt::WA_DeleteOnClose);
logs->show();
});
QObject::connect(viewLogs.getElement(), &RippleEffectButton::clicked,
[this] {
auto logs = new LogsPopup();
logs->setInfo(this->channel_, this->userName_);
logs->setAttribute(Qt::WA_DeleteOnClose);
logs->show();
});
QObject::connect(mod.getElement(), &RippleEffectButton::clicked,
[this] { this->channel_->sendMessage("/mod " + this->userName_); });
QObject::connect(unmod.getElement(), &RippleEffectButton::clicked,
[this] { this->channel_->sendMessage("/unmod " + this->userName_); });
QObject::connect(
mod.getElement(), &RippleEffectButton::clicked,
[this] { this->channel_->sendMessage("/mod " + this->userName_); });
QObject::connect(
unmod.getElement(), &RippleEffectButton::clicked, [this] {
this->channel_->sendMessage("/unmod " + this->userName_);
});
// userstate
this->userStateChanged_.connect([this, mod, unmod]() mutable {
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(this->channel_.get());
TwitchChannel *twitchChannel =
dynamic_cast<TwitchChannel *>(this->channel_.get());
if (twitchChannel) {
qDebug() << this->userName_;
bool isMyself =
QString::compare(getApp()->accounts->twitch.getCurrent()->getUserName(),
this->userName_, Qt::CaseInsensitive) == 0;
QString::compare(
getApp()->accounts->twitch.getCurrent()->getUserName(),
this->userName_, Qt::CaseInsensitive) == 0;
mod->setVisible(twitchChannel->isBroadcaster() && !isMyself);
unmod->setVisible((twitchChannel->isBroadcaster() && !isMyself) ||
(twitchChannel->isMod() && isMyself));
unmod->setVisible(
(twitchChannel->isBroadcaster() && !isMyself) ||
(twitchChannel->isMod() && isMyself));
}
});
}
@@ -124,7 +139,8 @@ UserInfoPopup::UserInfoPopup()
auto timeout = moderation.emplace<TimeoutWidget>();
this->userStateChanged_.connect([this, lineMod, timeout]() mutable {
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(this->channel_.get());
TwitchChannel *twitchChannel =
dynamic_cast<TwitchChannel *>(this->channel_.get());
if (twitchChannel) {
lineMod->setVisible(twitchChannel->hasModRights());
@@ -145,12 +161,14 @@ UserInfoPopup::UserInfoPopup()
} break;
case TimeoutWidget::Unban: {
if (this->channel_) {
this->channel_->sendMessage("/unban " + this->userName_);
this->channel_->sendMessage("/unban " +
this->userName_);
}
} break;
case TimeoutWidget::Timeout: {
if (this->channel_) {
this->channel_->sendMessage("/timeout " + this->userName_ + " " +
this->channel_->sendMessage("/timeout " +
this->userName_ + " " +
QString::number(arg));
}
} break;
@@ -175,29 +193,33 @@ void UserInfoPopup::installEvents()
std::weak_ptr<bool> hack = this->hack_;
// follow
QObject::connect(this->ui_.follow, &QCheckBox::stateChanged, [this](int) mutable {
auto currentUser = getApp()->accounts->twitch.getCurrent();
QObject::connect(
this->ui_.follow, &QCheckBox::stateChanged, [this](int) mutable {
auto currentUser = getApp()->accounts->twitch.getCurrent();
QUrl requestUrl("https://api.twitch.tv/kraken/users/" + currentUser->getUserId() +
"/follows/channels/" + this->userId_);
QUrl requestUrl("https://api.twitch.tv/kraken/users/" +
currentUser->getUserId() + "/follows/channels/" +
this->userId_);
const auto reenableFollowCheckbox = [this] {
this->ui_.follow->setEnabled(true); //
};
const auto reenableFollowCheckbox = [this] {
this->ui_.follow->setEnabled(true); //
};
this->ui_.follow->setEnabled(false);
if (this->ui_.follow->isChecked()) {
currentUser->followUser(this->userId_, reenableFollowCheckbox);
} else {
currentUser->unfollowUser(this->userId_, reenableFollowCheckbox);
}
});
this->ui_.follow->setEnabled(false);
if (this->ui_.follow->isChecked()) {
currentUser->followUser(this->userId_, reenableFollowCheckbox);
} else {
currentUser->unfollowUser(this->userId_,
reenableFollowCheckbox);
}
});
std::shared_ptr<bool> ignoreNext = std::make_shared<bool>(false);
// ignore
QObject::connect(
this->ui_.ignore, &QCheckBox::stateChanged, [this, ignoreNext, hack](int) mutable {
this->ui_.ignore, &QCheckBox::stateChanged,
[this, ignoreNext, hack](int) mutable {
if (*ignoreNext) {
*ignoreNext = false;
return;
@@ -207,54 +229,60 @@ void UserInfoPopup::installEvents()
auto currentUser = getApp()->accounts->twitch.getCurrent();
if (this->ui_.ignore->isChecked()) {
currentUser->ignoreByID(this->userId_, this->userName_,
[=](auto result, const auto &message) mutable {
if (hack.lock()) {
if (result == IgnoreResult_Failed) {
*ignoreNext = true;
this->ui_.ignore->setChecked(false);
}
this->ui_.ignore->setEnabled(true);
}
});
currentUser->ignoreByID(
this->userId_, this->userName_,
[=](auto result, const auto &message) mutable {
if (hack.lock()) {
if (result == IgnoreResult_Failed) {
*ignoreNext = true;
this->ui_.ignore->setChecked(false);
}
this->ui_.ignore->setEnabled(true);
}
});
} else {
currentUser->unignoreByID(this->userId_, this->userName_,
[=](auto result, const auto &message) mutable {
if (hack.lock()) {
if (result == UnignoreResult_Failed) {
*ignoreNext = true;
this->ui_.ignore->setChecked(true);
}
this->ui_.ignore->setEnabled(true);
}
});
currentUser->unignoreByID(
this->userId_, this->userName_,
[=](auto result, const auto &message) mutable {
if (hack.lock()) {
if (result == UnignoreResult_Failed) {
*ignoreNext = true;
this->ui_.ignore->setChecked(true);
}
this->ui_.ignore->setEnabled(true);
}
});
}
});
// ignore highlights
QObject::connect(this->ui_.ignoreHighlights, &QCheckBox::clicked, [this](bool checked) mutable {
this->ui_.ignoreHighlights->setEnabled(false);
QObject::connect(
this->ui_.ignoreHighlights, &QCheckBox::clicked,
[this](bool checked) mutable {
this->ui_.ignoreHighlights->setEnabled(false);
if (checked) {
getApp()->highlights->blacklistedUsers.insertItem(
HighlightBlacklistUser{this->userName_, false});
this->ui_.ignoreHighlights->setEnabled(true);
} else {
const auto &vector = getApp()->highlights->blacklistedUsers.getVector();
if (checked) {
getApp()->highlights->blacklistedUsers.insertItem(
HighlightBlacklistUser{this->userName_, false});
this->ui_.ignoreHighlights->setEnabled(true);
} else {
const auto &vector =
getApp()->highlights->blacklistedUsers.getVector();
for (int i = 0; i < vector.size(); i++) {
if (this->userName_ == vector[i].getPattern()) {
getApp()->highlights->blacklistedUsers.removeItem(i);
i--;
for (int i = 0; i < vector.size(); i++) {
if (this->userName_ == vector[i].getPattern()) {
getApp()->highlights->blacklistedUsers.removeItem(i);
i--;
}
}
if (getApp()->highlights->blacklistContains(this->userName_)) {
this->ui_.ignoreHighlights->setToolTip(
"Name matched by regex");
} else {
this->ui_.ignoreHighlights->setEnabled(true);
}
}
if (getApp()->highlights->blacklistContains(this->userName_)) {
this->ui_.ignoreHighlights->setToolTip("Name matched by regex");
} else {
this->ui_.ignoreHighlights->setEnabled(true);
}
}
});
});
}
void UserInfoPopup::setData(const QString &name, const ChannelPtr &channel)
@@ -285,12 +313,14 @@ void UserInfoPopup::updateUserData()
request.onSuccess([this](auto result) -> Outcome {
auto obj = result.parseJson();
this->ui_.followerCountLabel->setText(TEXT_FOLLOWERS +
QString::number(obj.value("followers").toInt()));
this->ui_.viewCountLabel->setText(TEXT_VIEWS +
QString::number(obj.value("views").toInt()));
this->ui_.followerCountLabel->setText(
TEXT_FOLLOWERS +
QString::number(obj.value("followers").toInt()));
this->ui_.viewCountLabel->setText(
TEXT_VIEWS + QString::number(obj.value("views").toInt()));
this->ui_.createdDateLabel->setText(
TEXT_CREATED + obj.value("created_at").toString().section("T", 0, 0));
TEXT_CREATED +
obj.value("created_at").toString().section("T", 0, 0));
this->loadAvatar(QUrl(obj.value("logo").toString()));
@@ -304,7 +334,8 @@ void UserInfoPopup::updateUserData()
if (hack.lock()) {
if (result != FollowResult_Failed) {
this->ui_.follow->setEnabled(true);
this->ui_.follow->setChecked(result == FollowResult_Following);
this->ui_.follow->setChecked(result ==
FollowResult_Following);
}
}
});
@@ -327,7 +358,8 @@ void UserInfoPopup::updateUserData()
break;
}
}
if (getApp()->highlights->blacklistContains(this->userName_) && !isIgnoringHighlights) {
if (getApp()->highlights->blacklistContains(this->userName_) &&
!isIgnoringHighlights) {
this->ui_.ignoreHighlights->setToolTip("Name matched by regex");
} else {
this->ui_.ignoreHighlights->setEnabled(true);
@@ -370,7 +402,9 @@ void UserInfoPopup::loadAvatar(const QUrl &url)
UserInfoPopup::TimeoutWidget::TimeoutWidget()
: BaseWidget(nullptr)
{
auto layout = LayoutCreator<TimeoutWidget>(this).setLayoutType<QHBoxLayout>().withoutMargin();
auto layout = LayoutCreator<TimeoutWidget>(this)
.setLayoutType<QHBoxLayout>()
.withoutMargin();
QColor color1(255, 255, 255, 80);
QColor color2(255, 255, 255, 0);
@@ -381,7 +415,8 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
layout->setSpacing(16);
auto addButton = [&](Action action, const QString &text, const QPixmap &pixmap) {
auto addButton = [&](Action action, const QString &text,
const QPixmap &pixmap) {
auto vbox = layout.emplace<QVBoxLayout>().withoutMargin();
{
auto title = vbox.emplace<QHBoxLayout>().withoutMargin();
@@ -399,9 +434,11 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
button->setScaleIndependantSize(buttonHeight, buttonHeight);
button->setBorderColor(QColor(255, 255, 255, 127));
QObject::connect(button.getElement(), &RippleEffectButton::clicked, [this, action] {
this->buttonClicked.invoke(std::make_pair(action, -1));
});
QObject::connect(
button.getElement(), &RippleEffectButton::clicked,
[this, action] {
this->buttonClicked.invoke(std::make_pair(action, -1));
});
}
}
};
@@ -431,11 +468,11 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
}
a->setBorderColor(color1);
QObject::connect(
a.getElement(), &RippleEffectLabel2::clicked,
[this, timeout = std::get<1>(item)] {
this->buttonClicked.invoke(std::make_pair(Action::Timeout, timeout));
});
QObject::connect(a.getElement(), &RippleEffectLabel2::clicked,
[this, timeout = std::get<1>(item)] {
this->buttonClicked.invoke(std::make_pair(
Action::Timeout, timeout));
});
}
}
};
@@ -470,7 +507,8 @@ void UserInfoPopup::TimeoutWidget::paintEvent(QPaintEvent *)
// painter.setPen(QColor(255, 255, 255, 63));
// painter.drawLine(0, this->height() / 2, this->width(), this->height() / 2);
// painter.drawLine(0, this->height() / 2, this->width(), this->height()
// / 2);
}
} // namespace chatterino
+158 -104
View File
@@ -33,7 +33,8 @@
namespace chatterino {
namespace {
void addEmoteContextMenuItems(const Emote &emote, MessageElement::Flags creatorFlags, QMenu &menu)
void addEmoteContextMenuItems(const Emote &emote,
MessageElement::Flags creatorFlags, QMenu &menu)
{
auto openAction = menu.addAction("Open");
auto openMenu = new QMenu;
@@ -45,18 +46,21 @@ void addEmoteContextMenuItems(const Emote &emote, MessageElement::Flags creatorF
// see if the QMenu actually gets destroyed
QObject::connect(openMenu, &QMenu::destroyed, [] {
QMessageBox(QMessageBox::Information, "xD", "the menu got deleted").exec();
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));
});
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));
});
}
};
@@ -69,12 +73,14 @@ void addEmoteContextMenuItems(const Emote &emote, MessageElement::Flags creatorF
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)); //
});
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) {
@@ -99,7 +105,8 @@ ChannelView::ChannelView(BaseWidget *parent)
}));
this->scrollBar_.getCurrentValueChanged().connect([this] {
// Whenever the scrollbar value has been changed, re-render the ChatWidgetView
// Whenever the scrollbar value has been changed, re-render the
// ChatWidgetView
this->actuallyLayoutMessages(true);
// if (!this->isPaused()) {
@@ -111,21 +118,24 @@ ChannelView::ChannelView(BaseWidget *parent)
this->queueUpdate();
});
this->scrollBar_.getDesiredValueChanged().connect(
[this] { this->pausedByScrollingUp_ = !this->scrollBar_.isAtBottom(); });
this->scrollBar_.getDesiredValueChanged().connect([this] {
this->pausedByScrollingUp_ = !this->scrollBar_.isAtBottom();
});
this->connections_.push_back(app->windows->repaintGifs.connect([&] {
this->queueUpdate(); //
}));
this->connections_.push_back(app->windows->layout.connect([&](Channel *channel) {
if (channel == nullptr || this->channel_.get() == channel) {
this->layoutMessages();
}
}));
this->connections_.push_back(
app->windows->layout.connect([&](Channel *channel) {
if (channel == nullptr || this->channel_.get() == channel) {
this->layoutMessages();
}
}));
this->goToBottom_ = new RippleEffectLabel(this, 0);
this->goToBottom_->setStyleSheet("background-color: rgba(0,0,0,0.66); color: #FFF;");
this->goToBottom_->setStyleSheet(
"background-color: rgba(0,0,0,0.66); color: #FFF;");
this->goToBottom_->getLabel().setText("More messages below");
this->goToBottom_->setVisible(false);
@@ -175,8 +185,9 @@ ChannelView::ChannelView(BaseWidget *parent)
});
QShortcut *shortcut = new QShortcut(QKeySequence("Ctrl+C"), this);
QObject::connect(shortcut, &QShortcut::activated,
[this] { QGuiApplication::clipboard()->setText(this->getSelectedText()); });
QObject::connect(shortcut, &QShortcut::activated, [this] {
QGuiApplication::clipboard()->setText(this->getSelectedText());
});
}
ChannelView::~ChannelView()
@@ -235,7 +246,8 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar)
// True if one of the following statements are true:
// The scrollbar was not visible
// The scrollbar was visible and at the bottom
this->showingLatestMessages_ = this->scrollBar_.isAtBottom() || !this->scrollBar_.isVisible();
this->showingLatestMessages_ =
this->scrollBar_.isAtBottom() || !this->scrollBar_.isVisible();
size_t start = size_t(this->scrollBar_.getCurrentValue());
int layoutWidth = this->getLayoutWidth();
@@ -250,7 +262,8 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar)
for (size_t i = start; i < messagesSnapshot.getLength(); ++i) {
auto message = messagesSnapshot[i];
redrawRequired |= message->layout(layoutWidth, this->getScale(), flags);
redrawRequired |=
message->layout(layoutWidth, this->getScale(), flags);
y += message->getHeight();
@@ -288,9 +301,10 @@ void ChannelView::actuallyLayoutMessages(bool causedByScrollbar)
this->scrollBar_.setMaximum(messagesSnapshot.getLength());
// If we were showing the latest messages and the scrollbar now wants to be rendered, scroll
// to bottom
if (this->enableScrollingToBottom_ && this->showingLatestMessages_ && showScrollbar) {
// If we were showing the latest messages and the scrollbar now wants to be
// rendered, scroll to bottom
if (this->enableScrollingToBottom_ && this->showingLatestMessages_ &&
showScrollbar) {
if (!this->isPaused()) {
this->scrollBar_.scrollToBottom(
// this->messageWasAdded &&
@@ -309,7 +323,8 @@ void ChannelView::clearMessages()
// Clear all stored messages in this chat widget
this->messages.clear();
// Layout chat widget messages, and force an update regardless if there are no messages
// Layout chat widget messages, and force an update regardless if there are
// no messages
this->layoutMessages();
this->queueUpdate();
}
@@ -323,7 +338,8 @@ QString ChannelView::getSelectedText()
{
QString result = "";
LimitedQueueSnapshot<MessageLayoutPtr> messagesSnapshot = this->getMessagesSnapshot();
LimitedQueueSnapshot<MessageLayoutPtr> messagesSnapshot =
this->getMessagesSnapshot();
Selection _selection = this->selection_;
@@ -334,10 +350,12 @@ QString ChannelView::getSelectedText()
for (int msg = _selection.selectionMin.messageIndex;
msg <= _selection.selectionMax.messageIndex; msg++) {
MessageLayoutPtr layout = messagesSnapshot[msg];
int from =
msg == _selection.selectionMin.messageIndex ? _selection.selectionMin.charIndex : 0;
int to = msg == _selection.selectionMax.messageIndex ? _selection.selectionMax.charIndex
: layout->getLastCharacterIndex() + 1;
int from = msg == _selection.selectionMin.messageIndex
? _selection.selectionMin.charIndex
: 0;
int to = msg == _selection.selectionMax.messageIndex
? _selection.selectionMax.charIndex
: layout->getLastCharacterIndex() + 1;
qDebug() << "from:" << from << ", to:" << to;
@@ -374,7 +392,8 @@ void ChannelView::setOverrideFlags(boost::optional<MessageElement::Flags> value)
this->overrideFlags_ = value;
}
const boost::optional<MessageElement::Flags> &ChannelView::getOverrideFlags() const
const boost::optional<MessageElement::Flags> &ChannelView::getOverrideFlags()
const
{
return this->overrideFlags_;
}
@@ -406,13 +425,15 @@ void ChannelView::setChannel(ChannelPtr newChannel)
if (this->lastMessageHasAlternateBackground_) {
messageRef->flags |= MessageLayout::AlternateBackground;
}
this->lastMessageHasAlternateBackground_ = !this->lastMessageHasAlternateBackground_;
this->lastMessageHasAlternateBackground_ =
!this->lastMessageHasAlternateBackground_;
if (this->isPaused()) {
this->messagesAddedSinceSelectionPause_++;
}
if (this->messages.pushBack(MessageLayoutPtr(messageRef), deleted)) {
if (this->messages.pushBack(MessageLayoutPtr(messageRef),
deleted)) {
// if (!this->isPaused()) {
if (this->scrollBar_.isAtBottom()) {
this->scrollBar_.scrollToBottom();
@@ -424,9 +445,11 @@ void ChannelView::setChannel(ChannelPtr newChannel)
if (!(message->flags & Message::DoNotTriggerNotification)) {
if (message->flags & Message::Highlighted) {
this->tabHighlightRequested.invoke(HighlightState::Highlighted);
this->tabHighlightRequested.invoke(
HighlightState::Highlighted);
} else {
this->tabHighlightRequested.invoke(HighlightState::NewMessage);
this->tabHighlightRequested.invoke(
HighlightState::NewMessage);
}
}
@@ -437,34 +460,37 @@ void ChannelView::setChannel(ChannelPtr newChannel)
}));
this->channelConnections_.push_back(
newChannel->messagesAddedAtStart.connect([this](std::vector<MessagePtr> &messages) {
std::vector<MessageLayoutPtr> messageRefs;
messageRefs.resize(messages.size());
for (size_t i = 0; i < messages.size(); i++) {
messageRefs.at(i) = MessageLayoutPtr(new MessageLayout(messages.at(i)));
}
newChannel->messagesAddedAtStart.connect(
[this](std::vector<MessagePtr> &messages) {
std::vector<MessageLayoutPtr> messageRefs;
messageRefs.resize(messages.size());
for (size_t i = 0; i < messages.size(); i++) {
messageRefs.at(i) =
MessageLayoutPtr(new MessageLayout(messages.at(i)));
}
if (!this->isPaused()) {
if (this->messages.pushFront(messageRefs).size() > 0) {
if (this->scrollBar_.isAtBottom()) {
this->scrollBar_.scrollToBottom();
} else {
this->scrollBar_.offset(qreal(messages.size()));
if (!this->isPaused()) {
if (this->messages.pushFront(messageRefs).size() > 0) {
if (this->scrollBar_.isAtBottom()) {
this->scrollBar_.scrollToBottom();
} else {
this->scrollBar_.offset(qreal(messages.size()));
}
}
}
}
std::vector<ScrollbarHighlight> highlights;
highlights.reserve(messages.size());
for (size_t i = 0; i < messages.size(); i++) {
highlights.push_back(messages.at(i)->getScrollBarHighlight());
}
std::vector<ScrollbarHighlight> highlights;
highlights.reserve(messages.size());
for (size_t i = 0; i < messages.size(); i++) {
highlights.push_back(
messages.at(i)->getScrollBarHighlight());
}
this->scrollBar_.addHighlightsAtStart(highlights);
this->scrollBar_.addHighlightsAtStart(highlights);
this->messageWasAdded_ = true;
this->layoutMessages();
}));
this->messageWasAdded_ = true;
this->layoutMessages();
}));
// on message removed
this->channelConnections_.push_back(
@@ -478,17 +504,19 @@ void ChannelView::setChannel(ChannelPtr newChannel)
}));
// on message replaced
this->channelConnections_.push_back(
newChannel->messageReplaced.connect([this](size_t index, MessagePtr replacement) {
if (index >= this->messages.getSnapshot().getLength() || index < 0) {
this->channelConnections_.push_back(newChannel->messageReplaced.connect(
[this](size_t index, MessagePtr replacement) {
if (index >= this->messages.getSnapshot().getLength() ||
index < 0) {
return;
}
MessageLayoutPtr newItem(new MessageLayout(replacement));
auto snapshot = this->messages.getSnapshot();
if (index >= snapshot.getLength()) {
Log("Tried to replace out of bounds message. Index: {}. Length: {}", index,
snapshot.getLength());
Log("Tried to replace out of bounds message. Index: {}. "
"Length: {}",
index, snapshot.getLength());
return;
}
@@ -497,7 +525,8 @@ void ChannelView::setChannel(ChannelPtr newChannel)
newItem->flags |= MessageLayout::AlternateBackground;
}
this->scrollBar_.replaceHighlight(index, replacement->getScrollBarHighlight());
this->scrollBar_.replaceHighlight(
index, replacement->getScrollBarHighlight());
this->messages.replaceItem(message, newItem);
this->layoutMessages();
@@ -513,7 +542,8 @@ void ChannelView::setChannel(ChannelPtr newChannel)
if (this->lastMessageHasAlternateBackground_) {
messageRef->flags |= MessageLayout::AlternateBackground;
}
this->lastMessageHasAlternateBackground_ = !this->lastMessageHasAlternateBackground_;
this->lastMessageHasAlternateBackground_ =
!this->lastMessageHasAlternateBackground_;
this->messages.pushBack(MessageLayoutPtr(messageRef), deleted);
}
@@ -567,7 +597,8 @@ void ChannelView::resizeEvent(QResizeEvent *)
this->update();
}
void ChannelView::setSelection(const SelectionItem &start, const SelectionItem &end)
void ChannelView::setSelection(const SelectionItem &start,
const SelectionItem &end)
{
// selections
if (!this->selecting_ && start != end) {
@@ -596,7 +627,8 @@ MessageElement::Flags ChannelView::getFlags() const
if (split != nullptr) {
if (split->getModerationMode()) {
flags = MessageElement::Flags(flags | MessageElement::ModeratorTools);
flags =
MessageElement::Flags(flags | MessageElement::ModeratorTools);
}
if (this->channel_ == app->twitch.server->mentionsChannel) {
flags = MessageElement::Flags(flags | MessageElement::ChannelName);
@@ -609,7 +641,8 @@ MessageElement::Flags ChannelView::getFlags() const
bool ChannelView::isPaused()
{
return false;
// return this->pausedTemporarily_ || this->pausedBySelection_ || this->pausedByScrollingUp_;
// return this->pausedTemporarily_ || this->pausedBySelection_ ||
// this->pausedByScrollingUp_;
}
void ChannelView::updatePauseStatus()
@@ -633,8 +666,8 @@ void ChannelView::paintEvent(QPaintEvent * /*event*/)
this->drawMessages(painter);
}
// if overlays is false then it draws the message, if true then it draws things such as the grey
// overlay when a message is disabled
// if overlays is false then it draws the message, if true then it draws things
// such as the grey overlay when a message is disabled
void ChannelView::drawMessages(QPainter &painter)
{
auto app = getApp();
@@ -661,7 +694,8 @@ void ChannelView::drawMessages(QPainter &painter)
isLastMessage = this->lastReadMessage_.get() == layout;
}
layout->paint(painter, DRAW_WIDTH, y, i, this->selection_, isLastMessage, windowFocused);
layout->paint(painter, DRAW_WIDTH, y, i, this->selection_,
isLastMessage, windowFocused);
y += layout->getHeight();
@@ -732,7 +766,8 @@ void ChannelView::wheelEvent(QWheelEvent *event)
if (delta > 0) {
qreal scrollFactor = fmod(desired, 1);
qreal currentScrollLeft = int(scrollFactor * snapshot[i]->getHeight());
qreal currentScrollLeft =
int(scrollFactor * snapshot[i]->getHeight());
for (; i >= 0; i--) {
if (delta < currentScrollLeft) {
@@ -746,8 +781,8 @@ void ChannelView::wheelEvent(QWheelEvent *event)
if (i == 0) {
desired = 0;
} else {
snapshot[i - 1]->layout(this->getLayoutWidth(), this->getScale(),
this->getFlags());
snapshot[i - 1]->layout(this->getLayoutWidth(),
this->getScale(), this->getFlags());
scrollFactor = 1;
currentScrollLeft = snapshot[i - 1]->getHeight();
}
@@ -755,11 +790,13 @@ void ChannelView::wheelEvent(QWheelEvent *event)
} else {
delta = -delta;
qreal scrollFactor = 1 - fmod(desired, 1);
qreal currentScrollLeft = int(scrollFactor * snapshot[i]->getHeight());
qreal currentScrollLeft =
int(scrollFactor * snapshot[i]->getHeight());
for (; i < snapshotLength; i++) {
if (delta < currentScrollLeft) {
desired += scrollFactor * (qreal(delta) / currentScrollLeft);
desired +=
scrollFactor * (qreal(delta) / currentScrollLeft);
break;
} else {
delta -= currentScrollLeft;
@@ -769,8 +806,8 @@ void ChannelView::wheelEvent(QWheelEvent *event)
if (i == snapshotLength - 1) {
desired = snapshot.getLength();
} else {
snapshot[i + 1]->layout(this->getLayoutWidth(), this->getScale(),
this->getFlags());
snapshot[i + 1]->layout(this->getLayoutWidth(),
this->getScale(), this->getFlags());
scrollFactor = 1;
currentScrollLeft = snapshot[i + 1]->getHeight();
@@ -826,7 +863,8 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
this->pause(300);
int index = layout->getSelectionIndex(relativePos);
this->setSelection(this->selection_.start, SelectionItem(messageIndex, index));
this->setSelection(this->selection_.start,
SelectionItem(messageIndex, index));
this->queueUpdate();
}
@@ -839,7 +877,8 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
}
// check if word underneath cursor
const MessageLayoutElement *hoverLayoutElement = layout->getElementAt(relativePos);
const MessageLayoutElement *hoverLayoutElement =
layout->getElementAt(relativePos);
if (hoverLayoutElement == nullptr) {
this->setCursor(Qt::ArrowCursor);
@@ -934,7 +973,8 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
if (this->isMouseDown_) {
this->isMouseDown_ = false;
if (fabsf(distanceBetweenPoints(this->lastPressPosition_, event->screenPos())) > 15.f) {
if (fabsf(distanceBetweenPoints(this->lastPressPosition_,
event->screenPos())) > 15.f) {
return;
}
} else {
@@ -944,8 +984,8 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
if (this->isRightMouseDown_) {
this->isRightMouseDown_ = false;
if (fabsf(distanceBetweenPoints(this->lastRightPressPosition_, event->screenPos())) >
15.f) {
if (fabsf(distanceBetweenPoints(this->lastRightPressPosition_,
event->screenPos())) > 15.f) {
return;
}
} else {
@@ -978,7 +1018,8 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
return;
}
const MessageLayoutElement *hoverLayoutElement = layout->getElementAt(relativePos);
const MessageLayoutElement *hoverLayoutElement =
layout->getElementAt(relativePos);
if (hoverLayoutElement == nullptr) {
return;
@@ -988,7 +1029,8 @@ void ChannelView::mouseReleaseEvent(QMouseEvent *event)
this->handleMouseClick(event, hoverLayoutElement, layout.get());
}
void ChannelView::handleMouseClick(QMouseEvent *event, const MessageLayoutElement *hoveredElement,
void ChannelView::handleMouseClick(QMouseEvent *event,
const MessageLayoutElement *hoveredElement,
MessageLayout *layout)
{
switch (event->button()) {
@@ -1029,8 +1071,8 @@ void ChannelView::handleMouseClick(QMouseEvent *event, const MessageLayoutElemen
}
}
void ChannelView::addContextMenuItems(const MessageLayoutElement *hoveredElement,
MessageLayout *layout)
void ChannelView::addContextMenuItems(
const MessageLayoutElement *hoveredElement, MessageLayout *layout)
{
const auto &creator = hoveredElement->getCreator();
auto creatorFlags = creator.getFlags();
@@ -1039,9 +1081,12 @@ void ChannelView::addContextMenuItems(const MessageLayoutElement *hoveredElement
menu->clear();
// Emote actions
if (creatorFlags & (MessageElement::Flags::EmoteImages | MessageElement::Flags::EmojiImage)) {
if (creatorFlags & (MessageElement::Flags::EmoteImages |
MessageElement::Flags::EmojiImage)) {
const auto emoteElement = dynamic_cast<const EmoteElement *>(&creator);
if (emoteElement) addEmoteContextMenuItems(*emoteElement->getEmote(), creatorFlags, *menu);
if (emoteElement)
addEmoteContextMenuItems(*emoteElement->getEmote(), creatorFlags,
*menu);
}
// add seperator
@@ -1053,16 +1098,19 @@ void ChannelView::addContextMenuItems(const MessageLayoutElement *hoveredElement
if (hoveredElement->getLink().type == Link::Url) {
QString url = hoveredElement->getLink().value;
menu->addAction("Open link", [url] { QDesktopServices::openUrl(QUrl(url)); });
menu->addAction("Copy link", [url] { QApplication::clipboard()->setText(url); });
menu->addAction("Open link",
[url] { QDesktopServices::openUrl(QUrl(url)); });
menu->addAction("Copy link",
[url] { QApplication::clipboard()->setText(url); });
menu->addSeparator();
}
// Copy actions
if (!this->selection_.isEmpty()) {
menu->addAction("Copy selection",
[this] { QGuiApplication::clipboard()->setText(this->getSelectedText()); });
menu->addAction("Copy selection", [this] {
QGuiApplication::clipboard()->setText(this->getSelectedText());
});
}
menu->addAction("Copy message", [layout] {
@@ -1103,7 +1151,8 @@ void ChannelView::mouseDoubleClickEvent(QMouseEvent *event)
return;
}
const MessageLayoutElement *hoverLayoutElement = layout->getElementAt(relativePos);
const MessageLayoutElement *hoverLayoutElement =
layout->getElementAt(relativePos);
if (hoverLayoutElement == nullptr) {
return;
@@ -1123,7 +1172,8 @@ void ChannelView::hideEvent(QHideEvent *)
this->messagesOnScreen_.clear();
}
void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link, MessageLayout *layout)
void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link,
MessageLayout *layout)
{
if (event->button() != Qt::LeftButton) {
return;
@@ -1136,7 +1186,8 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link, MessageL
auto *userPopup = new UserInfoPopup;
userPopup->setData(user, this->channel_);
userPopup->setActionOnFocusLoss(BaseWindow::Delete);
QPoint offset(int(150 * this->getScale()), int(70 * this->getScale()));
QPoint offset(int(150 * this->getScale()),
int(70 * this->getScale()));
userPopup->move(QCursor::pos() - offset);
userPopup->show();
@@ -1159,7 +1210,8 @@ void ChannelView::handleLinkClick(QMouseEvent *event, const Link &link, MessageL
}
}
bool ChannelView::tryGetMessageAt(QPoint p, std::shared_ptr<MessageLayout> &_message,
bool ChannelView::tryGetMessageAt(QPoint p,
std::shared_ptr<MessageLayout> &_message,
QPoint &relativePos, int &index)
{
auto messagesSnapshot = this->getMessagesSnapshot();
@@ -1170,7 +1222,8 @@ bool ChannelView::tryGetMessageAt(QPoint p, std::shared_ptr<MessageLayout> &_mes
return false;
}
int y = -(messagesSnapshot[start]->getHeight() * (fmod(this->scrollBar_.getCurrentValue(), 1)));
int y = -(messagesSnapshot[start]->getHeight() *
(fmod(this->scrollBar_.getCurrentValue(), 1)));
for (size_t i = start; i < messagesSnapshot.getLength(); ++i) {
auto message = messagesSnapshot[i];
@@ -1190,7 +1243,8 @@ 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();
}
+10 -7
View File
@@ -70,10 +70,11 @@ protected:
void hideEvent(QHideEvent *) override;
void handleLinkClick(QMouseEvent *event, const Link &link, MessageLayout *layout);
void handleLinkClick(QMouseEvent *event, const Link &link,
MessageLayout *layout);
bool tryGetMessageAt(QPoint p, std::shared_ptr<MessageLayout> &message, QPoint &relativePos,
int &index);
bool tryGetMessageAt(QPoint p, std::shared_ptr<MessageLayout> &message,
QPoint &relativePos, int &index);
private:
void updatePauseStatus();
@@ -85,9 +86,11 @@ private:
MessageElement::Flags getFlags() const;
bool isPaused();
void handleMouseClick(QMouseEvent *event, const MessageLayoutElement *hoverLayoutElement,
void handleMouseClick(QMouseEvent *event,
const MessageLayoutElement *hoverLayoutElement,
MessageLayout *layout);
void addContextMenuItems(const MessageLayoutElement *hoveredElement, MessageLayout *layout);
void addContextMenuItems(const MessageLayoutElement *hoveredElement,
MessageLayout *layout);
int getLayoutWidth() const;
QTimer *layoutCooldown_;
@@ -114,8 +117,8 @@ private:
Scrollbar scrollBar_;
RippleEffectLabel *goToBottom_;
// This variable can be used to decide whether or not we should render the "Show latest
// messages" button
// This variable can be used to decide whether or not we should render the
// "Show latest messages" button
bool showingLatestMessages_ = true;
bool enableScrollingToBottom_ = true;
+10 -5
View File
@@ -13,7 +13,8 @@ ComboBoxItemDelegate::~ComboBoxItemDelegate()
{
}
QWidget *ComboBoxItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
QWidget *ComboBoxItemDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QVariant data = index.data(Qt::UserRole + 1);
@@ -27,10 +28,12 @@ QWidget *ComboBoxItemDelegate::createEditor(QWidget *parent, const QStyleOptionV
return combo;
}
void ComboBoxItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
void ComboBoxItemDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
if (QComboBox *cb = qobject_cast<QComboBox *>(editor)) {
// get the index of the text in the combobox that matches the current value of the itenm
// get the index of the text in the combobox that matches the current
// value of the itenm
QString currentText = index.data(Qt::EditRole).toString();
int cbIndex = cb->findText(currentText);
@@ -43,11 +46,13 @@ void ComboBoxItemDelegate::setEditorData(QWidget *editor, const QModelIndex &ind
}
}
void ComboBoxItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
void ComboBoxItemDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const
{
if (QComboBox *cb = qobject_cast<QComboBox *>(editor))
// save the current text of the combo box as the current value of the item
// save the current text of the combo box as the current value of the
// item
model->setData(index, cb->currentText(), Qt::EditRole);
else
QStyledItemDelegate::setModelData(editor, model, index);
+2 -1
View File
@@ -14,7 +14,8 @@ public:
ComboBoxItemDelegate(QObject *parent = nullptr);
~ComboBoxItemDelegate();
virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const;
virtual void setModelData(QWidget *editor, QAbstractItemModel *model,
+6 -3
View File
@@ -31,14 +31,16 @@ EditableModelView::EditableModelView(QAbstractTableModel *model)
// add
QPushButton *add = new QPushButton("Add");
buttons->addWidget(add);
QObject::connect(add, &QPushButton::clicked, [this] { this->addButtonPressed.invoke(); });
QObject::connect(add, &QPushButton::clicked,
[this] { this->addButtonPressed.invoke(); });
// remove
QPushButton *remove = new QPushButton("Remove");
buttons->addWidget(remove);
QObject::connect(remove, &QPushButton::clicked, [this] {
QModelIndexList list;
while ((list = this->getTableView()->selectionModel()->selectedRows(0)).length() > 0) {
while ((list = this->getTableView()->selectionModel()->selectedRows(0))
.length() > 0) {
model_->removeRow(list[0].row());
}
});
@@ -55,7 +57,8 @@ void EditableModelView::setTitles(std::initializer_list<QString> titles)
break;
}
this->model_->setHeaderData(i++, Qt::Horizontal, title, Qt::DisplayRole);
this->model_->setHeaderData(i++, Qt::Horizontal, title,
Qt::DisplayRole);
}
}
+4 -2
View File
@@ -27,9 +27,11 @@ public:
painter.setPen(QColor("#999"));
if (this->vertical_) {
painter.drawLine(this->width() / 2, 0, this->width() / 2, this->height());
painter.drawLine(this->width() / 2, 0, this->width() / 2,
this->height());
} else {
painter.drawLine(0, this->height() / 2, this->width(), this->height() / 2);
painter.drawLine(0, this->height() / 2, this->width(),
this->height() / 2);
}
}
+15 -12
View File
@@ -68,12 +68,14 @@ void NotebookButton::paintEvent(QPaintEvent *event)
QRect rect = this->rect();
int s = h * 4 / 9;
painter.drawLine(
rect.left() + rect.width() / 2 - (s / 2), rect.top() + rect.height() / 2,
rect.left() + rect.width() / 2 + (s / 2), rect.top() + rect.height() / 2);
painter.drawLine(
rect.left() + rect.width() / 2, rect.top() + rect.height() / 2 - (s / 2),
rect.left() + rect.width() / 2, rect.top() + rect.height() / 2 + (s / 2));
painter.drawLine(rect.left() + rect.width() / 2 - (s / 2),
rect.top() + rect.height() / 2,
rect.left() + rect.width() / 2 + (s / 2),
rect.top() + rect.height() / 2);
painter.drawLine(rect.left() + rect.width() / 2,
rect.top() + rect.height() / 2 - (s / 2),
rect.left() + rect.width() / 2,
rect.top() + rect.height() / 2 + (s / 2));
} break;
case User: {
@@ -105,9 +107,10 @@ void NotebookButton::paintEvent(QPaintEvent *event)
path.arcMoveTo(a, a, 6 * a, 6 * a, 0 - (360 / 32.0));
for (int i = 0; i < 8; i++) {
path.arcTo(a, a, 6 * a, 6 * a, i * (360 / 8.0) - (360 / 32.0), (360 / 32.0));
path.arcTo(2 * a, 2 * a, 4 * a, 4 * a, i * (360 / 8.0) + (360 / 32.0),
path.arcTo(a, a, 6 * a, 6 * a, i * (360 / 8.0) - (360 / 32.0),
(360 / 32.0));
path.arcTo(2 * a, 2 * a, 4 * a, 4 * a,
i * (360 / 8.0) + (360 / 32.0), (360 / 32.0));
}
painter.fillPath(path, foreground);
@@ -144,8 +147,8 @@ void NotebookButton::dragEnterEvent(QDragEnterEvent *event)
event->acceptProposedAction();
auto e = new QMouseEvent(QMouseEvent::MouseButtonPress,
QPointF(this->width() / 2, this->height() / 2), Qt::LeftButton,
Qt::LeftButton, 0);
QPointF(this->width() / 2, this->height() / 2),
Qt::LeftButton, Qt::LeftButton, 0);
RippleEffectButton::mousePressEvent(e);
delete e;
}
@@ -156,8 +159,8 @@ void NotebookButton::dragLeaveEvent(QDragLeaveEvent *)
this->update();
auto e = new QMouseEvent(QMouseEvent::MouseButtonRelease,
QPointF(this->width() / 2, this->height() / 2), Qt::LeftButton,
Qt::LeftButton, 0);
QPointF(this->width() / 2, this->height() / 2),
Qt::LeftButton, Qt::LeftButton, 0);
RippleEffectButton::mouseReleaseEvent(e);
delete e;
}
+59 -38
View File
@@ -30,17 +30,20 @@ NotebookTab::NotebookTab(Notebook *notebook)
this->setAcceptDrops(true);
this->positionChangedAnimation_.setEasingCurve(QEasingCurve(QEasingCurve::InCubic));
this->positionChangedAnimation_.setEasingCurve(
QEasingCurve(QEasingCurve::InCubic));
app->settings->showTabCloseButton.connect(boost::bind(&NotebookTab::hideTabXChanged, this, _1),
this->managedConnections_);
app->settings->showTabCloseButton.connect(
boost::bind(&NotebookTab::hideTabXChanged, this, _1),
this->managedConnections_);
this->setMouseTracking(true);
this->menu_.addAction("Rename", [this]() {
TextInputDialog d(this);
d.setWindowTitle("Change tab title (Leave empty for default behaviour)");
d.setWindowTitle(
"Change tab title (Leave empty for default behaviour)");
d.setText(this->getCustomTitle());
d.highlightText();
@@ -54,12 +57,13 @@ NotebookTab::NotebookTab(Notebook *notebook)
// new QAction("Enable highlights on new message", &this->menu);
// enableHighlightsOnNewMessageAction->setCheckable(true);
this->menu_.addAction("Close", [=]() { this->notebook_->removePage(this->page); });
this->menu_.addAction("Close",
[=]() { this->notebook_->removePage(this->page); });
// this->menu.addAction(enableHighlightsOnNewMessageAction);
// QObject::connect(enableHighlightsOnNewMessageAction, &QAction::toggled, [this](bool
// newValue) {
// QObject::connect(enableHighlightsOnNewMessageAction,
// &QAction::toggled, [this](bool newValue) {
// Log("New value is {}", newValue); //
// });
}
@@ -78,7 +82,8 @@ void NotebookTab::updateSize()
int width;
QFontMetrics metrics = getApp()->fonts->getFontMetrics(
FontStyle::UiTabs, float(qreal(this->getScale()) * this->devicePixelRatioF()));
FontStyle::UiTabs,
float(qreal(this->getScale()) * this->devicePixelRatioF()));
if (this->hasXButton()) {
width = (metrics.width(this->getTitle()) + int(32 * scale));
@@ -135,7 +140,8 @@ const QString &NotebookTab::getDefaultTitle() const
const QString &NotebookTab::getTitle() const
{
return this->customTitle_.isEmpty() ? this->defaultTitle_ : this->customTitle_;
return this->customTitle_.isEmpty() ? this->defaultTitle_
: this->customTitle_;
}
void NotebookTab::titleUpdated()
@@ -188,7 +194,8 @@ void NotebookTab::moveAnimated(QPoint pos, bool animated)
QWidget *w = this->window();
if ((w != nullptr && !w->isVisible()) || !animated || !this->positionChangedAnimationRunning_) {
if ((w != nullptr && !w->isVisible()) || !animated ||
!this->positionChangedAnimationRunning_) {
this->move(pos);
this->positionChangedAnimationRunning_ = true;
@@ -213,9 +220,11 @@ void NotebookTab::paintEvent(QPaintEvent *)
float scale = this->getScale();
painter.setFont(getApp()->fonts->getFont(
FontStyle::UiTabs, scale * 96.f / this->logicalDpiX() * this->devicePixelRatioF()));
FontStyle::UiTabs,
scale * 96.f / this->logicalDpiX() * this->devicePixelRatioF()));
QFontMetrics metrics = app->fonts->getFontMetrics(
FontStyle::UiTabs, scale * 96.f / this->logicalDpiX() * this->devicePixelRatioF());
FontStyle::UiTabs,
scale * 96.f / this->logicalDpiX() * this->devicePixelRatioF());
int height = int(scale * NOTEBOOK_TAB_HEIGHT);
// int fullHeight = (int)(scale * 48);
@@ -239,10 +248,12 @@ void NotebookTab::paintEvent(QPaintEvent *)
QBrush tabBackground = /*this->mouseOver_ ? colors.backgrounds.hover
:*/
(windowFocused ? colors.backgrounds.regular : colors.backgrounds.unfocused);
(windowFocused ? colors.backgrounds.regular
: colors.backgrounds.unfocused);
// painter.fillRect(rect(), this->mouseOver_ ? regular.backgrounds.hover
// : (windowFocused ? regular.backgrounds.regular
// : (windowFocused ?
// regular.backgrounds.regular
// :
// regular.backgrounds.unfocused));
@@ -262,11 +273,12 @@ void NotebookTab::paintEvent(QPaintEvent *)
// painter.drawPath(path);
// top line
painter.fillRect(QRectF(0, (this->selected_ ? 0.f : 1.f) * scale, this->width(),
(this->selected_ ? 2.f : 1.f) * scale),
this->mouseOver_
? colors.line.hover
: (windowFocused ? colors.line.regular : colors.line.unfocused));
painter.fillRect(
QRectF(0, (this->selected_ ? 0.f : 1.f) * scale, this->width(),
(this->selected_ ? 2.f : 1.f) * scale),
this->mouseOver_
? colors.line.hover
: (windowFocused ? colors.line.regular : colors.line.unfocused));
// set the pen color
painter.setPen(colors.text);
@@ -277,15 +289,17 @@ void NotebookTab::paintEvent(QPaintEvent *)
// draw text
int offset = int(scale * 8);
QRect textRect(offset, this->selected_ ? 1 : 2, this->width() - offset - offset, height);
QRect textRect(offset, this->selected_ ? 1 : 2,
this->width() - offset - offset, height);
if (this->shouldDrawXButton()) {
textRect.setRight(textRect.right() - this->height() / 2);
}
int width = metrics.width(this->getTitle());
Qt::Alignment alignment = width > textRect.width() ? Qt::AlignLeft | Qt::AlignVCenter
: Qt::AlignHCenter | Qt::AlignVCenter;
Qt::Alignment alignment = width > textRect.width()
? Qt::AlignLeft | Qt::AlignVCenter
: Qt::AlignHCenter | Qt::AlignVCenter;
QTextOption option(alignment);
option.setWrapMode(QTextOption::NoWrap);
@@ -307,14 +321,17 @@ void NotebookTab::paintEvent(QPaintEvent *)
int a = static_cast<int>(scale * 4);
painter.drawLine(xRect.topLeft() + QPoint(a, a), xRect.bottomRight() + QPoint(-a, -a));
painter.drawLine(xRect.topRight() + QPoint(-a, a), xRect.bottomLeft() + QPoint(a, -a));
painter.drawLine(xRect.topLeft() + QPoint(a, a),
xRect.bottomRight() + QPoint(-a, -a));
painter.drawLine(xRect.topRight() + QPoint(-a, a),
xRect.bottomLeft() + QPoint(a, -a));
}
}
// draw line at bottom
if (!this->selected_) {
painter.fillRect(0, this->height() - 1, this->width(), 1, app->themes->window.background);
painter.fillRect(0, this->height() - 1, this->width(), 1,
app->themes->window.background);
this->fancyPaint(painter);
}
@@ -322,7 +339,8 @@ void NotebookTab::paintEvent(QPaintEvent *)
bool NotebookTab::hasXButton()
{
return getApp()->settings->showTabCloseButton && this->notebook_->getAllowUserTabManagement();
return getApp()->settings->showTabCloseButton &&
this->notebook_->getAllowUserTabManagement();
}
bool NotebookTab::shouldDrawXButton()
@@ -354,9 +372,10 @@ void NotebookTab::mouseReleaseEvent(QMouseEvent *event)
this->mouseDown_ = false;
auto removeThisPage = [this] {
auto reply = QMessageBox::question(this, "Remove this tab",
"Are you sure that you want to remove this tab?",
QMessageBox::Yes | QMessageBox::Cancel);
auto reply = QMessageBox::question(
this, "Remove this tab",
"Are you sure that you want to remove this tab?",
QMessageBox::Yes | QMessageBox::Cancel);
if (reply == QMessageBox::Yes) {
this->notebook_->removePage(this->page);
@@ -368,7 +387,8 @@ void NotebookTab::mouseReleaseEvent(QMouseEvent *event)
removeThisPage();
}
} else {
if (this->hasXButton() && this->mouseDownX_ && this->getXRect().contains(event->pos())) {
if (this->hasXButton() && this->mouseDownX_ &&
this->getXRect().contains(event->pos())) {
this->mouseDownX_ = false;
removeThisPage();
@@ -399,11 +419,9 @@ void NotebookTab::leaveEvent(QEvent *event)
void NotebookTab::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;
if (this->notebook_->getAllowUserTabManagement()) {
this->notebook_->select(this->page);
@@ -414,7 +432,8 @@ void NotebookTab::mouseMoveEvent(QMouseEvent *event)
{
auto app = getApp();
if (app->settings->showTabCloseButton && this->notebook_->getAllowUserTabManagement()) //
if (app->settings->showTabCloseButton &&
this->notebook_->getAllowUserTabManagement()) //
{
bool overX = this->getXRect().contains(event->pos());
@@ -432,7 +451,8 @@ void NotebookTab::mouseMoveEvent(QMouseEvent *event)
this->notebook_->getAllowUserTabManagement()) //
{
int index;
QWidget *clickedPage = this->notebook_->tabAt(relPoint, index, this->width());
QWidget *clickedPage =
this->notebook_->tabAt(relPoint, index, this->width());
if (clickedPage != nullptr && clickedPage != this->page) {
this->notebook_->rearrangePage(this->page, index);
@@ -449,8 +469,9 @@ QRect NotebookTab::getXRect()
// }
float s = this->getScale();
return QRect(this->width() - static_cast<int>(20 * s), static_cast<int>(6 * s),
static_cast<int>(16 * s), static_cast<int>(16 * s));
return QRect(this->width() - static_cast<int>(20 * s),
static_cast<int>(6 * s), static_cast<int>(16 * s),
static_cast<int>(16 * s));
}
} // namespace chatterino
+23 -14
View File
@@ -12,7 +12,8 @@ ResizingTextEdit::ResizingTextEdit()
this->setSizePolicy(sizePolicy);
this->setAcceptRichText(false);
QObject::connect(this, &QTextEdit::textChanged, this, &QWidget::updateGeometry);
QObject::connect(this, &QTextEdit::textChanged, this,
&QWidget::updateGeometry);
this->setFocusPolicy(Qt::ClickFocus);
}
@@ -77,8 +78,9 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
this->keyPressed.invoke(event);
bool doComplete = (event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab) &&
(event->modifiers() & Qt::ControlModifier) == Qt::NoModifier;
bool doComplete =
(event->key() == Qt::Key_Tab || event->key() == Qt::Key_Backtab) &&
(event->modifiers() & Qt::ControlModifier) == Qt::NoModifier;
if (doComplete) {
// check if there is a completer
@@ -93,10 +95,12 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
return;
}
auto *completionModel = static_cast<CompletionModel *>(this->completer_->model());
auto *completionModel =
static_cast<CompletionModel *>(this->completer_->model());
if (!this->completionInProgress_) {
// First type pressing tab after modifying a message, we refresh our completion model
// First type pressing tab after modifying a message, we refresh our
// completion model
this->completer_->setModel(completionModel);
completionModel->refresh();
this->completionInProgress_ = true;
@@ -107,14 +111,17 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
// scrolling through selections
if (event->key() == Qt::Key_Tab) {
if (!this->completer_->setCurrentRow(this->completer_->currentRow() + 1)) {
if (!this->completer_->setCurrentRow(
this->completer_->currentRow() + 1)) {
// wrap over and start again
this->completer_->setCurrentRow(0);
}
} else {
if (!this->completer_->setCurrentRow(this->completer_->currentRow() - 1)) {
if (!this->completer_->setCurrentRow(
this->completer_->currentRow() - 1)) {
// wrap over and start again
this->completer_->setCurrentRow(this->completer_->completionCount() - 1);
this->completer_->setCurrentRow(
this->completer_->completionCount() - 1);
}
}
@@ -123,10 +130,10 @@ void ResizingTextEdit::keyPressEvent(QKeyEvent *event)
}
// (hemirt)
// this resets the selection in the completion list, it should probably only trigger on actual
// chat input (space, character) and not on every key input (pressing alt for example)
// (fourtf)
// fixed for shift+tab, there might be a better solution but nobody is gonna bother anyways
// this resets the selection in the completion list, it should probably only
// trigger on actual chat input (space, character) and not on every key
// input (pressing alt for example) (fourtf) fixed for shift+tab, there
// might be a better solution but nobody is gonna bother anyways
if (event->key() != Qt::Key_Shift && event->key() != Qt::Key_Control &&
event->key() != Qt::Key_Alt && event->key() != Qt::Key_Super_L &&
event->key() != Qt::Key_Super_R) {
@@ -172,7 +179,8 @@ void ResizingTextEdit::setCompleter(QCompleter *c)
this->completer_->setCompletionMode(QCompleter::InlineCompletion);
this->completer_->setCaseSensitivity(Qt::CaseInsensitive);
QObject::connect(completer_,
static_cast<void (QCompleter::*)(const QString &)>(&QCompleter::highlighted),
static_cast<void (QCompleter::*)(const QString &)>(
&QCompleter::highlighted),
this, &ResizingTextEdit::insertCompletion);
}
@@ -192,7 +200,8 @@ void ResizingTextEdit::insertCompletion(const QString &completion)
}
QTextCursor tc = this->textCursor();
tc.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, prefixSize);
tc.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor,
prefixSize);
tc.insertText(completion);
this->setTextCursor(tc);
}
+2 -1
View File
@@ -31,7 +31,8 @@ protected:
void focusOutEvent(QFocusEvent *event) override;
private:
// hadSpace is set to true in case the "textUnderCursor" word was after a space
// hadSpace is set to true in case the "textUnderCursor" word was after a
// space
QString textUnderCursor(bool *hadSpace = nullptr) const;
QCompleter *completer_ = nullptr;
+22 -16
View File
@@ -10,7 +10,8 @@ namespace chatterino {
RippleEffectButton::RippleEffectButton(BaseWidget *parent)
: BaseWidget(parent)
{
connect(&effectTimer_, &QTimer::timeout, this, &RippleEffectButton::onMouseEffectTimeout);
connect(&effectTimer_, &QTimer::timeout, this,
&RippleEffectButton::onMouseEffectTimeout);
this->effectTimer_.setInterval(20);
this->effectTimer_.start();
@@ -121,29 +122,30 @@ void RippleEffectButton::fancyPaint(QPainter &painter)
if (this->mouseEffectColor_) {
c = this->mouseEffectColor_.get();
} else {
c = this->theme->isLightTheme() ? QColor(0, 0, 0) : QColor(255, 255, 255);
c = this->theme->isLightTheme() ? QColor(0, 0, 0)
: QColor(255, 255, 255);
}
if (this->hoverMultiplier_ > 0) {
QRadialGradient gradient(QPointF(mousePos_), this->width() / 2);
gradient.setColorAt(0,
QColor(c.red(), c.green(), c.blue(), int(50 * this->hoverMultiplier_)));
gradient.setColorAt(1,
QColor(c.red(), c.green(), c.blue(), int(40 * this->hoverMultiplier_)));
gradient.setColorAt(0, QColor(c.red(), c.green(), c.blue(),
int(50 * this->hoverMultiplier_)));
gradient.setColorAt(1, QColor(c.red(), c.green(), c.blue(),
int(40 * this->hoverMultiplier_)));
painter.fillRect(this->rect(), gradient);
}
for (auto effect : this->clickEffects_) {
QRadialGradient gradient(effect.position.x(), effect.position.y(),
effect.progress * qreal(width()) * 2, effect.position.x(),
effect.position.y());
effect.progress * qreal(width()) * 2,
effect.position.x(), effect.position.y());
gradient.setColorAt(0,
QColor(c.red(), c.green(), c.blue(), int((1 - effect.progress) * 95)));
gradient.setColorAt(0.9999,
QColor(c.red(), c.green(), c.blue(), int((1 - effect.progress) * 95)));
gradient.setColorAt(0, QColor(c.red(), c.green(), c.blue(),
int((1 - effect.progress) * 95)));
gradient.setColorAt(0.9999, QColor(c.red(), c.green(), c.blue(),
int((1 - effect.progress) * 95)));
gradient.setColorAt(1, QColor(c.red(), c.green(), c.blue(), int(0)));
painter.fillRect(this->rect(), gradient);
@@ -211,17 +213,20 @@ void RippleEffectButton::onMouseEffectTimeout()
if (selected_) {
if (this->hoverMultiplier_ != 0) {
this->hoverMultiplier_ = std::max(0.0, this->hoverMultiplier_ - 0.1);
this->hoverMultiplier_ =
std::max(0.0, this->hoverMultiplier_ - 0.1);
performUpdate = true;
}
} else if (mouseOver_) {
if (this->hoverMultiplier_ != 1) {
this->hoverMultiplier_ = std::min(1.0, this->hoverMultiplier_ + 0.5);
this->hoverMultiplier_ =
std::min(1.0, this->hoverMultiplier_ + 0.5);
performUpdate = true;
}
} else {
if (this->hoverMultiplier_ != 0) {
this->hoverMultiplier_ = std::max(0.0, this->hoverMultiplier_ - 0.3);
this->hoverMultiplier_ =
std::max(0.0, this->hoverMultiplier_ - 0.3);
performUpdate = true;
}
}
@@ -229,7 +234,8 @@ void RippleEffectButton::onMouseEffectTimeout()
if (this->clickEffects_.size() != 0) {
performUpdate = true;
for (auto it = this->clickEffects_.begin(); it != this->clickEffects_.end();) {
for (auto it = this->clickEffects_.begin();
it != this->clickEffects_.end();) {
it->progress += mouseDown_ ? 0.02 : 0.07;
if (it->progress >= 1.0) {
+2 -1
View File
@@ -77,7 +77,8 @@ void SearchPopup::performSearch()
MessagePtr message = this->snapshot_[i];
if (text.isEmpty() ||
message->searchText.indexOf(this->searchInput_->text(), 0, Qt::CaseInsensitive) != -1) {
message->searchText.indexOf(this->searchInput_->text(), 0,
Qt::CaseInsensitive) != -1) {
channel->addMessage(message);
}
}
+4 -3
View File
@@ -7,8 +7,8 @@
namespace chatterino {
SettingsDialogTab::SettingsDialogTab(SettingsDialog *_dialog, SettingsPage *_page,
QString imageFileName)
SettingsDialogTab::SettingsDialogTab(SettingsDialog *_dialog,
SettingsPage *_page, QString imageFileName)
: BaseWidget(_dialog)
, dialog_(_dialog)
, page_(_page)
@@ -48,7 +48,8 @@ void SettingsDialogTab::paintEvent(QPaintEvent *)
this->style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
int a = (this->height() - (20 * this->getScale())) / 2;
QPixmap pixmap = this->ui_.icon.pixmap(QSize(this->height() - a * 2, this->height() - a * 2));
QPixmap pixmap = this->ui_.icon.pixmap(
QSize(this->height() - a * 2, this->height() - a * 2));
painter.drawPixmap(a, a, pixmap);
+2 -1
View File
@@ -16,7 +16,8 @@ class SettingsDialogTab : public BaseWidget
Q_OBJECT
public:
SettingsDialogTab(SettingsDialog *dialog_, SettingsPage *page_, QString imageFileName);
SettingsDialogTab(SettingsDialog *dialog_, SettingsPage *page_,
QString imageFileName);
void setSelected(bool selected_);
SettingsPage *getSettingsPage();
+3 -2
View File
@@ -102,9 +102,10 @@ void TitleBarButton::paintEvent(QPaintEvent *event)
path.arcMoveTo(a, a, 6 * a, 6 * a, 0 - (360 / 32.0));
for (int i = 0; i < 8; i++) {
path.arcTo(a, a, 6 * a, 6 * a, i * (360 / 8.0) - (360 / 32.0), (360 / 32.0));
path.arcTo(2 * a, 2 * a, 4 * a, 4 * a, i * (360 / 8.0) + (360 / 32.0),
path.arcTo(a, a, 6 * a, 6 * a, i * (360 / 8.0) - (360 / 32.0),
(360 / 32.0));
path.arcTo(2 * a, 2 * a, 4 * a, 4 * a,
i * (360 / 8.0) + (360 / 32.0), (360 / 32.0));
}
painter.strokePath(path, color);
+28 -18
View File
@@ -32,7 +32,8 @@ AboutPage::AboutPage()
auto logo = layout.emplace<QLabel>().assign(&this->logo_);
logo->setPixmap(pixmap);
logo->setFixedSize(PIXMAP_WIDTH, PIXMAP_WIDTH * pixmap.height() / pixmap.width());
logo->setFixedSize(PIXMAP_WIDTH,
PIXMAP_WIDTH * pixmap.height() / pixmap.width());
logo->setScaledContents(true);
// this does nothing
@@ -45,9 +46,9 @@ AboutPage::AboutPage()
{
auto created = xd.emplace<QLabel>();
{
created->setText("Created by <a href=\"https://github.com/fourtf\">fourtf</a><br>"
"with big help from pajlada.");
created->setTextFormat(Qt::RichText);
created->setText("Created by <a
href=\"https://github.com/fourtf\">fourtf</a><br>" "with big help from
pajlada."); created->setTextFormat(Qt::RichText);
created->setTextInteractionFlags(Qt::TextBrowserInteraction |
Qt::LinksAccessibleByKeyboard |
Qt::LinksAccessibleByKeyboard);
@@ -58,18 +59,20 @@ AboutPage::AboutPage()
// auto github = xd.emplace<QLabel>();
// {
// github->setText(
// "<a href=\"https://github.com/fourtf/chatterino2\">Chatterino on
// "<a
href=\"https://github.com/fourtf/chatterino2\">Chatterino on
// Github</a>");
// github->setTextFormat(Qt::RichText);
// github->setTextInteractionFlags(Qt::TextBrowserInteraction |
// Qt::LinksAccessibleByKeyboard |
// Qt::LinksAccessibleByKeyboard);
// github->setTextInteractionFlags(Qt::TextBrowserInteraction |
// Qt::LinksAccessibleByKeyboard |
// Qt::LinksAccessibleByKeyboard);
// github->setOpenExternalLinks(true);
// // github->setPalette(palette);
// }
}*/
auto licenses = layout.emplace<QGroupBox>("Open source software used...");
auto licenses =
layout.emplace<QGroupBox>("Open source software used...");
{
auto form = licenses.emplace<QFormLayout>();
@@ -77,18 +80,23 @@ AboutPage::AboutPage()
":/licenses/qt_lgpl-3.0.txt");
addLicense(form.getElement(), "Boost", "https://www.boost.org/",
":/licenses/boost_boost.txt");
addLicense(form.getElement(), "Fmt", "http://fmtlib.net/", ":/licenses/fmt_bsd2.txt");
addLicense(form.getElement(), "LibCommuni", "https://github.com/communi/libcommuni",
addLicense(form.getElement(), "Fmt", "http://fmtlib.net/",
":/licenses/fmt_bsd2.txt");
addLicense(form.getElement(), "LibCommuni",
"https://github.com/communi/libcommuni",
":/licenses/libcommuni_BSD3.txt");
addLicense(form.getElement(), "OpenSSL", "https://www.openssl.org/",
":/licenses/openssl.txt");
addLicense(form.getElement(), "RapidJson", "http://rapidjson.org/",
":/licenses/rapidjson.txt");
addLicense(form.getElement(), "Pajlada/Settings", "https://github.com/pajlada/settings",
addLicense(form.getElement(), "Pajlada/Settings",
"https://github.com/pajlada/settings",
":/licenses/pajlada_settings.txt");
addLicense(form.getElement(), "Pajlada/Signals", "https://github.com/pajlada/signals",
addLicense(form.getElement(), "Pajlada/Signals",
"https://github.com/pajlada/signals",
":/licenses/pajlada_signals.txt");
addLicense(form.getElement(), "Websocketpp", "https://www.zaphoyd.com/websocketpp/",
addLicense(form.getElement(), "Websocketpp",
"https://www.zaphoyd.com/websocketpp/",
":/licenses/websocketpp.txt");
}
@@ -137,7 +145,8 @@ AboutPage::AboutPage()
QString avatarUrl = contributorParts[2].trimmed();
QString role = contributorParts[3].trimmed();
auto *usernameLabel = new QLabel("<a href=\"" + url + "\">" + username + "</a>");
auto *usernameLabel =
new QLabel("<a href=\"" + url + "\">" + username + "</a>");
usernameLabel->setOpenExternalLinks(true);
auto *roleLabel = new QLabel(role);
@@ -155,7 +164,8 @@ AboutPage::AboutPage()
}
};
const auto addLabels = [&contributorBox2, &usernameLabel, &roleLabel] {
const auto addLabels = [&contributorBox2, &usernameLabel,
&roleLabel] {
auto labelBox = new QVBoxLayout();
contributorBox2->addLayout(labelBox);
@@ -172,8 +182,8 @@ AboutPage::AboutPage()
layout->addStretch(1);
}
void AboutPage::addLicense(QFormLayout *form, const QString &name, const QString &website,
const QString &licenseLink)
void AboutPage::addLicense(QFormLayout *form, const QString &name,
const QString &website, const QString &licenseLink)
{
auto *a = new QLabel("<a href=\"" + website + "\">" + name + "</a>");
a->setOpenExternalLinks(true);
+2 -2
View File
@@ -13,8 +13,8 @@ public:
AboutPage();
private:
void addLicense(QFormLayout *form, const QString &name_, const QString &website,
const QString &licenseLink);
void addLicense(QFormLayout *form, const QString &name_,
const QString &website, const QString &licenseLink);
QLabel *logo_;
};
+5 -3
View File
@@ -25,7 +25,8 @@ AccountsPage::AccountsPage()
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
EditableModelView *view =
layout.emplace<EditableModelView>(app->accounts->createModel(nullptr)).getElement();
layout.emplace<EditableModelView>(app->accounts->createModel(nullptr))
.getElement();
view->getTableView()->horizontalHeader()->setVisible(false);
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
@@ -41,8 +42,9 @@ AccountsPage::AccountsPage()
// auto buttons = layout.emplace<QDialogButtonBox>();
// {
// this->addButton = buttons->addButton("Add", QDialogButtonBox::YesRole);
// this->removeButton = buttons->addButton("Remove", QDialogButtonBox::NoRole);
// this->addButton = buttons->addButton("Add",
// QDialogButtonBox::YesRole); this->removeButton =
// buttons->addButton("Remove", QDialogButtonBox::NoRole);
// }
// layout.emplace<AccountSwitchWidget>(this).assign(&this->accSwitchWidget);
@@ -15,18 +15,20 @@ namespace chatterino {
BrowserExtensionPage::BrowserExtensionPage()
: SettingsPage("Browser integration", "")
{
auto layout = LayoutCreator<BrowserExtensionPage>(this).setLayoutType<QVBoxLayout>();
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.");
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>");
auto firefox =
layout.emplace<QLabel>("<a href=\"" FIREFOX_EXTENSION_LINK
"\">Download for Mozilla Firefox</a>");
firefox->setOpenExternalLinks(true);
layout->addStretch(1);
}
+7 -4
View File
@@ -35,16 +35,19 @@ CommandPage::CommandPage()
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
EditableModelView *view =
layout.emplace<EditableModelView>(app->commands->createModel(nullptr)).getElement();
layout.emplace<EditableModelView>(app->commands->createModel(nullptr))
.getElement();
view->setTitles({"Trigger", "Command"});
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
view->addButtonPressed.connect([] {
getApp()->commands->items.appendItem(Command{"/command", "I made a new command HeyGuys"});
getApp()->commands->items.appendItem(
Command{"/command", "I made a new command HeyGuys"});
});
layout.append(this->createCheckBox("Also match the trigger at the end of the message",
app->settings->allowCommandsAtEnd));
layout.append(
this->createCheckBox("Also match the trigger at the end of the message",
app->settings->allowCommandsAtEnd));
QLabel *text = layout.emplace<QLabel>(TEXT).getElement();
text->setWordWrap(true);
+7 -4
View File
@@ -12,11 +12,14 @@ EmotesPage::EmotesPage()
// 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 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.enableFfzEmotes)); layout.append(this->createCheckBox("Enable
// emojis", settings.enableEmojis));
// layout.append(this->createCheckBox("Enable gif animations",
// settings.enableGifAnimations));
// // clang-format on
+25 -15
View File
@@ -5,7 +5,8 @@
#include <QGroupBox>
#define STREAMLINK_QUALITY "Choose", "Source", "High", "Medium", "Low", "Audio only"
#define STREAMLINK_QUALITY \
"Choose", "Source", "High", "Medium", "Low", "Audio only"
namespace chatterino {
@@ -13,7 +14,8 @@ namespace {
QString CreateLink(const QString &url, const QString &name)
{
return QString("<a href=\"" + url + "\"><span style=\"color: white;\">" + name + "</span></a>");
return QString("<a href=\"" + url + "\"><span style=\"color: white;\">" +
name + "</span></a>");
}
} // namespace
@@ -30,37 +32,45 @@ ExternalToolsPage::ExternalToolsPage()
auto group = layout.emplace<QGroupBox>("Streamlink");
auto groupLayout = group.setLayoutType<QFormLayout>();
auto description =
new QLabel("Streamlink is a command-line utility that pipes video streams from various "
"services into a video player, such as VLC. Make sure to edit the "
"configuration file before you use it!");
auto description = new QLabel(
"Streamlink is a command-line utility that pipes video streams "
"from various "
"services into a video player, such as VLC. Make sure to edit the "
"configuration file before you use it!");
description->setWordWrap(true);
description->setStyleSheet("color: #bbb");
auto links = new QLabel(
CreateLink("https://streamlink.github.io/", "Website") + " " +
CreateLink("https://github.com/streamlink/streamlink/releases/latest", "Download"));
CreateLink(
"https://github.com/streamlink/streamlink/releases/latest",
"Download"));
links->setTextFormat(Qt::RichText);
links->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::LinksAccessibleByKeyboard |
links->setTextInteractionFlags(Qt::TextBrowserInteraction |
Qt::LinksAccessibleByKeyboard |
Qt::LinksAccessibleByKeyboard);
links->setOpenExternalLinks(true);
groupLayout->setWidget(0, QFormLayout::SpanningRole, description);
groupLayout->setWidget(1, QFormLayout::SpanningRole, links);
auto customPathCb = this->createCheckBox(
"Use custom path (Enable if using non-standard streamlink installation path)",
app->settings->streamlinkUseCustomPath);
auto customPathCb =
this->createCheckBox("Use custom path (Enable if using "
"non-standard streamlink installation path)",
app->settings->streamlinkUseCustomPath);
groupLayout->setWidget(2, QFormLayout::SpanningRole, customPathCb);
auto customPath = this->createLineEdit(app->settings->streamlinkPath);
customPath->setPlaceholderText("Path to folder where Streamlink executable can be found");
customPath->setPlaceholderText(
"Path to folder where Streamlink executable can be found");
groupLayout->addRow("Custom streamlink path:", customPath);
groupLayout->addRow(
"Preferred quality:",
this->createComboBox({STREAMLINK_QUALITY}, app->settings->preferredQuality));
groupLayout->addRow("Additional options:",
this->createLineEdit(app->settings->streamlinkOpts));
this->createComboBox({STREAMLINK_QUALITY},
app->settings->preferredQuality));
groupLayout->addRow(
"Additional options:",
this->createLineEdit(app->settings->streamlinkOpts));
app->settings->streamlinkUseCustomPath.connect(
[=](const auto &value, auto) {
+24 -16
View File
@@ -12,7 +12,8 @@
#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"
#define LIMIT_CHATTERS_FOR_SMALLER_STREAMERS \
"Only fetch chatters list for viewers under X viewers"
namespace chatterino {
@@ -26,25 +27,30 @@ FeelPage::FeelPage()
// 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));
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)",
app->settings->showJoins));
"", this->createCheckBox(
"Show which users joined the channel (up to 1000 chatters)",
app->settings->showJoins));
form->addRow(
"", this->createCheckBox("Show which users parted the channel (up to 1000 chatters)",
app->settings->showParts));
"", this->createCheckBox(
"Show which users parted the channel (up to 1000 chatters)",
app->settings->showParts));
form->addRow("Pause chat:",
this->createCheckBox(PAUSE_HOVERING, app->settings->pauseChatHover));
this->createCheckBox(PAUSE_HOVERING,
app->settings->pauseChatHover));
form->addRow("Mouse scroll speed:", this->createMouseScrollSlider());
form->addRow("Links:", this->createCheckBox("Open links only on double click",
app->settings->linksDoubleClickOnly));
form->addRow("Links:",
this->createCheckBox("Open links only on double click",
app->settings->linksDoubleClickOnly));
}
layout->addSpacing(16);
@@ -54,18 +60,20 @@ FeelPage::FeelPage()
auto groupLayout = group.setLayoutType<QFormLayout>();
groupLayout->addRow(
LIMIT_CHATTERS_FOR_SMALLER_STREAMERS,
this->createCheckBox("", app->settings->onlyFetchChattersForSmallerStreamers));
this->createCheckBox(
"", app->settings->onlyFetchChattersForSmallerStreamers));
groupLayout->addRow("What viewer count counts as a \"smaller streamer\"",
this->createSpinBox(app->settings->smallStreamerLimit, 10, 50000));
groupLayout->addRow(
"What viewer count counts as a \"smaller streamer\"",
this->createSpinBox(app->settings->smallStreamerLimit, 10, 50000));
}
{
auto group = layout.emplace<QGroupBox>("Misc");
auto groupLayout = group.setLayoutType<QVBoxLayout>();
groupLayout.append(
this->createCheckBox("Show whispers inline", app->settings->inlineWhispers));
groupLayout.append(this->createCheckBox("Show whispers inline",
app->settings->inlineWhispers));
}
layout->addStretch(1);
+45 -24
View File
@@ -24,7 +24,8 @@
#define HIGHLIGHT_MSG "Highlight messages containing your name"
#define PLAY_SOUND "Play sound when your name is mentioned"
#define FLASH_TASKBAR "Flash taskbar when your name is mentioned"
#define ALWAYS_PLAY "Always play highlight sound (Even if Chatterino is focused)"
#define ALWAYS_PLAY \
"Always play highlight sound (Even if Chatterino is focused)"
namespace chatterino {
@@ -37,7 +38,8 @@ HighlightingPage::HighlightingPage()
auto layout = layoutCreator.emplace<QVBoxLayout>().withoutMargin();
{
// GENERAL
// layout.append(this->createCheckBox(ENABLE_HIGHLIGHTS, app->settings->enableHighlights));
// layout.append(this->createCheckBox(ENABLE_HIGHLIGHTS,
// app->settings->enableHighlights));
// TABS
auto tabs = layout.emplace<QTabWidget>();
@@ -46,15 +48,20 @@ HighlightingPage::HighlightingPage()
auto highlights = tabs.appendTab(new QVBoxLayout, "Phrases");
{
EditableModelView *view =
highlights.emplace<EditableModelView>(app->highlights->createModel(nullptr))
highlights
.emplace<EditableModelView>(
app->highlights->createModel(nullptr))
.getElement();
view->setTitles({"Pattern", "Flash\ntaskbar", "Play\nsound", "Enable\nregex"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
view->setTitles({"Pattern", "Flash\ntaskbar", "Play\nsound",
"Enable\nregex"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(
QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
0, QHeaderView::Stretch);
// fourtf: make class extrend BaseWidget and add this to dpiChanged
// fourtf: make class extrend BaseWidget and add this to
// dpiChanged
QTimer::singleShot(1, [view] {
view->getTableView()->resizeColumnsToContents();
view->getTableView()->setColumnWidth(0, 200);
@@ -69,15 +76,20 @@ HighlightingPage::HighlightingPage()
auto pingUsers = tabs.appendTab(new QVBoxLayout, "Users");
{
EditableModelView *view =
pingUsers.emplace<EditableModelView>(app->highlights->createUserModel(nullptr))
pingUsers
.emplace<EditableModelView>(
app->highlights->createUserModel(nullptr))
.getElement();
view->setTitles({"Username", "Flash\ntaskbar", "Play\nsound", "Enable\nregex"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
view->setTitles({"Username", "Flash\ntaskbar", "Play\nsound",
"Enable\nregex"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(
QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
0, QHeaderView::Stretch);
// fourtf: make class extrend BaseWidget and add this to dpiChanged
// fourtf: make class extrend BaseWidget and add this to
// dpiChanged
QTimer::singleShot(1, [view] {
view->getTableView()->resizeColumnsToContents();
view->getTableView()->setColumnWidth(0, 200);
@@ -85,23 +97,28 @@ HighlightingPage::HighlightingPage()
view->addButtonPressed.connect([] {
getApp()->highlights->highlightedUsers.appendItem(
HighlightPhrase{"highlighted user", true, false, false});
HighlightPhrase{"highlighted user", true, false,
false});
});
}
auto disabledUsers = tabs.appendTab(new QVBoxLayout, "Excluded Users");
auto disabledUsers =
tabs.appendTab(new QVBoxLayout, "Excluded Users");
{
EditableModelView *view =
disabledUsers
.emplace<EditableModelView>(app->highlights->createBlacklistModel(nullptr))
.emplace<EditableModelView>(
app->highlights->createBlacklistModel(nullptr))
.getElement();
view->setTitles({"Pattern", "Enable\nregex"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
0, QHeaderView::Stretch);
// fourtf: make class extrend BaseWidget and add this to dpiChanged
// fourtf: make class extrend BaseWidget and add this to
// dpiChanged
QTimer::singleShot(1, [view] {
view->getTableView()->resizeColumnsToContents();
view->getTableView()->setColumnWidth(0, 200);
@@ -117,17 +134,21 @@ HighlightingPage::HighlightingPage()
// MISC
auto customSound = layout.emplace<QHBoxLayout>().withoutMargin();
{
customSound.append(
this->createCheckBox("Custom sound", app->settings->customHighlightSound));
auto selectFile = customSound.emplace<QPushButton>("Select custom sound file");
QObject::connect(selectFile.getElement(), &QPushButton::clicked, this, [this, app] {
auto fileName = QFileDialog::getOpenFileName(this, tr("Open Sound"), "",
tr("Audio Files (*.mp3 *.wav)"));
app->settings->pathHighlightSound = fileName;
});
customSound.append(this->createCheckBox(
"Custom sound", app->settings->customHighlightSound));
auto selectFile =
customSound.emplace<QPushButton>("Select custom sound file");
QObject::connect(selectFile.getElement(), &QPushButton::clicked,
this, [this, app] {
auto fileName = QFileDialog::getOpenFileName(
this, tr("Open Sound"), "",
tr("Audio Files (*.mp3 *.wav)"));
app->settings->pathHighlightSound = fileName;
});
}
layout.append(createCheckBox(ALWAYS_PLAY, app->settings->highlightAlwaysPlaySound));
layout.append(createCheckBox(ALWAYS_PLAY,
app->settings->highlightAlwaysPlaySound));
}
// ---- misc
+16 -8
View File
@@ -24,7 +24,8 @@
namespace chatterino {
static void addPhrasesTab(LayoutCreator<QVBoxLayout> box);
static void addUsersTab(IgnoresPage &page, LayoutCreator<QVBoxLayout> box, QStringListModel &model);
static void addUsersTab(IgnoresPage &page, LayoutCreator<QVBoxLayout> box,
QStringListModel &model);
IgnoresPage::IgnoresPage()
: SettingsPage("Ignores", "")
@@ -34,7 +35,8 @@ IgnoresPage::IgnoresPage()
auto tabs = layout.emplace<QTabWidget>();
addPhrasesTab(tabs.appendTab(new QVBoxLayout, "Phrases"));
addUsersTab(*this, tabs.appendTab(new QVBoxLayout, "Users"), this->userListModel_);
addUsersTab(*this, tabs.appendTab(new QVBoxLayout, "Users"),
this->userListModel_);
auto label = layout.emplace<QLabel>(INFO);
label->setWordWrap(true);
@@ -44,10 +46,14 @@ IgnoresPage::IgnoresPage()
void addPhrasesTab(LayoutCreator<QVBoxLayout> layout)
{
EditableModelView *view =
layout.emplace<EditableModelView>(getApp()->ignores->createModel(nullptr)).getElement();
layout
.emplace<EditableModelView>(getApp()->ignores->createModel(nullptr))
.getElement();
view->setTitles({"Pattern", "Regex"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
0, QHeaderView::Stretch);
QTimer::singleShot(1, [view] {
view->getTableView()->resizeColumnsToContents();
@@ -59,10 +65,12 @@ void addPhrasesTab(LayoutCreator<QVBoxLayout> layout)
});
}
void addUsersTab(IgnoresPage &page, LayoutCreator<QVBoxLayout> users, QStringListModel &userModel)
void addUsersTab(IgnoresPage &page, LayoutCreator<QVBoxLayout> users,
QStringListModel &userModel)
{
users.append(page.createCheckBox("Enable twitch ignored users",
getApp()->settings->enableTwitchIgnoredUsers));
users.append(
page.createCheckBox("Enable twitch ignored users",
getApp()->settings->enableTwitchIgnoredUsers));
auto anyways = users.emplace<QHBoxLayout>().withoutMargin();
{
@@ -10,31 +10,37 @@ namespace chatterino {
KeyboardSettingsPage::KeyboardSettingsPage()
: SettingsPage("Keybindings", "")
{
auto layout = LayoutCreator<KeyboardSettingsPage>(this).setLayoutType<QVBoxLayout>();
auto layout =
LayoutCreator<KeyboardSettingsPage>(this).setLayoutType<QVBoxLayout>();
auto form = layout.emplace<QFormLayout>();
form->addRow(new QLabel("Hold Ctrl"), new QLabel("Show resize handles"));
form->addRow(new QLabel("Hold Ctrl + Alt"), new QLabel("Show split overlay"));
form->addRow(new QLabel("Hold Ctrl + Alt"),
new QLabel("Show split overlay"));
form->addItem(new QSpacerItem(16, 16));
form->addRow(new QLabel("Ctrl + T"), new QLabel("Create new split"));
form->addRow(new QLabel("Ctrl + W"), new QLabel("Close current split"));
form->addRow(new QLabel("Ctrl + Shift + T"), new QLabel("Create new tab"));
form->addRow(new QLabel("Ctrl + Shift + W"), new QLabel("Close current tab"));
form->addRow(new QLabel("Ctrl + Shift + W"),
new QLabel("Close current tab"));
form->addItem(new QSpacerItem(16, 16));
form->addRow(new QLabel("Ctrl + 1/2/3/..."), new QLabel("Select tab 1/2/3/..."));
form->addRow(new QLabel("Ctrl + 1/2/3/..."),
new QLabel("Select tab 1/2/3/..."));
form->addRow(new QLabel("Ctrl + Tab"), new QLabel("Select next tab"));
form->addRow(new QLabel("Ctrl + Shift + Tab"), new QLabel("Select previous tab"));
form->addRow(new QLabel("Ctrl + Shift + Tab"),
new QLabel("Select previous tab"));
form->addRow(new QLabel("Alt + Left/Up/Right/Down"),
new QLabel("Select split left/up/right/down"));
form->addItem(new QSpacerItem(16, 16));
form->addRow(new QLabel("Ctrl + R"), new QLabel("Change channel"));
form->addRow(new QLabel("Ctrl + F"), new QLabel("Search in current channel"));
form->addRow(new QLabel("Ctrl + F"),
new QLabel("Search in current channel"));
}
} // namespace chatterino
+8 -4
View File
@@ -15,11 +15,13 @@
// inline QString CreateLink(const QString &url, bool file = false)
//{
// if (file) {
// return QString("<a href=\"file:///" + url + "\"><span style=\"color: white;\">" + url +
// return QString("<a href=\"file:///" + url + "\"><span style=\"color:
// white;\">" + url +
// "</span></a>");
// }
// return QString("<a href=\"" + url + "\"><span style=\"color: white;\">" + url +
// return QString("<a href=\"" + url + "\"><span style=\"color: white;\">" +
// url +
// "</span></a>");
//}
@@ -36,10 +38,12 @@
// auto created = layout.emplace<QLabel>();
// created->setText("Logs are saved to " + CreateLink(logPath, true));
// created->setTextFormat(Qt::RichText);
// created->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::LinksAccessibleByKeyboard |
// created->setTextInteractionFlags(Qt::TextBrowserInteraction |
// Qt::LinksAccessibleByKeyboard |
// Qt::LinksAccessibleByKeyboard);
// created->setOpenExternalLinks(true);
// layout.append(this->createCheckBox("Enable logging", app->settings->enableLogging));
// layout.append(this->createCheckBox("Enable logging",
// app->settings->enableLogging));
// layout->addStretch(1);
//}
+131 -83
View File
@@ -70,9 +70,12 @@ void LookPage::addInterfaceTab(LayoutCreator<QVBoxLayout> layout)
{
// theme
{
auto *theme = this->createComboBox({THEME_ITEMS}, getApp()->themes->themeName);
auto *theme =
this->createComboBox({THEME_ITEMS}, getApp()->themes->themeName);
QObject::connect(theme, &QComboBox::currentTextChanged,
[](const QString &) { getApp()->windows->forceLayoutChannelViews(); });
[](const QString &) {
getApp()->windows->forceLayoutChannelViews();
});
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
box.emplace<QLabel>("Theme: ");
@@ -87,24 +90,29 @@ void LookPage::addInterfaceTab(LayoutCreator<QVBoxLayout> layout)
box.append(this->createUiScaleSlider());
}
layout.append(this->createCheckBox(WINDOW_TOPMOST, getSettings()->windowTopMost));
layout.append(
this->createCheckBox(WINDOW_TOPMOST, getSettings()->windowTopMost));
// --
layout.emplace<Line>(false);
// tab x
layout.append(this->createCheckBox(TAB_X, getSettings()->showTabCloseButton));
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));
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));
this->createCheckBox(INPUT_EMPTY, getSettings()->showEmptyInput));
layout.append(this->createCheckBox("Show message length while typing",
getSettings()->showMessageLength));
layout->addStretch(1);
}
@@ -125,37 +133,43 @@ void LookPage::addMessageTab(LayoutCreator<QVBoxLayout> layout)
// timestamps
{
auto box = layout.emplace<QHBoxLayout>().withoutMargin();
box.append(this->createCheckBox("Show timestamps", getSettings()->showTimestamps));
box.append(this->createComboBox({TIMESTAMP_FORMATS}, getSettings()->timestampFormat));
box.append(this->createCheckBox("Show timestamps",
getSettings()->showTimestamps));
box.append(this->createComboBox({TIMESTAMP_FORMATS},
getSettings()->timestampFormat));
box->addStretch(1);
}
// badges
layout.append(this->createCheckBox("Show badges", getSettings()->showBadges));
layout.append(
this->createCheckBox("Show badges", getSettings()->showBadges));
// --
layout.emplace<Line>(false);
// seperate
layout.append(this->createCheckBox("Seperate lines", getSettings()->separateMessages));
layout.append(this->createCheckBox("Seperate lines",
getSettings()->separateMessages));
// alternate
layout.append(
this->createCheckBox("Alternate background", getSettings()->alternateMessageBackground));
layout.append(this->createCheckBox(
"Alternate background", getSettings()->alternateMessageBackground));
// --
layout.emplace<Line>(false);
// lowercase links
layout.append(this->createCheckBox("Lowercase domains", getSettings()->enableLowercaseLink));
layout.append(this->createCheckBox("Lowercase domains",
getSettings()->enableLowercaseLink));
// bold usernames
layout.append(this->createCheckBox("Bold @usernames", getSettings()->enableUsernameBold));
layout.append(this->createCheckBox("Bold @usernames",
getSettings()->enableUsernameBold));
// collapsing
{
auto *combo = new QComboBox(this);
combo->addItems(
{"Never", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"});
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();
@@ -166,9 +180,10 @@ void LookPage::addMessageTab(LayoutCreator<QVBoxLayout> layout)
}();
combo->setCurrentIndex(currentIndex);
QObject::connect(combo, &QComboBox::currentTextChanged, [](const QString &str) {
getSettings()->collpseMessagesMinLines = str.toInt();
});
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");
@@ -187,14 +202,17 @@ void LookPage::addEmoteTab(LayoutCreator<QVBoxLayout> layout)
{
/*
emotes.append(
this->createCheckBox("Enable Twitch emotes", app->settings->enableTwitchEmotes));
this->createCheckBox("Enable Twitch emotes",
app->settings->enableTwitchEmotes));
emotes.append(this->createCheckBox("Enable BetterTTV emotes for Twitch",
app->settings->enableBttvEmotes));
emotes.append(this->createCheckBox("Enable FrankerFaceZ emotes for Twitch",
app->settings->enableFfzEmotes));
emotes.append(this->createCheckBox("Enable emojis", app->settings->enableEmojis));
emotes.append(this->createCheckBox("Enable emojis",
app->settings->enableEmojis));
*/
layout.append(this->createCheckBox("Animations", getSettings()->enableGifAnimations));
layout.append(
this->createCheckBox("Animations", getSettings()->enableGifAnimations));
auto scaleBox = layout.emplace<QHBoxLayout>().withoutMargin();
{
@@ -214,22 +232,25 @@ void LookPage::addEmoteTab(LayoutCreator<QVBoxLayout> layout)
getSettings()->emoteScale.setValue(f);
});
emoteScale->setValue(
std::max<int>(5, std::min<int>(50, int(getSettings()->emoteScale.getValue() * 10.f))));
emoteScale->setValue(std::max<int>(
5, std::min<int>(
50, int(getSettings()->emoteScale.getValue() * 10.f))));
scaleLabel->setText(QString::number(getSettings()->emoteScale.getValue()));
scaleLabel->setText(
QString::number(getSettings()->emoteScale.getValue()));
}
{
auto *combo = new QComboBox(this);
combo->addItems(
{"EmojiOne 2", "EmojiOne 3", "Twitter", "Facebook", "Apple", "Google", "Messenger"});
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; //
});
QObject::connect(combo, &QComboBox::currentTextChanged,
[](const QString &str) {
getSettings()->emojiSet = str; //
});
auto hbox = layout.emplace<QHBoxLayout>().withoutMargin();
hbox.emplace<QLabel>("Emoji set:");
@@ -241,15 +262,18 @@ void LookPage::addEmoteTab(LayoutCreator<QVBoxLayout> layout)
void LookPage::addSplitHeaderTab(LayoutCreator<QVBoxLayout> layout)
{
layout.append(this->createCheckBox("Show viewer count", getSettings()->showViewerCount));
layout.append(this->createCheckBox("Show viewer count",
getSettings()->showViewerCount));
layout.append(this->createCheckBox("Show title", getSettings()->showTitle));
layout.append(this->createCheckBox("Show game", getSettings()->showGame));
layout.append(this->createCheckBox("Show uptime", getSettings()->showUptime));
layout.append(
this->createCheckBox("Show uptime", getSettings()->showUptime));
layout->addStretch(1);
}
void LookPage::addLastReadMessageIndicatorPatternSelector(LayoutCreator<QVBoxLayout> layout)
void LookPage::addLastReadMessageIndicatorPatternSelector(
LayoutCreator<QVBoxLayout> layout)
{
// combo
auto *combo = new QComboBox(this);
@@ -266,22 +290,25 @@ void LookPage::addLastReadMessageIndicatorPatternSelector(LayoutCreator<QVBoxLay
}();
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;
}
}();
});
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;
}
}();
});
// layout
auto hbox = layout.emplace<QHBoxLayout>().withoutMargin();
hbox.append(this->createCheckBox(LAST_MSG, getSettings()->showLastMessageIndicator));
hbox.append(this->createCheckBox(LAST_MSG,
getSettings()->showLastMessageIndicator));
hbox.append(combo);
hbox->addStretch(1);
}
@@ -293,39 +320,49 @@ ChannelPtr LookPage::createPreviewChannel()
{
auto message = MessagePtr(new Message());
message->addElement(new TimestampElement(QTime(8, 13, 42)));
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 ImageElement(Image::fromNonOwningPixmap(&getApp()->resources->twitch.moderator),
MessageElement::BadgeChannelAuthority));
new TextElement("username1:", MessageElement::Username,
QColor("#0094FF"), FontStyle::ChatMediumBold));
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));
new TextElement("This is a preview message", MessageElement::Text));
message->addElement(new ImageElement(
Image::fromNonOwningPixmap(&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));
new TextElement("@fourtf", TextElement::BoldUsername,
MessageColor::Text, FontStyle::ChatMediumBold));
message->addElement(
new TextElement("@fourtf", TextElement::NonBoldUsername));
channel->addMessage(message);
}
{
auto message = MessagePtr(new Message());
message->addElement(new TimestampElement(QTime(8, 15, 21)));
message->addElement(
new ImageElement(Image::fromNonOwningPixmap(&getApp()->resources->twitch.broadcaster),
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 ImageElement(
// Image::fromNonOwningPixmap(&getApp()->resources->ppHop), MessageElement::BttvEmote));
message->addElement(
(new TextElement("www.fourtf.com", MessageElement::LowercaseLink, MessageColor::Link))
new TextElement("username2:", MessageElement::Username,
QColor("#FF6A00"), FontStyle::ChatMediumBold));
message->addElement(
new TextElement("This is another one", MessageElement::Text));
// 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")));
message->addElement(
(new TextElement("wWw.FoUrTf.CoM", MessageElement::OriginalLink, MessageColor::Link))
(new TextElement("wWw.FoUrTf.CoM", MessageElement::OriginalLink,
MessageColor::Link))
->setLink(Link(Link::Url, "https://www.fourtf.com")));
channel->addMessage(message);
}
@@ -343,7 +380,8 @@ QLayout *LookPage::createThemeColorChanger()
// SLIDER
QSlider *slider = new QSlider(Qt::Horizontal);
layout->addWidget(slider);
slider->setValue(int(std::min(std::max(themeHue.getValue(), 0.0), 1.0) * 100));
slider->setValue(
int(std::min(std::max(themeHue.getValue(), 0.0), 1.0) * 100));
// BUTTON
QPushButton *button = new QPushButton;
@@ -384,12 +422,16 @@ QLayout *LookPage::createFontChanger()
layout->addWidget(label);
auto updateFontFamilyLabel = [=](auto) {
label->setText("Font (" + QString::fromStdString(app->fonts->chatFontFamily.getValue()) +
", " + QString::number(app->fonts->chatFontSize) + "pt)");
label->setText(
"Font (" +
QString::fromStdString(app->fonts->chatFontFamily.getValue()) +
", " + QString::number(app->fonts->chatFontSize) + "pt)");
};
app->fonts->chatFontFamily.connectSimple(updateFontFamilyLabel, this->managedConnections_);
app->fonts->chatFontSize.connectSimple(updateFontFamilyLabel, this->managedConnections_);
app->fonts->chatFontFamily.connectSimple(updateFontFamilyLabel,
this->managedConnections_);
app->fonts->chatFontSize.connectSimple(updateFontFamilyLabel,
this->managedConnections_);
// BUTTON
QPushButton *button = new QPushButton("Select");
@@ -401,10 +443,11 @@ QLayout *LookPage::createFontChanger()
dialog.setWindowFlag(Qt::WindowStaysOnTopHint);
dialog.connect(&dialog, &QFontDialog::fontSelected, [=](const QFont &font) {
app->fonts->chatFontFamily = font.family().toStdString();
app->fonts->chatFontSize = font.pointSize();
});
dialog.connect(
&dialog, &QFontDialog::fontSelected, [=](const QFont &font) {
app->fonts->chatFontFamily = font.family().toStdString();
app->fonts->chatFontSize = font.pointSize();
});
dialog.show();
dialog.exec();
@@ -425,15 +468,19 @@ QLayout *LookPage::createUiScaleSlider()
slider->setMinimum(WindowManager::uiScaleMin);
slider->setMaximum(WindowManager::uiScaleMax);
slider->setValue(WindowManager::clampUiScale(getSettings()->uiScale.getValue()));
slider->setValue(
WindowManager::clampUiScale(getSettings()->uiScale.getValue()));
label->setMinimumWidth(100);
QObject::connect(slider, &QSlider::valueChanged,
[](auto value) { getSettings()->uiScale.setValue(value); });
QObject::connect(slider, &QSlider::valueChanged, [](auto value) {
getSettings()->uiScale.setValue(value);
});
getSettings()->uiScale.connect(
[label](auto, auto) { label->setText(QString::number(WindowManager::getUiScaleValue())); },
[label](auto, auto) {
label->setText(QString::number(WindowManager::getUiScaleValue()));
},
this->connections_);
return layout;
@@ -454,8 +501,9 @@ QLayout *LookPage::createBoldScaleSlider()
label->setMinimumWidth(100);
QObject::connect(slider, &QSlider::valueChanged,
[](auto value) { getSettings()->boldScale.setValue(value); });
QObject::connect(slider, &QSlider::valueChanged, [](auto value) {
getSettings()->boldScale.setValue(value);
});
// show value
// getSettings()->boldScale.connect(
// [label](auto, auto) {
+2 -1
View File
@@ -24,7 +24,8 @@ private:
void addEmoteTab(LayoutCreator<QVBoxLayout> layout);
void addSplitHeaderTab(LayoutCreator<QVBoxLayout> layout);
void addLastReadMessageIndicatorPatternSelector(LayoutCreator<QVBoxLayout> layout);
void addLastReadMessageIndicatorPatternSelector(
LayoutCreator<QVBoxLayout> layout);
QLayout *createThemeColorChanger();
QLayout *createFontChanger();
+57 -43
View File
@@ -28,11 +28,13 @@ namespace chatterino {
inline QString CreateLink(const QString &url, bool file = false)
{
if (file) {
return QString("<a href=\"file:///" + url + "\"><span style=\"color: white;\">" + url +
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>");
return QString("<a href=\"" + url + "\"><span style=\"color: white;\">" +
url + "</span></a>");
}
qint64 dirSize(QString dirPath)
@@ -46,7 +48,8 @@ qint64 dirSize(QString dirPath)
size += fi.size();
}
// add size of child directories recursively
QDir::Filters dirFilters = QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden;
QDir::Filters dirFilters =
QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden;
for (QString childDirPath : dir.entryList(dirFilters))
size += dirSize(dirPath + QDir::separator() + childDirPath);
return size;
@@ -58,8 +61,7 @@ QString formatSize(qint64 size)
int i;
double outputSize = size;
for (i = 0; i < units.size() - 1; i++) {
if (outputSize < 1024)
break;
if (outputSize < 1024) break;
outputSize = outputSize / 1024;
}
return QString("%0 %1").arg(outputSize, 0, 'f', 2).arg(units[i]);
@@ -95,57 +97,63 @@ ModerationPage::ModerationPage()
// Show how big (size-wise) the logs are
auto logsPathSizeLabel = logs.emplace<QLabel>();
logsPathSizeLabel->setText(QtConcurrent::run([] { return fetchLogDirectorySize(); }));
logsPathSizeLabel->setText(
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
// Logs (copied from LoggingMananger)
app->settings->logPath.connect([app, logsPathLabel](const QString &logPath, auto) mutable {
QString pathOriginal;
app->settings->logPath.connect(
[app, logsPathLabel](const QString &logPath, auto) mutable {
QString pathOriginal;
if (logPath == "") {
pathOriginal = app->paths->messageLogDirectory;
} else {
pathOriginal = logPath;
}
if (logPath == "") {
pathOriginal = app->paths->messageLogDirectory;
} else {
pathOriginal = logPath;
}
QString pathShortened;
QString pathShortened;
if (pathOriginal.size() > 50) {
pathShortened = pathOriginal;
pathShortened.resize(50);
pathShortened += "...";
} else {
pathShortened = pathOriginal;
}
if (pathOriginal.size() > 50) {
pathShortened = pathOriginal;
pathShortened.resize(50);
pathShortened += "...";
} else {
pathShortened = pathOriginal;
}
pathShortened = "Logs saved at <a href=\"file:///" + pathOriginal +
"\"><span style=\"color: white;\">" + pathShortened + "</span></a>";
pathShortened = "Logs saved at <a href=\"file:///" +
pathOriginal +
"\"><span style=\"color: white;\">" +
pathShortened + "</span></a>";
logsPathLabel->setText(pathShortened);
logsPathLabel->setToolTip(pathOriginal);
});
logsPathLabel->setText(pathShortened);
logsPathLabel->setToolTip(pathOriginal);
});
logsPathLabel->setTextFormat(Qt::RichText);
logsPathLabel->setTextInteractionFlags(Qt::TextBrowserInteraction |
Qt::LinksAccessibleByKeyboard |
Qt::LinksAccessibleByKeyboard);
logsPathLabel->setOpenExternalLinks(true);
logs.append(this->createCheckBox("Enable logging", app->settings->enableLogging));
logs.append(this->createCheckBox("Enable logging",
app->settings->enableLogging));
logs->addStretch(1);
auto selectDir = logs.emplace<QPushButton>("Set custom logpath");
// Setting custom logpath
QObject::connect(selectDir.getElement(), &QPushButton::clicked, this,
[this, logsPathSizeLabel]() mutable {
auto app = getApp();
auto dirName = QFileDialog::getExistingDirectory(this);
QObject::connect(
selectDir.getElement(), &QPushButton::clicked, this,
[this, logsPathSizeLabel]() mutable {
auto app = getApp();
auto dirName = QFileDialog::getExistingDirectory(this);
app->settings->logPath = dirName;
app->settings->logPath = dirName;
// Refresh: Show how big (size-wise) the logs are
logsPathSizeLabel->setText(
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
});
// Refresh: Show how big (size-wise) the logs are
logsPathSizeLabel->setText(
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
});
// Reset custom logpath
auto resetDir = logs.emplace<QPushButton>("Reset logpath");
@@ -155,8 +163,8 @@ ModerationPage::ModerationPage()
app->settings->logPath = "";
// Refresh: Show how big (size-wise) the logs are
logsPathSizeLabel->setText(
QtConcurrent::run([] { return fetchLogDirectorySize(); }));
logsPathSizeLabel->setText(QtConcurrent::run(
[] { return fetchLogDirectorySize(); }));
});
// Logs end
@@ -172,21 +180,27 @@ ModerationPage::ModerationPage()
// auto form = modMode.emplace<QFormLayout>();
// {
// form->addRow("Action on timed out messages (unimplemented):",
// form->addRow("Action on timed out messages
// (unimplemented):",
// this->createComboBox({"Disable", "Hide"},
// app->settings->timeoutAction));
// }
EditableModelView *view =
modMode.emplace<EditableModelView>(app->moderationActions->createModel(nullptr))
modMode
.emplace<EditableModelView>(
app->moderationActions->createModel(nullptr))
.getElement();
view->setTitles({"Actions"});
view->getTableView()->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
QHeaderView::Fixed);
view->getTableView()->horizontalHeader()->setSectionResizeMode(
0, QHeaderView::Stretch);
view->addButtonPressed.connect([] {
getApp()->moderationActions->items.appendItem(ModerationAction("/timeout {user} 300"));
getApp()->moderationActions->items.appendItem(
ModerationAction("/timeout {user} 300"));
});
/*auto taggedUsers = tabs.appendTab(new QVBoxLayout, "Tagged users");
+22 -16
View File
@@ -25,8 +25,8 @@ void SettingsPage::cancel()
this->onCancel_.invoke();
}
QCheckBox *SettingsPage::createCheckBox(const QString &text,
pajlada::Settings::Setting<bool> &setting)
QCheckBox *SettingsPage::createCheckBox(
const QString &text, pajlada::Settings::Setting<bool> &setting)
{
QCheckBox *checkbox = new QCheckBox(text);
@@ -38,16 +38,17 @@ QCheckBox *SettingsPage::createCheckBox(const QString &text,
this->managedConnections_);
// update setting on toggle
QObject::connect(checkbox, &QCheckBox::toggled, this, [&setting](bool state) {
qDebug() << "update checkbox value";
setting = state; //
});
QObject::connect(checkbox, &QCheckBox::toggled, this,
[&setting](bool state) {
qDebug() << "update checkbox value";
setting = state; //
});
return checkbox;
}
QComboBox *SettingsPage::createComboBox(const QStringList &items,
pajlada::Settings::Setting<QString> &setting)
QComboBox *SettingsPage::createComboBox(
const QStringList &items, pajlada::Settings::Setting<QString> &setting)
{
QComboBox *combo = new QComboBox();
@@ -55,29 +56,34 @@ QComboBox *SettingsPage::createComboBox(const QStringList &items,
combo->addItems(items);
// update when setting changes
setting.connect([combo](const QString &value, auto) { combo->setCurrentText(value); },
this->managedConnections_);
setting.connect(
[combo](const QString &value, auto) { combo->setCurrentText(value); },
this->managedConnections_);
QObject::connect(combo, &QComboBox::currentTextChanged,
[&setting](const QString &newValue) { setting = newValue; });
QObject::connect(
combo, &QComboBox::currentTextChanged,
[&setting](const QString &newValue) { setting = newValue; });
return combo;
}
QLineEdit *SettingsPage::createLineEdit(pajlada::Settings::Setting<QString> &setting)
QLineEdit *SettingsPage::createLineEdit(
pajlada::Settings::Setting<QString> &setting)
{
QLineEdit *edit = new QLineEdit();
edit->setText(setting);
// update when setting changes
QObject::connect(edit, &QLineEdit::textChanged,
[&setting](const QString &newValue) { setting = newValue; });
QObject::connect(
edit, &QLineEdit::textChanged,
[&setting](const QString &newValue) { setting = newValue; });
return edit;
}
QSpinBox *SettingsPage::createSpinBox(pajlada::Settings::Setting<int> &setting, int min, int max)
QSpinBox *SettingsPage::createSpinBox(pajlada::Settings::Setting<int> &setting,
int min, int max)
{
QSpinBox *w = new QSpinBox;
+4 -2
View File
@@ -20,11 +20,13 @@ public:
void cancel();
QCheckBox *createCheckBox(const QString &text, pajlada::Settings::Setting<bool> &setting);
QCheckBox *createCheckBox(const QString &text,
pajlada::Settings::Setting<bool> &setting);
QComboBox *createComboBox(const QStringList &items,
pajlada::Settings::Setting<QString> &setting);
QLineEdit *createLineEdit(pajlada::Settings::Setting<QString> &setting);
QSpinBox *createSpinBox(pajlada::Settings::Setting<int> &setting, int min = 0, int max = 2500);
QSpinBox *createSpinBox(pajlada::Settings::Setting<int> &setting,
int min = 0, int max = 2500);
virtual void onShow()
{
@@ -18,12 +18,14 @@ SpecialChannelsPage::SpecialChannelsPage()
LayoutCreator<SpecialChannelsPage> layoutCreator(this);
auto layout = layoutCreator.setLayoutType<QVBoxLayout>();
auto mentions = layout.emplace<QGroupBox>("Mentions channel").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>();
auto whispers =
layout.emplace<QGroupBox>("Whispers").setLayoutType<QVBoxLayout>();
{
whispers.emplace<QLabel>("Join /whispers to view your mentions.");
}
+46 -31
View File
@@ -128,19 +128,23 @@ Split::Split(QWidget *parent)
this->header_.updateModerationModeIcon();
this->overlay_->hide();
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
this->setSizePolicy(QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding);
this->managedConnect(modifierStatusChanged, [this](Qt::KeyboardModifiers status) {
if ((status == showSplitOverlayModifiers /*|| status == showAddSplitRegions*/) &&
this->managedConnect(modifierStatusChanged,
[this](Qt::KeyboardModifiers status) {
if ((status == showSplitOverlayModifiers /*|| status == showAddSplitRegions*/) &&
this->isMouseOver_) {
this->overlay_->show();
} else {
this->overlay_->hide();
}
});
this->overlay_->show();
} else {
this->overlay_->hide();
}
});
this->input_.ui_.textEdit->focused.connect([this] { this->focused.invoke(); });
this->input_.ui_.textEdit->focusLost.connect([this] { this->focusLost.invoke(); });
this->input_.ui_.textEdit->focused.connect(
[this] { this->focused.invoke(); });
this->input_.ui_.textEdit->focusLost.connect(
[this] { this->focusLost.invoke(); });
}
Split::~Split()
@@ -199,13 +203,14 @@ void Split::setChannel(IndirectChannel newChannel)
this->header_.updateRoomModes();
});
this->roomModeChangedConnection_ =
tc->roomModesChanged.connect([this] { this->header_.updateRoomModes(); });
this->roomModeChangedConnection_ = tc->roomModesChanged.connect(
[this] { this->header_.updateRoomModes(); });
}
this->indirectChannelChangedConnection_ = newChannel.getChannelChanged().connect([this] { //
QTimer::singleShot(0, [this] { this->setChannel(this->channel_); });
});
this->indirectChannelChangedConnection_ =
newChannel.getChannelChanged().connect([this] { //
QTimer::singleShot(0, [this] { this->setChannel(this->channel_); });
});
this->header_.updateModerationModeIcon();
this->header_.updateChannelText();
@@ -376,7 +381,8 @@ void Split::doChangeChannel()
this->showChangeChannelPopup("Change channel", false, [](bool) {});
auto popup = this->findChildren<QDockWidget *>();
if (popup.size() && popup.at(0)->isVisible() && !popup.at(0)->isFloating()) {
if (popup.size() && popup.at(0)->isVisible() &&
!popup.at(0)->isFloating()) {
popup.at(0)->hide();
showViewerList();
}
@@ -387,8 +393,8 @@ void Split::doPopup()
auto app = getApp();
Window &window = app->windows->createWindow(Window::Type::Popup);
Split *split =
new Split(static_cast<SplitContainer *>(window.getNotebook().getOrAddSelectedPage()));
Split *split = new Split(static_cast<SplitContainer *>(
window.getNotebook().getOrAddSelectedPage()));
split->setChannel(this->getIndirectChannel());
window.getNotebook().getOrAddSelectedPage()->appendSplit(split);
@@ -406,7 +412,8 @@ void Split::openInBrowser()
auto channel = this->getChannel();
if (auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get())) {
QDesktopServices::openUrl("https://twitch.tv/" + twitchChannel->getName());
QDesktopServices::openUrl("https://twitch.tv/" +
twitchChannel->getName());
}
}
@@ -414,7 +421,8 @@ void Split::openInPopupPlayer()
{
ChannelPtr channel = this->getChannel();
if (auto twitchChannel = dynamic_cast<TwitchChannel *>(channel.get())) {
QDesktopServices::openUrl("https://player.twitch.tv/?channel=" + twitchChannel->getName());
QDesktopServices::openUrl("https://player.twitch.tv/?channel=" +
twitchChannel->getName());
}
}
@@ -432,9 +440,11 @@ void Split::showViewerList()
auto viewerDock = new QDockWidget("Viewer List", this);
viewerDock->setAllowedAreas(Qt::LeftDockWidgetArea);
viewerDock->setFeatures(QDockWidget::DockWidgetVerticalTitleBar |
QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable);
viewerDock->resize(0.5 * this->width(),
this->height() - this->header_.height() - this->input_.height());
QDockWidget::DockWidgetClosable |
QDockWidget::DockWidgetFloatable);
viewerDock->resize(
0.5 * this->width(),
this->height() - this->header_.height() - this->input_.height());
viewerDock->move(0, this->header_.height());
auto multiWidget = new QWidget(viewerDock);
@@ -444,8 +454,10 @@ void Split::showViewerList()
auto chattersList = new QListWidget();
auto resultList = new QListWidget();
static QStringList labels = {"Moderators", "Staff", "Admins", "Global Moderators", "Viewers"};
static QStringList jsonLabels = {"moderators", "staff", "admins", "global_mods", "viewers"};
static QStringList labels = {"Moderators", "Staff", "Admins",
"Global Moderators", "Viewers"};
static QStringList jsonLabels = {"moderators", "staff", "admins",
"global_mods", "viewers"};
QList<QListWidgetItem *> labelList;
for (auto &x : labels) {
auto label = new QListWidgetItem(x);
@@ -454,8 +466,9 @@ void Split::showViewerList()
}
auto loadingLabel = new QLabel("Loading...");
auto request = NetworkRequest::twitchRequest("https://tmi.twitch.tv/group/user/" +
this->getChannel()->getName() + "/chatters");
auto request = NetworkRequest::twitchRequest(
"https://tmi.twitch.tv/group/user/" + this->getChannel()->getName() +
"/chatters");
request.setCaller(this);
request.onSuccess([=](auto result) -> Outcome {
@@ -465,7 +478,8 @@ void Split::showViewerList()
loadingLabel->hide();
for (int i = 0; i < jsonLabels.size(); i++) {
chattersList->addItem(labelList.at(i));
foreach (const QJsonValue &v, chattersObj.value(jsonLabels.at(i)).toArray())
foreach (const QJsonValue &v,
chattersObj.value(jsonLabels.at(i)).toArray())
chattersList->addItem(v.toString());
}
@@ -482,7 +496,8 @@ void Split::showViewerList()
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 {
@@ -523,8 +538,8 @@ void Split::showUserInfoPopup(const UserName &user)
auto *userPopup = new UserInfoPopup;
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->move(QCursor::pos() - QPoint(int(150 * this->getScale()),
int(70 * this->getScale())));
userPopup->show();
}
+6 -4
View File
@@ -24,9 +24,10 @@ class SplitContainer;
class SplitOverlay;
class SelectChannelDialog;
// Each ChatWidget consists of three sub-elements that handle their own part of the chat widget:
// ChatWidgetHeader
// - Responsible for rendering which channel the ChatWidget is in, and the menu in the top-left of
// Each ChatWidget consists of three sub-elements that handle their own part of
// the chat widget: ChatWidgetHeader
// - Responsible for rendering which channel the ChatWidget is in, and the
// menu in the top-left of
// the chat widget
// ChatWidgetView
// - Responsible for rendering all chat messages, and the scrollbar
@@ -76,7 +77,8 @@ public:
void setContainer(SplitContainer *container);
static pajlada::Signals::Signal<Qt::KeyboardModifiers> modifierStatusChanged;
static pajlada::Signals::Signal<Qt::KeyboardModifiers>
modifierStatusChanged;
static Qt::KeyboardModifiers modifierStatus;
protected:
+164 -101
View File
@@ -124,10 +124,12 @@ void SplitContainer::appendSplit(Split *split)
void SplitContainer::insertSplit(Split *split, const Position &position)
{
this->insertSplit(split, position.direction_, reinterpret_cast<Node *>(position.relativeNode_));
this->insertSplit(split, position.direction_,
reinterpret_cast<Node *>(position.relativeNode_));
}
void SplitContainer::insertSplit(Split *split, Direction direction, Split *relativeTo)
void SplitContainer::insertSplit(Split *split, Direction direction,
Split *relativeTo)
{
Node *node = this->baseNode_.findNodeContainingSplit(relativeTo);
assert(node != nullptr);
@@ -135,7 +137,8 @@ void SplitContainer::insertSplit(Split *split, Direction direction, Split *relat
this->insertSplit(split, direction, node);
}
void SplitContainer::insertSplit(Split *split, Direction direction, Node *relativeTo)
void SplitContainer::insertSplit(Split *split, Direction direction,
Node *relativeTo)
{
assertInGuiThread();
@@ -170,11 +173,12 @@ void SplitContainer::addSplit(Split *split)
this->refreshTabTitle();
split->getChannelView().tabHighlightRequested.connect([this](HighlightState state) {
if (this->tab_ != nullptr) {
this->tab_->setHighlightState(state);
}
});
split->getChannelView().tabHighlightRequested.connect(
[this](HighlightState state) {
if (this->tab_ != nullptr) {
this->tab_->setHighlightState(state);
}
});
split->focused.connect([this, split] { this->setSelected(split); });
@@ -206,7 +210,8 @@ SplitContainer::Position SplitContainer::releaseSplit(Split *split)
Node *node = this->baseNode_.findNodeContainingSplit(split);
assert(node != nullptr);
this->splits_.erase(std::find(this->splits_.begin(), this->splits_.end(), split));
this->splits_.erase(
std::find(this->splits_.begin(), this->splits_.end(), split));
split->setParent(nullptr);
Position position = node->releaseSplit();
this->layout();
@@ -251,21 +256,24 @@ void SplitContainer::selectSplitRecursive(Node *node, Direction direction)
if (node->parent_->type_ == Node::toContainerType(direction)) {
auto &siblings = node->parent_->children_;
auto it = std::find_if(siblings.begin(), siblings.end(),
[node](const auto &other) { return other.get() == node; });
auto it = std::find_if(
siblings.begin(), siblings.end(),
[node](const auto &other) { return other.get() == node; });
assert(it != siblings.end());
if (direction == Direction::Left || direction == Direction::Above) {
if (it == siblings.begin()) {
this->selectSplitRecursive(node->parent_, direction);
} else {
this->focusSplitRecursive(siblings[it - siblings.begin() - 1].get(), direction);
this->focusSplitRecursive(
siblings[it - siblings.begin() - 1].get(), direction);
}
} else {
if (it->get() == siblings.back().get()) {
this->selectSplitRecursive(node->parent_, direction);
} else {
this->focusSplitRecursive(siblings[it - siblings.begin() + 1].get(), direction);
this->focusSplitRecursive(
siblings[it - siblings.begin() + 1].get(), direction);
}
}
} else {
@@ -285,14 +293,16 @@ void SplitContainer::focusSplitRecursive(Node *node, Direction direction)
case Node::VerticalContainer: {
auto &children = node->children_;
auto it = std::find_if(children.begin(), children.end(), [node](const auto &other) {
return node->preferedFocusTarget_ == other.get();
});
auto it = std::find_if(
children.begin(), children.end(), [node](const auto &other) {
return node->preferedFocusTarget_ == other.get();
});
if (it != children.end()) {
this->focusSplitRecursive(it->get(), direction);
} else {
this->focusSplitRecursive(node->children_.front().get(), direction);
this->focusSplitRecursive(node->children_.front().get(),
direction);
}
} break;
@@ -306,8 +316,9 @@ void SplitContainer::layout()
std::vector<DropRect> _dropRects;
std::vector<ResizeRect> _resizeRects;
this->baseNode_.layout(Split::modifierStatus == showAddSplitRegions || this->isDragging_,
this->getScale(), _dropRects, _resizeRects);
this->baseNode_.layout(
Split::modifierStatus == showAddSplitRegions || this->isDragging_,
this->getScale(), _dropRects, _resizeRects);
this->dropRects_ = _dropRects;
@@ -316,23 +327,26 @@ void SplitContainer::layout()
Node *node = this->baseNode_.findNodeContainingSplit(split);
_dropRects.push_back(DropRect(QRect(g.left(), g.top(), g.width() / 4, g.height()),
Position(node, Direction::Left)));
_dropRects.push_back(
DropRect(QRect(g.left() + g.width() / 4 * 3, g.top(), g.width() / 4, g.height()),
Position(node, Direction::Right)));
DropRect(QRect(g.left(), g.top(), g.width() / 4, g.height()),
Position(node, Direction::Left)));
_dropRects.push_back(DropRect(QRect(g.left() + g.width() / 4 * 3,
g.top(), g.width() / 4, g.height()),
Position(node, Direction::Right)));
_dropRects.push_back(DropRect(QRect(g.left(), g.top(), g.width(), g.height() / 2),
Position(node, Direction::Above)));
_dropRects.push_back(
DropRect(QRect(g.left(), g.top() + g.height() / 2, g.width(), g.height() / 2),
Position(node, Direction::Below)));
DropRect(QRect(g.left(), g.top(), g.width(), g.height() / 2),
Position(node, Direction::Above)));
_dropRects.push_back(DropRect(QRect(g.left(), g.top() + g.height() / 2,
g.width(), g.height() / 2),
Position(node, Direction::Below)));
}
if (this->splits_.empty()) {
QRect g = this->rect();
_dropRects.push_back(DropRect(QRect(g.left(), g.top(), g.width(), g.height()),
Position(nullptr, Direction::Below)));
_dropRects.push_back(
DropRect(QRect(g.left(), g.top(), g.width(), g.height()),
Position(nullptr, Direction::Below)));
}
this->overlay_.setRects(std::move(_dropRects));
@@ -340,7 +354,8 @@ void SplitContainer::layout()
// handle resizeHandles
if (this->resizeHandles_.size() < _resizeRects.size()) {
while (this->resizeHandles_.size() < _resizeRects.size()) {
this->resizeHandles_.push_back(std::make_unique<ResizeHandle>(this));
this->resizeHandles_.push_back(
std::make_unique<ResizeHandle>(this));
}
} else if (this->resizeHandles_.size() > _resizeRects.size()) {
this->resizeHandles_.resize(_resizeRects.size());
@@ -386,7 +401,9 @@ void SplitContainer::mouseReleaseEvent(QMouseEvent *event)
} else {
auto it =
std::find_if(this->dropRects_.begin(), this->dropRects_.end(),
[event](DropRect &rect) { return rect.rect.contains(event->pos()); });
[event](DropRect &rect) {
return rect.rect.contains(event->pos());
});
if (it != this->dropRects_.end()) {
this->insertSplit(new Split(this), it->position);
}
@@ -409,7 +426,8 @@ void SplitContainer::paintEvent(QPaintEvent *)
if (notebook != nullptr) {
if (notebook->getPageCount() > 1) {
text += "\n\nTip: After adding a split you can hold <Alt> to move it or split it "
text += "\n\nTip: After adding a split you can hold <Alt> to "
"move it or split it "
"further.";
}
}
@@ -442,22 +460,28 @@ void SplitContainer::paintEvent(QPaintEvent *)
painter.drawRect(rect);
int s = std::min<int>(dropRect.rect.width(), dropRect.rect.height()) - 12;
int s =
std::min<int>(dropRect.rect.width(), dropRect.rect.height()) - 12;
if (this->theme->isLightTheme()) {
painter.setPen(QColor(0, 0, 0));
} else {
painter.setPen(QColor(255, 255, 255));
}
painter.drawLine(rect.left() + rect.width() / 2 - (s / 2), rect.top() + rect.height() / 2,
rect.left() + rect.width() / 2 + (s / 2), rect.top() + rect.height() / 2);
painter.drawLine(rect.left() + rect.width() / 2, rect.top() + rect.height() / 2 - (s / 2),
rect.left() + rect.width() / 2, rect.top() + rect.height() / 2 + (s / 2));
painter.drawLine(rect.left() + rect.width() / 2 - (s / 2),
rect.top() + rect.height() / 2,
rect.left() + rect.width() / 2 + (s / 2),
rect.top() + rect.height() / 2);
painter.drawLine(rect.left() + rect.width() / 2,
rect.top() + rect.height() / 2 - (s / 2),
rect.left() + rect.width() / 2,
rect.top() + rect.height() / 2 + (s / 2));
}
QBrush accentColor = (QApplication::activeWindow() == this->window()
? this->theme->tabs.selected.backgrounds.regular
: this->theme->tabs.selected.backgrounds.unfocused);
QBrush accentColor =
(QApplication::activeWindow() == this->window()
? this->theme->tabs.selected.backgrounds.regular
: this->theme->tabs.selected.backgrounds.unfocused);
painter.fillRect(0, 0, width(), 1, accentColor);
}
@@ -562,7 +586,8 @@ void SplitContainer::decodeNodeRecusively(QJsonObject &obj, Node *node)
if (type == "split") {
auto *split = new Split(this);
split->setChannel(WindowManager::decodeChannel(obj.value("data").toObject()));
split->setChannel(
WindowManager::decodeChannel(obj.value("data").toObject()));
this->appendSplit(split);
} else if (type == "horizontal" || type == "vertical") {
@@ -570,7 +595,8 @@ void SplitContainer::decodeNodeRecusively(QJsonObject &obj, Node *node)
Direction direction = vertical ? Direction::Below : Direction::Right;
node->type_ = vertical ? Node::VerticalContainer : Node::HorizontalContainer;
node->type_ =
vertical ? Node::VerticalContainer : Node::HorizontalContainer;
for (QJsonValue _val : obj.value("items").toArray()) {
auto _obj = _val.toObject();
@@ -578,7 +604,8 @@ void SplitContainer::decodeNodeRecusively(QJsonObject &obj, Node *node)
auto _type = _obj.value("type");
if (_type == "split") {
auto *split = new Split(this);
split->setChannel(WindowManager::decodeChannel(_obj.value("data").toObject()));
split->setChannel(WindowManager::decodeChannel(
_obj.value("data").toObject()));
Node *_node = new Node();
_node->parent_ = node;
@@ -601,7 +628,8 @@ void SplitContainer::decodeNodeRecusively(QJsonObject &obj, Node *node)
for (int i = 0; i < 2; i++) {
if (node->getChildren().size() < 2) {
auto *split = new Split(this);
split->setChannel(WindowManager::decodeChannel(obj.value("data").toObject()));
split->setChannel(
WindowManager::decodeChannel(obj.value("data").toObject()));
this->insertSplit(split, direction, node);
}
@@ -637,7 +665,8 @@ qreal SplitContainer::Node::getVerticalFlex()
return this->flexV_;
}
const std::vector<std::unique_ptr<SplitContainer::Node>> &SplitContainer::Node::getChildren()
const std::vector<std::unique_ptr<SplitContainer::Node>>
&SplitContainer::Node::getChildren()
{
return this->children_;
}
@@ -663,10 +692,13 @@ bool SplitContainer::Node::isOrContainsNode(SplitContainer::Node *_node)
}
return std::any_of(this->children_.begin(), this->children_.end(),
[_node](std::unique_ptr<Node> &n) { return n->isOrContainsNode(_node); });
[_node](std::unique_ptr<Node> &n) {
return n->isOrContainsNode(_node);
});
}
SplitContainer::Node *SplitContainer::Node::findNodeContainingSplit(Split *_split)
SplitContainer::Node *SplitContainer::Node::findNodeContainingSplit(
Split *_split)
{
if (this->type_ == Type::_Split && this->split_ == _split) {
return this;
@@ -682,7 +714,8 @@ SplitContainer::Node *SplitContainer::Node::findNodeContainingSplit(Split *_spli
return nullptr;
}
void SplitContainer::Node::insertSplitRelative(Split *_split, Direction _direction)
void SplitContainer::Node::insertSplitRelative(Split *_split,
Direction _direction)
{
if (this->parent_ == nullptr) {
switch (this->type_) {
@@ -711,7 +744,8 @@ void SplitContainer::Node::insertSplitRelative(Split *_split, Direction _directi
}
}
void SplitContainer::Node::nestSplitIntoCollection(Split *_split, Direction _direction)
void SplitContainer::Node::nestSplitIntoCollection(Split *_split,
Direction _direction)
{
if (toContainerType(_direction) == this->type_) {
this->children_.emplace_back(new Node(_split, this));
@@ -784,8 +818,9 @@ SplitContainer::Position SplitContainer::Node::releaseSplit()
} else {
auto &siblings = this->parent_->children_;
auto it = std::find_if(begin(siblings), end(siblings),
[this](auto &node) { return this == node.get(); });
auto it =
std::find_if(begin(siblings), end(siblings),
[this](auto &node) { return this == node.get(); });
assert(it != siblings.end());
Position position;
@@ -793,9 +828,11 @@ SplitContainer::Position SplitContainer::Node::releaseSplit()
// delete this and move split to parent
position.relativeNode_ = this->parent_;
if (this->parent_->type_ == Type::VerticalContainer) {
position.direction_ = siblings.begin() == it ? Direction::Above : Direction::Below;
position.direction_ = siblings.begin() == it ? Direction::Above
: Direction::Below;
} else {
position.direction_ = siblings.begin() == it ? Direction::Left : Direction::Right;
position.direction_ =
siblings.begin() == it ? Direction::Left : Direction::Right;
}
Node *_parent = this->parent_;
@@ -803,23 +840,26 @@ SplitContainer::Position SplitContainer::Node::releaseSplit()
std::unique_ptr<Node> &sibling = siblings.front();
_parent->type_ = sibling->type_;
_parent->split_ = sibling->split_;
std::vector<std::unique_ptr<Node>> nodes = std::move(sibling->children_);
std::vector<std::unique_ptr<Node>> nodes =
std::move(sibling->children_);
for (auto &node : nodes) {
node->parent_ = _parent;
}
_parent->children_ = std::move(nodes);
} else {
if (this == siblings.back().get()) {
position.direction_ = this->parent_->type_ == Type::VerticalContainer
? Direction::Below
: Direction::Right;
position.direction_ =
this->parent_->type_ == Type::VerticalContainer
? Direction::Below
: Direction::Right;
siblings.erase(it);
position.relativeNode_ = siblings.back().get();
} else {
position.relativeNode_ = (it + 1)->get();
position.direction_ = this->parent_->type_ == Type::VerticalContainer
? Direction::Above
: Direction::Left;
position.direction_ =
this->parent_->type_ == Type::VerticalContainer
? Direction::Above
: Direction::Left;
siblings.erase(it);
}
}
@@ -840,12 +880,15 @@ qreal SplitContainer::Node::getSize(bool isVertical)
qreal SplitContainer::Node::getChildrensTotalFlex(bool isVertical)
{
return std::accumulate(
this->children_.begin(), this->children_.end(), qreal(0),
[=](qreal val, std::unique_ptr<Node> &node) { return val + node->getFlex(isVertical); });
return std::accumulate(this->children_.begin(), this->children_.end(),
qreal(0),
[=](qreal val, std::unique_ptr<Node> &node) {
return val + node->getFlex(isVertical);
});
}
void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<DropRect> &dropRects,
void SplitContainer::Node::layout(bool addSpacing, float _scale,
std::vector<DropRect> &dropRects,
std::vector<ResizeRect> &resizeRects)
{
for (std::unique_ptr<Node> &node : this->children_) {
@@ -856,7 +899,8 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<Dro
switch (this->type_) {
case Node::_Split: {
QRect rect = this->geometry_.toRect();
this->split_->setGeometry(rect.marginsRemoved(QMargins(1, 1, 1, 1)));
this->split_->setGeometry(
rect.marginsRemoved(QMargins(1, 1, 1, 1)));
} break;
case Node::VerticalContainer:
case Node::HorizontalContainer: {
@@ -869,7 +913,8 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<Dro
qreal totalSize = std::accumulate(
this->children_.begin(), this->children_.end(), qreal(0),
[=](int val, std::unique_ptr<Node> &node) {
return val + std::max<qreal>(this->getSize(isVertical) / totalFlex *
return val + std::max<qreal>(this->getSize(isVertical) /
totalFlex *
node->getFlex(isVertical),
minSize);
});
@@ -879,8 +924,8 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<Dro
// add spacing if reqested
if (addSpacing) {
qreal offset =
std::min<qreal>(this->getSize(!isVertical) * 0.1, qreal(_scale * 24));
qreal offset = std::min<qreal>(this->getSize(!isVertical) * 0.1,
qreal(_scale * 24));
// droprect left / above
dropRects.emplace_back(
@@ -888,18 +933,21 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<Dro
isVertical ? offset : this->geometry_.width(),
isVertical ? this->geometry_.height() : offset)
.toRect(),
Position(this, isVertical ? Direction::Left : Direction::Above));
Position(this,
isVertical ? Direction::Left : Direction::Above));
// droprect right / below
if (isVertical) {
dropRects.emplace_back(
QRectF(this->geometry_.right() - offset, this->geometry_.top(), offset,
QRectF(this->geometry_.right() - offset,
this->geometry_.top(), offset,
this->geometry_.height())
.toRect(),
Position(this, Direction::Right));
} else {
dropRects.emplace_back(
QRectF(this->geometry_.left(), this->geometry_.bottom() - offset,
QRectF(this->geometry_.left(),
this->geometry_.bottom() - offset,
this->geometry_.width(), offset)
.toRect(),
Position(this, Direction::Below));
@@ -923,15 +971,16 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<Dro
if (isVertical) {
rect.setTop(pos);
rect.setHeight(
std::max<qreal>(this->geometry_.height() / totalFlex * child->flexV_,
std::max<qreal>(this->geometry_.height() / totalFlex *
child->flexV_,
minSize) *
sizeMultiplier);
} else {
rect.setLeft(pos);
rect.setWidth(
std::max<qreal>(this->geometry_.width() / totalFlex * child->flexH_,
minSize) *
sizeMultiplier);
rect.setWidth(std::max<qreal>(this->geometry_.width() /
totalFlex * child->flexH_,
minSize) *
sizeMultiplier);
}
child->geometry_ = rect;
@@ -941,20 +990,24 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<Dro
// add resize rect
if (child != this->children_.front()) {
QRectF r = isVertical
? QRectF(this->geometry_.left(), child->geometry_.top() - 4,
this->geometry_.width(), 8)
: QRectF(child->geometry_.left() - 4, this->geometry_.top(), 8,
this->geometry_.height());
resizeRects.push_back(ResizeRect(r.toRect(), child.get(), isVertical));
QRectF r = isVertical ? QRectF(this->geometry_.left(),
child->geometry_.top() - 4,
this->geometry_.width(), 8)
: QRectF(child->geometry_.left() - 4,
this->geometry_.top(), 8,
this->geometry_.height());
resizeRects.push_back(
ResizeRect(r.toRect(), child.get(), isVertical));
}
// normalize flex
if (isVertical) {
child->flexV_ = child->flexV_ / totalFlex * this->children_.size();
child->flexV_ =
child->flexV_ / totalFlex * this->children_.size();
child->flexH_ = 1;
} else {
child->flexH_ = child->flexH_ / totalFlex * this->children_.size();
child->flexH_ =
child->flexH_ / totalFlex * this->children_.size();
child->flexV_ = 1;
}
}
@@ -964,8 +1017,9 @@ void SplitContainer::Node::layout(bool addSpacing, float _scale, std::vector<Dro
SplitContainer::Node::Type SplitContainer::Node::toContainerType(Direction _dir)
{
return _dir == Direction::Left || _dir == Direction::Right ? Type::HorizontalContainer
: Type::VerticalContainer;
return _dir == Direction::Left || _dir == Direction::Right
? Type::HorizontalContainer
: Type::VerticalContainer;
}
//
@@ -981,7 +1035,8 @@ SplitContainer::DropOverlay::DropOverlay(SplitContainer *_parent)
this->setAcceptDrops(true);
}
void SplitContainer::DropOverlay::setRects(std::vector<SplitContainer::DropRect> _rects)
void SplitContainer::DropOverlay::setRects(
std::vector<SplitContainer::DropRect> _rects)
{
this->rects_ = std::move(_rects);
}
@@ -1074,12 +1129,15 @@ void SplitContainer::ResizeHandle::paintEvent(QPaintEvent *)
QPainter painter(this);
painter.setPen(QPen(getApp()->themes->splits.resizeHandle, 2));
painter.fillRect(this->rect(), getApp()->themes->splits.resizeHandleBackground);
painter.fillRect(this->rect(),
getApp()->themes->splits.resizeHandleBackground);
if (this->vertical_) {
painter.drawLine(0, this->height() / 2, this->width(), this->height() / 2);
painter.drawLine(0, this->height() / 2, this->width(),
this->height() / 2);
} else {
painter.drawLine(this->width() / 2, 0, this->width() / 2, this->height());
painter.drawLine(this->width() / 2, 0, this->width() / 2,
this->height());
}
}
@@ -1103,29 +1161,34 @@ void SplitContainer::ResizeHandle::mouseMoveEvent(QMouseEvent *event)
assert(node->parent_ != nullptr);
auto &siblings = node->parent_->getChildren();
auto it =
std::find_if(siblings.begin(), siblings.end(),
[this](const std::unique_ptr<Node> &n) { return n.get() == this->node; });
auto it = std::find_if(siblings.begin(), siblings.end(),
[this](const std::unique_ptr<Node> &n) {
return n.get() == this->node;
});
assert(it != siblings.end());
Node *before = siblings[it - siblings.begin() - 1].get();
QPoint topLeft = this->parent->mapToGlobal(before->geometry_.topLeft().toPoint());
QPoint bottomRight = this->parent->mapToGlobal(this->node->geometry_.bottomRight().toPoint());
QPoint topLeft =
this->parent->mapToGlobal(before->geometry_.topLeft().toPoint());
QPoint bottomRight = this->parent->mapToGlobal(
this->node->geometry_.bottomRight().toPoint());
int globalX = topLeft.x() > event->globalX()
? topLeft.x()
: (bottomRight.x() < event->globalX() ? bottomRight.x() : event->globalX());
: (bottomRight.x() < event->globalX() ? bottomRight.x()
: event->globalX());
int globalY = topLeft.y() > event->globalY()
? topLeft.y()
: (bottomRight.y() < event->globalY() ? bottomRight.y() : event->globalY());
: (bottomRight.y() < event->globalY() ? bottomRight.y()
: event->globalY());
QPoint mousePoint(globalX, globalY);
if (this->vertical_) {
qreal totalFlexV = this->node->flexV_ + before->flexV_;
before->flexV_ =
totalFlexV * (mousePoint.y() - topLeft.y()) / (bottomRight.y() - topLeft.y());
before->flexV_ = totalFlexV * (mousePoint.y() - topLeft.y()) /
(bottomRight.y() - topLeft.y());
this->node->flexV_ = totalFlexV - before->flexV_;
this->parent->layout();
@@ -1134,8 +1197,8 @@ void SplitContainer::ResizeHandle::mouseMoveEvent(QMouseEvent *event)
this->move(this->x(), int(before->geometry_.bottom() - 4));
} else {
qreal totalFlexH = this->node->flexH_ + before->flexH_;
before->flexH_ =
totalFlexH * (mousePoint.x() - topLeft.x()) / (bottomRight.x() - topLeft.x());
before->flexH_ = totalFlexH * (mousePoint.x() - topLeft.x()) /
(bottomRight.x() - topLeft.x());
this->node->flexH_ = totalFlexH - before->flexH_;
this->parent->layout();
+6 -4
View File
@@ -23,8 +23,8 @@ class QJsonObject;
namespace chatterino {
//
// Note: This class is a spaghetti container. There is a lot of spaghetti code inside but it doesn't
// expose any of it publicly.
// Note: This class is a spaghetti container. There is a lot of spaghetti code
// inside but it doesn't expose any of it publicly.
//
class SplitContainer : public BaseWidget, pajlada::Signals::SignalHolder
@@ -103,7 +103,8 @@ public:
qreal getFlex(bool isVertical);
qreal getSize(bool isVertical);
qreal getChildrensTotalFlex(bool isVertical);
void layout(bool addSpacing, float _scale, std::vector<DropRect> &dropRects_,
void layout(bool addSpacing, float _scale,
std::vector<DropRect> &dropRects_,
std::vector<ResizeRect> &resizeRects);
static Type toContainerType(Direction _dir);
@@ -171,7 +172,8 @@ public:
void appendSplit(Split *split);
void insertSplit(Split *split, const Position &position);
void insertSplit(Split *split, Direction direction, Split *relativeTo);
void insertSplit(Split *split, Direction direction, Node *relativeTo = nullptr);
void insertSplit(Split *split, Direction direction,
Node *relativeTo = nullptr);
Position releaseSplit(Split *split);
Position deleteSplit(Split *split);
+117 -88
View File
@@ -39,48 +39,58 @@ SplitHeader::SplitHeader(Split *_split)
{
// channel name label
auto title = layout.emplace<Label>().assign(&this->titleLabel);
title->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
title->setSizePolicy(QSizePolicy::MinimumExpanding,
QSizePolicy::Preferred);
title->setCentered(true);
title->setHasOffset(false);
// mode button
auto mode = layout.emplace<RippleEffectLabel>(nullptr).assign(&this->modeButton_);
auto mode = layout.emplace<RippleEffectLabel>(nullptr).assign(
&this->modeButton_);
mode->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
mode->hide();
this->setupModeLabel(*mode);
QObject::connect(mode.getElement(), &RippleEffectLabel::clicked, this, [this] {
QTimer::singleShot(80, this, [&, this] {
ChannelPtr _channel = this->split_->getChannel();
if (_channel->hasModRights()) {
this->modeMenu_.popup(QCursor::pos());
}
QObject::connect(
mode.getElement(), &RippleEffectLabel::clicked, this, [this] {
QTimer::singleShot(80, this, [&, this] {
ChannelPtr _channel = this->split_->getChannel();
if (_channel->hasModRights()) {
this->modeMenu_.popup(QCursor::pos());
}
});
});
});
// moderation mode
auto moderator = layout.emplace<RippleEffectButton>(this).assign(&this->moderationButton_);
auto moderator = layout.emplace<RippleEffectButton>(this).assign(
&this->moderationButton_);
QObject::connect(moderator.getElement(), &RippleEffectButton::clicked, this,
[this, moderator]() mutable {
this->split_->setModerationMode(!this->split_->getModerationMode());
QObject::connect(
moderator.getElement(), &RippleEffectButton::clicked, this,
[this, moderator]() mutable {
this->split_->setModerationMode(
!this->split_->getModerationMode());
moderator->setDim(!this->split_->getModerationMode());
});
moderator->setDim(!this->split_->getModerationMode());
});
this->updateModerationModeIcon();
// dropdown label
auto dropdown = layout.emplace<RippleEffectButton>(this).assign(&this->dropdownButton_);
auto dropdown = layout.emplace<RippleEffectButton>(this).assign(
&this->dropdownButton_);
dropdown->setMouseTracking(true);
// dropdown->setPixmap(*app->resources->splitHeaderContext->getPixmap());
// dropdown->setScaleIndependantSize(23, 23);
this->addDropdownItems(dropdown.getElement());
QObject::connect(dropdown.getElement(), &RippleEffectButton::leftMousePress, this, [this] {
QTimer::singleShot(80, [&, this] { this->dropdownMenu_.popup(QCursor::pos()); });
});
QObject::connect(dropdown.getElement(),
&RippleEffectButton::leftMousePress, this, [this] {
QTimer::singleShot(80, [&, this] {
this->dropdownMenu_.popup(QCursor::pos());
});
});
}
// ---- misc
@@ -166,53 +176,57 @@ void SplitHeader::updateRoomModes()
void SplitHeader::setupModeLabel(RippleEffectLabel &label)
{
this->managedConnections_.push_back(this->modeUpdateRequested_.connect([this, &label] {
auto twitchChannel = dynamic_cast<TwitchChannel *>(this->split_->getChannel().get());
this->managedConnections_.push_back(
this->modeUpdateRequested_.connect([this, &label] {
auto twitchChannel =
dynamic_cast<TwitchChannel *>(this->split_->getChannel().get());
// return if the channel is not a twitch channel
if (twitchChannel == nullptr) {
label.hide();
return;
}
// set lable enabled
label.setEnable(twitchChannel->hasModRights());
// set the label text
QString text;
{
auto roomModes = twitchChannel->accessRoomModes();
if (roomModes->r9k) text += "r9k, ";
if (roomModes->slowMode)
text += QString("slow(%1), ").arg(QString::number(roomModes->slowMode));
if (roomModes->emoteOnly) text += "emote, ";
if (roomModes->submode) text += "sub, ";
}
if (text.length() > 2) {
text = text.mid(0, text.size() - 2);
}
if (text.isEmpty()) {
if (twitchChannel->hasModRights()) {
label.getLabel().setText("none");
label.show();
} else {
// return if the channel is not a twitch channel
if (twitchChannel == nullptr) {
label.hide();
}
} else {
static QRegularExpression commaReplacement("^.+?, .+?,( ).+$");
QRegularExpressionMatch match = commaReplacement.match(text);
if (match.hasMatch()) {
text = text.mid(0, match.capturedStart(1)) + '\n' + text.mid(match.capturedEnd(1));
return;
}
label.getLabel().setText(text);
label.show();
}
}));
// set lable enabled
label.setEnable(twitchChannel->hasModRights());
// set the label text
QString text;
{
auto roomModes = twitchChannel->accessRoomModes();
if (roomModes->r9k) text += "r9k, ";
if (roomModes->slowMode)
text += QString("slow(%1), ")
.arg(QString::number(roomModes->slowMode));
if (roomModes->emoteOnly) text += "emote, ";
if (roomModes->submode) text += "sub, ";
}
if (text.length() > 2) {
text = text.mid(0, text.size() - 2);
}
if (text.isEmpty()) {
if (twitchChannel->hasModRights()) {
label.getLabel().setText("none");
label.show();
} else {
label.hide();
}
} else {
static QRegularExpression commaReplacement("^.+?, .+?,( ).+$");
QRegularExpressionMatch match = commaReplacement.match(text);
if (match.hasMatch()) {
text = text.mid(0, match.capturedStart(1)) + '\n' +
text.mid(match.capturedEnd(1));
}
label.getLabel().setText(text);
label.show();
}
}));
}
void SplitHeader::addModeActions(QMenu &menu)
@@ -234,7 +248,8 @@ void SplitHeader::addModeActions(QMenu &menu)
this->managedConnections_.push_back(this->modeUpdateRequested_.connect( //
[this, setSub, setEmote, setSlow, setR9k]() {
auto twitchChannel = dynamic_cast<TwitchChannel *>(this->split_->getChannel().get());
auto twitchChannel =
dynamic_cast<TwitchChannel *>(this->split_->getChannel().get());
if (twitchChannel == nullptr) {
this->modeButton_->hide();
return;
@@ -260,11 +275,13 @@ void SplitHeader::addModeActions(QMenu &menu)
this->split_->getChannel().get()->sendMessage(command);
};
QObject::connect(setSub, &QAction::triggered, this,
[setSub, toggle]() mutable { toggle("/subscribers", setSub); });
QObject::connect(
setSub, &QAction::triggered, this,
[setSub, toggle]() mutable { toggle("/subscribers", setSub); });
QObject::connect(setEmote, &QAction::triggered, this,
[setEmote, toggle]() mutable { toggle("/emoteonly", setEmote); });
QObject::connect(
setEmote, &QAction::triggered, this,
[setEmote, toggle]() mutable { toggle("/emoteonly", setEmote); });
QObject::connect(setSlow, &QAction::triggered, this, [setSlow, this]() {
if (!setSlow->isChecked()) {
@@ -273,17 +290,19 @@ void SplitHeader::addModeActions(QMenu &menu)
return;
};
bool ok;
int slowSec =
QInputDialog::getInt(this, "", "Seconds:", 10, 0, 500, 1, &ok, Qt::FramelessWindowHint);
int slowSec = QInputDialog::getInt(this, "", "Seconds:", 10, 0, 500, 1,
&ok, Qt::FramelessWindowHint);
if (ok) {
this->split_->getChannel().get()->sendMessage(QString("/slow %1").arg(slowSec));
this->split_->getChannel().get()->sendMessage(
QString("/slow %1").arg(slowSec));
} else {
setSlow->setChecked(false);
}
});
QObject::connect(setR9k, &QAction::triggered, this,
[setR9k, toggle]() mutable { toggle("/r9kbeta", setR9k); });
QObject::connect(
setR9k, &QAction::triggered, this,
[setR9k, toggle]() mutable { toggle("/r9kbeta", setR9k); });
}
void SplitHeader::initializeChannelSignals()
@@ -295,9 +314,10 @@ void SplitHeader::initializeChannelSignals()
TwitchChannel *twitchChannel = dynamic_cast<TwitchChannel *>(channel.get());
if (twitchChannel) {
this->managedConnections_.emplace_back(twitchChannel->liveStatusChanged.connect([this]() {
this->updateChannelText(); //
}));
this->managedConnections_.emplace_back(
twitchChannel->liveStatusChanged.connect([this]() {
this->updateChannelText(); //
}));
}
}
@@ -332,9 +352,10 @@ void SplitHeader::updateChannelText()
this->isLive_ = true;
this->tooltip_ = "<style>.center { text-align: center; }</style>"
"<p class = \"center\">" +
streamStatus->title + "<br><br>" + streamStatus->game + "<br>" +
(streamStatus->rerun ? "Vod-casting" : "Live") + " for " +
streamStatus->uptime + " with " +
streamStatus->title + "<br><br>" +
streamStatus->game + "<br>" +
(streamStatus->rerun ? "Vod-casting" : "Live") +
" for " + streamStatus->uptime + " with " +
QString::number(streamStatus->viewerCount) +
" viewers"
"</p>";
@@ -346,7 +367,8 @@ void SplitHeader::updateChannelText()
title += " (live)";
}
if (getSettings()->showViewerCount) {
title += " - " + QString::number(streamStatus->viewerCount) + " viewers";
title += " - " + QString::number(streamStatus->viewerCount) +
" viewers";
}
if (getSettings()->showTitle) {
title += " - " + streamStatus->title;
@@ -374,9 +396,10 @@ void SplitHeader::updateModerationModeIcon()
{
auto app = getApp();
this->moderationButton_->setPixmap(this->split_->getModerationMode()
? app->resources->buttons.modModeEnabled
: app->resources->buttons.modModeDisabled);
this->moderationButton_->setPixmap(
this->split_->getModerationMode()
? app->resources->buttons.modModeEnabled
: app->resources->buttons.modModeDisabled);
bool modButtonVisible = false;
ChannelPtr channel = this->split_->getChannel();
@@ -427,7 +450,8 @@ void SplitHeader::mouseReleaseEvent(QMouseEvent *event)
TooltipWidget *widget = new TooltipWidget();
widget->setText("Double click or press <Ctrl+R> to change the channel.\nClick and "
widget->setText("Double click or press <Ctrl+R> to change the "
"channel.\nClick and "
"drag to move the split.");
widget->setAttribute(Qt::WA_DeleteOnClose);
widget->move(pos);
@@ -448,8 +472,10 @@ void SplitHeader::mouseReleaseEvent(QMouseEvent *event)
void SplitHeader::mouseMoveEvent(QMouseEvent *event)
{
if (this->dragging_) {
if (std::abs(this->dragStart_.x() - event->pos().x()) > int(12 * this->getScale()) ||
std::abs(this->dragStart_.y() - event->pos().y()) > int(12 * this->getScale())) {
if (std::abs(this->dragStart_.x() - event->pos().x()) >
int(12 * this->getScale()) ||
std::abs(this->dragStart_.y() - event->pos().y()) >
int(12 * this->getScale())) {
this->split_->drag();
this->dragging_ = false;
}
@@ -468,7 +494,8 @@ void SplitHeader::enterEvent(QEvent *event)
{
if (!this->tooltip_.isEmpty()) {
auto tooltipWidget = TooltipWidget::getInstance();
tooltipWidget->moveTo(this, this->mapToGlobal(this->rect().bottomLeft()), false);
tooltipWidget->moveTo(
this, this->mapToGlobal(this->rect().bottomLeft()), false);
tooltipWidget->setText(this->tooltip_);
tooltipWidget->show();
tooltipWidget->raise();
@@ -493,7 +520,8 @@ void SplitHeader::themeChangedEvent()
QPalette palette;
if (this->split_->hasFocus()) {
palette.setColor(QPalette::Foreground, this->theme->splits.header.focusedText);
palette.setColor(QPalette::Foreground,
this->theme->splits.header.focusedText);
} else {
palette.setColor(QPalette::Foreground, this->theme->splits.header.text);
}
@@ -501,7 +529,8 @@ void SplitHeader::themeChangedEvent()
if (this->theme->isLightTheme()) {
this->dropdownButton_->setPixmap(getApp()->resources->buttons.menuDark);
} else {
this->dropdownButton_->setPixmap(getApp()->resources->buttons.menuLight);
this->dropdownButton_->setPixmap(
getApp()->resources->buttons.menuLight);
}
this->titleLabel->setPalette(palette);
+63 -39
View File
@@ -22,11 +22,13 @@ SplitInput::SplitInput(Split *_chatWidget)
{
this->initLayout();
auto completer = new QCompleter(&this->split_->getChannel().get()->completionModel);
auto completer =
new QCompleter(&this->split_->getChannel().get()->completionModel);
this->ui_.textEdit->setCompleter(completer);
this->split_->channelChanged.connect([this] {
auto completer = new QCompleter(&this->split_->getChannel()->completionModel);
auto completer =
new QCompleter(&this->split_->getChannel()->completionModel);
this->ui_.textEdit->setCompleter(completer);
});
@@ -41,10 +43,12 @@ void SplitInput::initLayout()
LayoutCreator<SplitInput> layoutCreator(this);
auto layout =
layoutCreator.setLayoutType<QHBoxLayout>().withoutMargin().assign(&this->ui_.hbox);
layoutCreator.setLayoutType<QHBoxLayout>().withoutMargin().assign(
&this->ui_.hbox);
// input
auto textEdit = layout.emplace<ResizingTextEdit>().assign(&this->ui_.textEdit);
auto textEdit =
layout.emplace<ResizingTextEdit>().assign(&this->ui_.textEdit);
connect(textEdit.getElement(), &ResizingTextEdit::textChanged, this,
&SplitInput::editTextChanged);
@@ -52,7 +56,8 @@ void SplitInput::initLayout()
auto box = layout.emplace<QVBoxLayout>().withoutMargin();
box->setSpacing(0);
{
auto textEditLength = box.emplace<QLabel>().assign(&this->ui_.textEditLength);
auto textEditLength =
box.emplace<QLabel>().assign(&this->ui_.textEditLength);
textEditLength->setAlignment(Qt::AlignRight);
box->addStretch(1);
@@ -64,39 +69,46 @@ void SplitInput::initLayout()
// ---- misc
// set edit font
this->ui_.textEdit->setFont(app->fonts->getFont(Fonts::Type::ChatMedium, this->getScale()));
this->ui_.textEdit->setFont(
app->fonts->getFont(Fonts::Type::ChatMedium, this->getScale()));
this->managedConnections_.push_back(app->fonts->fontChanged.connect([=]() {
this->ui_.textEdit->setFont(app->fonts->getFont(Fonts::Type::ChatMedium, this->getScale()));
this->ui_.textEdit->setFont(
app->fonts->getFont(Fonts::Type::ChatMedium, this->getScale()));
}));
// open emote popup
QObject::connect(this->ui_.emoteButton, &RippleEffectLabel::clicked, [this] {
if (!this->emotePopup_) {
this->emotePopup_ = std::make_unique<EmotePopup>();
this->emotePopup_->linkClicked.connect([this](const Link &link) {
if (link.type == Link::InsertText) {
this->insertText(link.value + " ");
}
});
}
QObject::connect(
this->ui_.emoteButton, &RippleEffectLabel::clicked, [this] {
if (!this->emotePopup_) {
this->emotePopup_ = std::make_unique<EmotePopup>();
this->emotePopup_->linkClicked.connect(
[this](const Link &link) {
if (link.type == Link::InsertText) {
this->insertText(link.value + " ");
}
});
}
this->emotePopup_->resize(int(300 * this->emotePopup_->getScale()),
int(500 * this->emotePopup_->getScale()));
this->emotePopup_->loadChannel(this->split_->getChannel());
this->emotePopup_->show();
});
this->emotePopup_->resize(int(300 * this->emotePopup_->getScale()),
int(500 * this->emotePopup_->getScale()));
this->emotePopup_->loadChannel(this->split_->getChannel());
this->emotePopup_->show();
});
// clear channelview selection when selecting in the input
QObject::connect(this->ui_.textEdit, &QTextEdit::copyAvailable, [this](bool available) {
if (available) {
this->split_->view_.clearSelection();
}
});
QObject::connect(this->ui_.textEdit, &QTextEdit::copyAvailable,
[this](bool available) {
if (available) {
this->split_->view_.clearSelection();
}
});
// textEditLength visibility
app->settings->showMessageLength.connect(
[this](const bool &value, auto) { this->ui_.textEditLength->setHidden(!value); },
[this](const bool &value, auto) {
this->ui_.textEditLength->setHidden(!value);
},
this->managedConnections_);
}
@@ -107,7 +119,8 @@ void SplitInput::scaleChangedEvent(float scale)
// set maximum height
this->setMaximumHeight(int(150 * this->getScale()));
this->ui_.textEdit->setFont(getApp()->fonts->getFont(FontStyle::ChatMedium, this->getScale()));
this->ui_.textEdit->setFont(
getApp()->fonts->getFont(FontStyle::ChatMedium, this->getScale()));
}
void SplitInput::themeChangedEvent()
@@ -121,7 +134,8 @@ void SplitInput::themeChangedEvent()
this->ui_.textEdit->setStyleSheet(this->theme->splits.input.styleSheet);
this->ui_.hbox->setMargin(int((this->theme->isLightTheme() ? 4 : 2) * this->getScale()));
this->ui_.hbox->setMargin(
int((this->theme->isLightTheme() ? 4 : 2) * this->getScale()));
this->ui_.emoteButton->getLabel().setStyleSheet("color: #000");
}
@@ -189,7 +203,8 @@ void SplitInput::installKeyPressedEvent()
}
this->prevIndex_--;
this->ui_.textEdit->setText(this->prevMsg_.at(this->prevIndex_));
this->ui_.textEdit->setText(
this->prevMsg_.at(this->prevIndex_));
QTextCursor cursor = this->ui_.textEdit->textCursor();
cursor.movePosition(QTextCursor::End);
@@ -210,7 +225,8 @@ void SplitInput::installKeyPressedEvent()
if (this->prevIndex_ != (this->prevMsg_.size() - 1) &&
this->prevIndex_ != this->prevMsg_.size()) {
this->prevIndex_++;
this->ui_.textEdit->setText(this->prevMsg_.at(this->prevIndex_));
this->ui_.textEdit->setText(
this->prevMsg_.at(this->prevIndex_));
} else {
this->prevIndex_ = this->prevMsg_.size();
this->ui_.textEdit->setText(this->currMsg_);
@@ -238,21 +254,27 @@ void SplitInput::installKeyPressedEvent()
}
} else if (event->key() == Qt::Key_Tab) {
if (event->modifiers() == Qt::ControlModifier) {
SplitContainer *page = static_cast<SplitContainer *>(this->split_->parentWidget());
SplitContainer *page =
static_cast<SplitContainer *>(this->split_->parentWidget());
Notebook *notebook = static_cast<Notebook *>(page->parentWidget());
Notebook *notebook =
static_cast<Notebook *>(page->parentWidget());
notebook->selectNextTab();
}
} else if (event->key() == Qt::Key_Backtab) {
if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) {
SplitContainer *page = static_cast<SplitContainer *>(this->split_->parentWidget());
if (event->modifiers() ==
(Qt::ControlModifier | Qt::ShiftModifier)) {
SplitContainer *page =
static_cast<SplitContainer *>(this->split_->parentWidget());
Notebook *notebook = static_cast<Notebook *>(page->parentWidget());
Notebook *notebook =
static_cast<Notebook *>(page->parentWidget());
notebook->selectPreviousTab();
}
} else if (event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier) {
} else if (event->key() == Qt::Key_C &&
event->modifiers() == Qt::ControlModifier) {
if (this->split_->view_.hasSelection()) {
this->split_->copyToClipboard();
event->accept();
@@ -303,7 +325,8 @@ void SplitInput::editTextChanged()
static QRegularExpression spaceRegex("\\s\\s+");
text = text.replace(spaceRegex, " ");
text = app->commands->execCommand(text, this->split_->getChannel(), true);
text =
app->commands->execCommand(text, this->split_->getChannel(), true);
}
QString labelText;
@@ -340,7 +363,8 @@ void SplitInput::paintEvent(QPaintEvent *)
}
// int offset = 2;
// painter.fillRect(offset, this->height() - offset, this->width() - 2 * offset, 1,
// painter.fillRect(offset, this->height() - offset, this->width() - 2 *
// offset, 1,
// getApp()->themes->splits.input.focusedLine);
}
+26 -13
View File
@@ -30,10 +30,14 @@ SplitOverlay::SplitOverlay(Split *parent)
layout->setColumnStretch(3, 1);
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());
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));
@@ -103,7 +107,8 @@ void SplitOverlay::paintEvent(QPaintEvent *)
} break;
case SplitRight: {
rect = QRect(this->width() / 2, 0, this->width() / 2, this->height());
rect =
QRect(this->width() / 2, 0, this->width() / 2, this->height());
} break;
case SplitUp: {
@@ -111,7 +116,8 @@ void SplitOverlay::paintEvent(QPaintEvent *)
} break;
case SplitDown: {
rect = QRect(0, this->height() / 2, this->width(), this->height() / 2);
rect =
QRect(0, this->height() / 2, this->width(), this->height() / 2);
} break;
default:;
@@ -145,24 +151,28 @@ void SplitOverlay::mouseMoveEvent(QMouseEvent *event)
// qDebug() << QGuiApplication::queryKeyboardModifiers();
// if ((QGuiApplication::queryKeyboardModifiers() & Qt::AltModifier) == Qt::AltModifier) {
// if ((QGuiApplication::queryKeyboardModifiers() & Qt::AltModifier) ==
// Qt::AltModifier) {
// this->hide();
// }
}
SplitOverlay::ButtonEventFilter::ButtonEventFilter(SplitOverlay *_parent, HoveredElement _element)
SplitOverlay::ButtonEventFilter::ButtonEventFilter(SplitOverlay *_parent,
HoveredElement _element)
: QObject(_parent)
, parent(_parent)
, hoveredElement(_element)
{
}
bool SplitOverlay::ButtonEventFilter::eventFilter(QObject *watched, QEvent *event)
bool SplitOverlay::ButtonEventFilter::eventFilter(QObject *watched,
QEvent *event)
{
switch (event->type()) {
case QEvent::Enter: {
QGraphicsOpacityEffect *effect =
dynamic_cast<QGraphicsOpacityEffect *>(((QWidget *)watched)->graphicsEffect());
dynamic_cast<QGraphicsOpacityEffect *>(
((QWidget *)watched)->graphicsEffect());
if (effect != nullptr) {
effect->setOpacity(0.99);
@@ -173,7 +183,8 @@ bool SplitOverlay::ButtonEventFilter::eventFilter(QObject *watched, QEvent *even
} break;
case QEvent::Leave: {
QGraphicsOpacityEffect *effect =
dynamic_cast<QGraphicsOpacityEffect *>(((QWidget *)watched)->graphicsEffect());
dynamic_cast<QGraphicsOpacityEffect *>(
((QWidget *)watched)->graphicsEffect());
if (effect != nullptr) {
effect->setOpacity(0.7);
@@ -193,12 +204,14 @@ bool SplitOverlay::ButtonEventFilter::eventFilter(QObject *watched, QEvent *even
} break;
case QEvent::MouseButtonRelease: {
if (this->hoveredElement != HoveredElement::SplitMove) {
SplitContainer *container = this->parent->split_->getContainer();
SplitContainer *container =
this->parent->split_->getContainer();
if (container != nullptr) {
auto *_split = new Split(container);
auto dir = SplitContainer::Direction(this->hoveredElement +
SplitContainer::Left - SplitLeft);
SplitContainer::Left -
SplitLeft);
container->insertSplit(_split, dir, this->parent->split_);
this->parent->hide();
}
+8 -1
View File
@@ -23,7 +23,14 @@ protected:
private:
// fourtf: !!! preserve the order of left, up, right and down
enum HoveredElement { None, SplitMove, SplitLeft, SplitUp, SplitRight, SplitDown };
enum HoveredElement {
None,
SplitMove,
SplitLeft,
SplitUp,
SplitRight,
SplitDown
};
class ButtonEventFilter : public QObject
{