changed to 80 max column
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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();
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 }");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
//}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user