diff --git a/chatterino.pro b/chatterino.pro
index bf3578cb0..6800fb8a2 100644
--- a/chatterino.pro
+++ b/chatterino.pro
@@ -194,7 +194,8 @@ SOURCES += \
src/widgets/helper/editablemodelview.cpp \
src/controllers/accounts/accountcontroller.cpp \
src/controllers/accounts/accountmodel.cpp \
- src/controllers/accounts/account.cpp
+ src/controllers/accounts/account.cpp \
+ src/widgets/helper/splitoverlay.cpp
HEADERS += \
src/precompiled_header.hpp \
@@ -336,7 +337,8 @@ HEADERS += \
src/controllers/accounts/accountcontroller.hpp \
src/controllers/accounts/accountmodel.hpp \
src/controllers/accounts/account.hpp \
- src/util/sharedptrelementless.hpp
+ src/util/sharedptrelementless.hpp \
+ src/widgets/helper/splitoverlay.hpp
RESOURCES += \
resources/resources.qrc
diff --git a/resources/images/split/splitdown.png b/resources/images/split/splitdown.png
new file mode 100644
index 000000000..3891ca398
Binary files /dev/null and b/resources/images/split/splitdown.png differ
diff --git a/resources/images/split/splitleft.png b/resources/images/split/splitleft.png
new file mode 100644
index 000000000..8d1cb0e19
Binary files /dev/null and b/resources/images/split/splitleft.png differ
diff --git a/resources/images/split/splitmove.png b/resources/images/split/splitmove.png
new file mode 100644
index 000000000..82bf5382b
Binary files /dev/null and b/resources/images/split/splitmove.png differ
diff --git a/resources/images/split/splitright.png b/resources/images/split/splitright.png
new file mode 100644
index 000000000..173537331
Binary files /dev/null and b/resources/images/split/splitright.png differ
diff --git a/resources/images/split/splitup.png b/resources/images/split/splitup.png
new file mode 100644
index 000000000..a9cc0f30e
Binary files /dev/null and b/resources/images/split/splitup.png differ
diff --git a/resources/resources.qrc b/resources/resources.qrc
index cb535c604..aa3b77573 100644
--- a/resources/resources.qrc
+++ b/resources/resources.qrc
@@ -46,6 +46,11 @@
images/about.svg
images/moderatormode_disabled.png
images/moderatormode_enabled.png
+ images/split/splitdown.png
+ images/split/splitleft.png
+ images/split/splitright.png
+ images/split/splitup.png
+ images/split/splitmove.png
qt.conf
diff --git a/src/singletons/resourcemanager.cpp b/src/singletons/resourcemanager.cpp
index 274b8ee86..b989261c7 100644
--- a/src/singletons/resourcemanager.cpp
+++ b/src/singletons/resourcemanager.cpp
@@ -1,6 +1,7 @@
#include "resourcemanager.hpp"
#include "util/urlfetch.hpp"
+#include
#include
namespace chatterino {
@@ -288,6 +289,11 @@ ResourceManager::ResourceManager()
, buttonBan(lli(":/images/button_ban.png", 0.25))
, buttonTimeout(lli(":/images/button_timeout.png", 0.25))
{
+ this->split.left = QIcon(":/images/split/splitleft.png");
+ this->split.right = QIcon(":/images/split/splitright.png");
+ this->split.up = QIcon(":/images/split/splitup.png");
+ this->split.down = QIcon(":/images/split/splitdown.png");
+ this->split.move = QIcon(":/images/split/splitmove.png");
qDebug() << "init ResourceManager";
}
diff --git a/src/singletons/resourcemanager.hpp b/src/singletons/resourcemanager.hpp
index 17bb7f18a..2da506583 100644
--- a/src/singletons/resourcemanager.hpp
+++ b/src/singletons/resourcemanager.hpp
@@ -20,6 +20,14 @@ public:
void initialize();
+ struct {
+ QIcon left;
+ QIcon right;
+ QIcon up;
+ QIcon down;
+ QIcon move;
+ } split;
+
messages::Image *badgeStaff;
messages::Image *badgeAdmin;
messages::Image *badgeGlobalModerator;
diff --git a/src/widgets/basewidget.cpp b/src/widgets/basewidget.cpp
index 74b548286..4dcc1a6d3 100644
--- a/src/widgets/basewidget.cpp
+++ b/src/widgets/basewidget.cpp
@@ -111,7 +111,7 @@ void BaseWidget::childEvent(QChildEvent *event)
void BaseWidget::showEvent(QShowEvent *)
{
- this->scaleChangedEvent(this->getScale());
+ this->setScale(this->getScale());
this->themeRefreshEvent();
}
diff --git a/src/widgets/helper/splitoverlay.cpp b/src/widgets/helper/splitoverlay.cpp
new file mode 100644
index 000000000..45758b3af
--- /dev/null
+++ b/src/widgets/helper/splitoverlay.cpp
@@ -0,0 +1,152 @@
+#include "splitoverlay.hpp"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "application.hpp"
+#include "singletons/resourcemanager.hpp"
+#include "widgets/split.hpp"
+
+namespace chatterino {
+namespace widgets {
+
+SplitOverlay::SplitOverlay(Split *parent)
+ : BaseWidget(parent)
+ , split(parent)
+{
+ QGridLayout *layout = new QGridLayout(this);
+ layout->setMargin(1);
+ layout->setSpacing(1);
+
+ layout->setRowStretch(1, 1);
+ layout->setRowStretch(3, 1);
+ layout->setColumnStretch(1, 1);
+ layout->setColumnStretch(3, 1);
+
+ QPushButton *move = new QPushButton(getApp()->resources->split.move, QString());
+ QPushButton *left = new QPushButton(getApp()->resources->split.left, QString());
+ QPushButton *right = new QPushButton(getApp()->resources->split.right, QString());
+ QPushButton *up = new QPushButton(getApp()->resources->split.up, QString());
+ QPushButton *down = new QPushButton(getApp()->resources->split.down, QString());
+
+ move->setGraphicsEffect(new QGraphicsOpacityEffect(this));
+ left->setGraphicsEffect(new QGraphicsOpacityEffect(this));
+ right->setGraphicsEffect(new QGraphicsOpacityEffect(this));
+ up->setGraphicsEffect(new QGraphicsOpacityEffect(this));
+ down->setGraphicsEffect(new QGraphicsOpacityEffect(this));
+
+ move->setFlat(true);
+ left->setFlat(true);
+ right->setFlat(true);
+ up->setFlat(true);
+ down->setFlat(true);
+
+ layout->addWidget(move, 2, 2);
+ layout->addWidget(left, 2, 0);
+ layout->addWidget(right, 2, 4);
+ layout->addWidget(up, 0, 2);
+ layout->addWidget(down, 4, 2);
+
+ move->installEventFilter(new ButtonEventFilter(this, SplitMove));
+ left->installEventFilter(new ButtonEventFilter(this, SplitLeft));
+ right->installEventFilter(new ButtonEventFilter(this, SplitRight));
+ up->installEventFilter(new ButtonEventFilter(this, SplitUp));
+ down->installEventFilter(new ButtonEventFilter(this, SplitDown));
+
+ move->setFocusPolicy(Qt::NoFocus);
+ left->setFocusPolicy(Qt::NoFocus);
+ right->setFocusPolicy(Qt::NoFocus);
+ up->setFocusPolicy(Qt::NoFocus);
+ down->setFocusPolicy(Qt::NoFocus);
+
+ move->setCursor(Qt::SizeAllCursor);
+
+ this->managedConnect(this->scaleChanged, [=](float scale) {
+ int a = scale * 40;
+ QSize size(a, a);
+
+ move->setIconSize(size);
+ left->setIconSize(size);
+ right->setIconSize(size);
+ up->setIconSize(size);
+ down->setIconSize(size);
+ });
+}
+
+void SplitOverlay::paintEvent(QPaintEvent *event)
+{
+ QPainter painter(this);
+ painter.fillRect(this->rect(), QColor(0, 0, 0, 90));
+
+ QRect rect;
+ switch (this->hoveredElement) {
+ case SplitLeft: {
+ rect = QRect(0, 0, this->width() / 2, this->height());
+ } break;
+ case SplitRight: {
+ rect = QRect(this->width() / 2, 0, this->width() / 2, this->height());
+ } break;
+ case SplitUp: {
+ rect = QRect(0, 0, this->width(), this->height() / 2);
+ } break;
+ case SplitDown: {
+ rect = QRect(0, this->height() / 2, this->width(), this->height() / 2);
+ } break;
+ }
+ if (!rect.isNull()) {
+ painter.setPen(QColor(0, 148, 255, 0x70));
+ painter.setBrush(QColor(0, 148, 255, 0x30));
+ painter.drawRect(rect);
+ }
+}
+
+SplitOverlay::ButtonEventFilter::ButtonEventFilter(SplitOverlay *_parent, HoveredElement _element)
+ : QObject(_parent)
+ , parent(_parent)
+ , hoveredElement(_element)
+{
+}
+
+bool SplitOverlay::ButtonEventFilter::eventFilter(QObject *watched, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::Enter: {
+ QGraphicsOpacityEffect *effect =
+ dynamic_cast(((QWidget *)watched)->graphicsEffect());
+
+ if (effect != nullptr) {
+ effect->setOpacity(1);
+ }
+
+ this->parent->hoveredElement = this->hoveredElement;
+ this->parent->update();
+ } break;
+ case QEvent::Leave: {
+ QGraphicsOpacityEffect *effect =
+ dynamic_cast(((QWidget *)watched)->graphicsEffect());
+
+ if (effect != nullptr) {
+ effect->setOpacity(0.7);
+ }
+
+ this->parent->hoveredElement = HoveredElement::None;
+ this->parent->update();
+ } break;
+ case QEvent::MouseButtonPress: {
+ if (this->hoveredElement == HoveredElement::SplitMove) {
+ QMouseEvent *mouseEvent = static_cast(event);
+ if (mouseEvent->button() == Qt::LeftButton) {
+ this->parent->split->drag();
+ }
+ return true;
+ }
+ } break;
+ }
+ return QObject::eventFilter(watched, event);
+}
+
+} // namespace widgets
+} // namespace chatterino
diff --git a/src/widgets/helper/splitoverlay.hpp b/src/widgets/helper/splitoverlay.hpp
new file mode 100644
index 000000000..31b7a4b42
--- /dev/null
+++ b/src/widgets/helper/splitoverlay.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "pajlada/signals/signalholder.hpp"
+#include "widgets/basewidget.hpp"
+
+namespace chatterino {
+namespace widgets {
+
+class Split;
+
+class SplitOverlay : public BaseWidget, pajlada::Signals::SignalHolder
+{
+public:
+ explicit SplitOverlay(Split *parent = nullptr);
+
+protected:
+ void paintEvent(QPaintEvent *event) override;
+
+private:
+ enum HoveredElement { None, SplitMove, SplitLeft, SplitRight, SplitUp, SplitDown };
+ HoveredElement hoveredElement = None;
+ Split *split;
+
+ class ButtonEventFilter : public QObject
+ {
+ HoveredElement hoveredElement;
+ SplitOverlay *parent;
+
+ public:
+ ButtonEventFilter(SplitOverlay *parent, HoveredElement hoveredElement);
+
+ protected:
+ bool eventFilter(QObject *watched, QEvent *event) override;
+ };
+
+ friend class ButtonEventFilter;
+};
+
+} // namespace widgets
+} // namespace chatterino
diff --git a/src/widgets/split.cpp b/src/widgets/split.cpp
index d4408191a..c186188c5 100644
--- a/src/widgets/split.cpp
+++ b/src/widgets/split.cpp
@@ -13,6 +13,7 @@
#include "widgets/helper/debugpopup.hpp"
#include "widgets/helper/searchpopup.hpp"
#include "widgets/helper/shortcut.hpp"
+#include "widgets/helper/splitoverlay.hpp"
#include "widgets/qualitypopup.hpp"
#include "widgets/selectchanneldialog.hpp"
#include "widgets/splitcontainer.hpp"
@@ -38,6 +39,9 @@ using namespace chatterino::messages;
namespace chatterino {
namespace widgets {
+pajlada::Signals::Signal Split::altPressedStatusChanged;
+bool Split::altPressesStatus = false;
+
Split::Split(SplitContainer *parent)
: Split((QWidget *)parent)
{
@@ -52,6 +56,7 @@ Split::Split(QWidget *parent)
, header(this)
, view(this)
, input(this)
+ , overlay(new SplitOverlay(this))
{
auto app = getApp();
@@ -119,8 +124,17 @@ Split::Split(QWidget *parent)
this->managedConnections);
this->header.updateModerationModeIcon();
+ this->overlay->hide();
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+
+ this->managedConnect(altPressedStatusChanged, [this](bool status) {
+ if (status && this->isMouseOver) {
+ this->overlay->show();
+ } else {
+ this->overlay->hide();
+ }
+ });
}
Split::~Split()
@@ -287,15 +301,39 @@ void Split::keyReleaseEvent(QKeyEvent *event)
this->handleModifiers(event, event->modifiers());
}
+void Split::resizeEvent(QResizeEvent *event)
+{
+ BaseWidget::resizeEvent(event);
+
+ this->overlay->setGeometry(this->rect());
+}
+
+void Split::enterEvent(QEvent *event)
+{
+ this->isMouseOver = true;
+ if (altPressesStatus) {
+ this->overlay->show();
+ }
+}
+
+void Split::leaveEvent(QEvent *event)
+{
+ this->isMouseOver = false;
+ this->overlay->hide();
+}
+
void Split::handleModifiers(QEvent *event, Qt::KeyboardModifiers modifiers)
{
if (modifiers == Qt::AltModifier) {
- this->setCursor(Qt::SizeAllCursor);
- event->accept();
- // } else if (modifiers == Qt::ControlModifier) {
- // this->setCursor(Qt::SplitHCursor);
- // event->accept();
+ if (!altPressesStatus) {
+ altPressesStatus = true;
+ altPressedStatusChanged.invoke(true);
+ }
} else {
+ if (altPressesStatus) {
+ altPressesStatus = false;
+ altPressedStatusChanged.invoke(false);
+ }
this->setCursor(Qt::ArrowCursor);
}
}
diff --git a/src/widgets/split.hpp b/src/widgets/split.hpp
index dd6cbf56d..e184cefc9 100644
--- a/src/widgets/split.hpp
+++ b/src/widgets/split.hpp
@@ -21,6 +21,7 @@ namespace chatterino {
namespace widgets {
class SplitContainer;
+class SplitOverlay;
// Each ChatWidget consists of three sub-elements that handle their own part of the chat widget:
// ChatWidgetHeader
@@ -32,12 +33,15 @@ class SplitContainer;
// - Responsible for rendering and handling user text input
//
// Each sub-element has a reference to the parent Chat Widget
-class Split : public BaseWidget
+class Split : public BaseWidget, pajlada::Signals::SignalHolder
{
friend class SplitInput;
Q_OBJECT
+ static pajlada::Signals::Signal altPressedStatusChanged;
+ static bool altPressesStatus;
+
public:
explicit Split(SplitContainer *parent);
explicit Split(QWidget *parent);
@@ -81,6 +85,9 @@ protected:
void mousePressEvent(QMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *event) override;
+ void resizeEvent(QResizeEvent *event) override;
+ void enterEvent(QEvent *event) override;
+ void leaveEvent(QEvent *event) override;
private:
SplitContainer *container;
@@ -90,11 +97,15 @@ private:
SplitHeader header;
ChannelView view;
SplitInput input;
+ SplitOverlay *overlay;
+
double flexSizeX = 1;
double flexSizeY = 1;
bool moderationMode = false;
+ bool isMouseOver = false;
+
pajlada::Signals::Connection channelIDChangedConnection;
pajlada::Signals::Connection usermodeChangedConnection;
pajlada::Signals::Connection indirectChannelChangedConnection;
diff --git a/src/widgets/window.cpp b/src/widgets/window.cpp
index b2020ea23..ef667c50b 100644
--- a/src/widgets/window.cpp
+++ b/src/widgets/window.cpp
@@ -138,9 +138,9 @@ void Window::refreshWindowTitle(const QString &username)
this->setWindowTitle(username + " - Chatterino for Twitch");
}
-bool Window::event(QEvent *e)
+bool Window::event(QEvent *event)
{
- switch (e->type()) {
+ switch (event->type()) {
case QEvent::WindowActivate:
break;
@@ -156,7 +156,7 @@ bool Window::event(QEvent *e)
}
} break;
};
- return BaseWindow::event(e);
+ return BaseWindow::event(event);
}
void Window::closeEvent(QCloseEvent *event)