refactor: buttons and friends (#6102)
This commit is contained in:
@@ -52,6 +52,7 @@
|
|||||||
- Dev: Simplified string literals to be a re-export of Qt functions. (#6175)
|
- Dev: Simplified string literals to be a re-export of Qt functions. (#6175)
|
||||||
- Dev: Fixed incorrect lua generation of static methods for typescript plugins. (#6190, #6223)
|
- Dev: Fixed incorrect lua generation of static methods for typescript plugins. (#6190, #6223)
|
||||||
- Dev: Merged top/bottom and left/right notebook layouts. (#6215)
|
- Dev: Merged top/bottom and left/right notebook layouts. (#6215)
|
||||||
|
- Dev: Refactored `Button` and friends. (#6102)
|
||||||
|
|
||||||
## 2.5.3
|
## 2.5.3
|
||||||
|
|
||||||
|
|||||||
+21
-14
@@ -523,8 +523,6 @@ set(SOURCE_FILES
|
|||||||
util/Helpers.hpp
|
util/Helpers.hpp
|
||||||
util/IncognitoBrowser.cpp
|
util/IncognitoBrowser.cpp
|
||||||
util/IncognitoBrowser.hpp
|
util/IncognitoBrowser.hpp
|
||||||
util/InitUpdateButton.cpp
|
|
||||||
util/InitUpdateButton.hpp
|
|
||||||
util/IpcQueue.cpp
|
util/IpcQueue.cpp
|
||||||
util/IpcQueue.hpp
|
util/IpcQueue.hpp
|
||||||
util/IrcHelpers.cpp
|
util/IrcHelpers.cpp
|
||||||
@@ -602,6 +600,27 @@ set(SOURCE_FILES
|
|||||||
widgets/Window.cpp
|
widgets/Window.cpp
|
||||||
widgets/Window.hpp
|
widgets/Window.hpp
|
||||||
|
|
||||||
|
widgets/buttons/Button.cpp
|
||||||
|
widgets/buttons/Button.hpp
|
||||||
|
widgets/buttons/DimButton.cpp
|
||||||
|
widgets/buttons/DimButton.hpp
|
||||||
|
widgets/buttons/InitUpdateButton.cpp
|
||||||
|
widgets/buttons/InitUpdateButton.hpp
|
||||||
|
widgets/buttons/LabelButton.cpp
|
||||||
|
widgets/buttons/LabelButton.hpp
|
||||||
|
widgets/buttons/NotebookButton.cpp
|
||||||
|
widgets/buttons/NotebookButton.hpp
|
||||||
|
widgets/buttons/PixmapButton.cpp
|
||||||
|
widgets/buttons/PixmapButton.hpp
|
||||||
|
widgets/buttons/SignalLabel.cpp
|
||||||
|
widgets/buttons/SignalLabel.hpp
|
||||||
|
widgets/buttons/SvgButton.cpp
|
||||||
|
widgets/buttons/SvgButton.hpp
|
||||||
|
widgets/buttons/TitlebarButton.cpp
|
||||||
|
widgets/buttons/TitlebarButton.hpp
|
||||||
|
widgets/buttons/TitlebarButtons.cpp
|
||||||
|
widgets/buttons/TitlebarButtons.hpp
|
||||||
|
|
||||||
widgets/dialogs/BadgePickerDialog.cpp
|
widgets/dialogs/BadgePickerDialog.cpp
|
||||||
widgets/dialogs/BadgePickerDialog.hpp
|
widgets/dialogs/BadgePickerDialog.hpp
|
||||||
widgets/dialogs/ChannelFilterEditorDialog.cpp
|
widgets/dialogs/ChannelFilterEditorDialog.cpp
|
||||||
@@ -660,8 +679,6 @@ set(SOURCE_FILES
|
|||||||
widgets/helper/color/SBCanvas.cpp
|
widgets/helper/color/SBCanvas.cpp
|
||||||
widgets/helper/color/SBCanvas.hpp
|
widgets/helper/color/SBCanvas.hpp
|
||||||
|
|
||||||
widgets/helper/Button.cpp
|
|
||||||
widgets/helper/Button.hpp
|
|
||||||
widgets/helper/ChannelView.cpp
|
widgets/helper/ChannelView.cpp
|
||||||
widgets/helper/ChannelView.hpp
|
widgets/helper/ChannelView.hpp
|
||||||
widgets/helper/ComboBoxItemDelegate.cpp
|
widgets/helper/ComboBoxItemDelegate.cpp
|
||||||
@@ -670,16 +687,12 @@ set(SOURCE_FILES
|
|||||||
widgets/helper/DebugPopup.hpp
|
widgets/helper/DebugPopup.hpp
|
||||||
widgets/helper/EditableModelView.cpp
|
widgets/helper/EditableModelView.cpp
|
||||||
widgets/helper/EditableModelView.hpp
|
widgets/helper/EditableModelView.hpp
|
||||||
widgets/helper/EffectLabel.cpp
|
|
||||||
widgets/helper/EffectLabel.hpp
|
|
||||||
widgets/helper/IconDelegate.cpp
|
widgets/helper/IconDelegate.cpp
|
||||||
widgets/helper/IconDelegate.hpp
|
widgets/helper/IconDelegate.hpp
|
||||||
widgets/helper/InvisibleSizeGrip.cpp
|
widgets/helper/InvisibleSizeGrip.cpp
|
||||||
widgets/helper/InvisibleSizeGrip.hpp
|
widgets/helper/InvisibleSizeGrip.hpp
|
||||||
widgets/helper/MessageView.cpp
|
widgets/helper/MessageView.cpp
|
||||||
widgets/helper/MessageView.hpp
|
widgets/helper/MessageView.hpp
|
||||||
widgets/helper/NotebookButton.cpp
|
|
||||||
widgets/helper/NotebookButton.hpp
|
|
||||||
widgets/helper/NotebookTab.cpp
|
widgets/helper/NotebookTab.cpp
|
||||||
widgets/helper/NotebookTab.hpp
|
widgets/helper/NotebookTab.hpp
|
||||||
widgets/helper/OverlayInteraction.cpp
|
widgets/helper/OverlayInteraction.cpp
|
||||||
@@ -694,14 +707,8 @@ set(SOURCE_FILES
|
|||||||
widgets/helper/SearchPopup.hpp
|
widgets/helper/SearchPopup.hpp
|
||||||
widgets/helper/SettingsDialogTab.cpp
|
widgets/helper/SettingsDialogTab.cpp
|
||||||
widgets/helper/SettingsDialogTab.hpp
|
widgets/helper/SettingsDialogTab.hpp
|
||||||
widgets/helper/SignalLabel.cpp
|
|
||||||
widgets/helper/SignalLabel.hpp
|
|
||||||
widgets/helper/TableStyles.cpp
|
widgets/helper/TableStyles.cpp
|
||||||
widgets/helper/TableStyles.hpp
|
widgets/helper/TableStyles.hpp
|
||||||
widgets/helper/TitlebarButton.cpp
|
|
||||||
widgets/helper/TitlebarButton.hpp
|
|
||||||
widgets/helper/TitlebarButtons.cpp
|
|
||||||
widgets/helper/TitlebarButtons.hpp
|
|
||||||
widgets/helper/TrimRegExpValidator.cpp
|
widgets/helper/TrimRegExpValidator.cpp
|
||||||
widgets/helper/TrimRegExpValidator.hpp
|
widgets/helper/TrimRegExpValidator.hpp
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace pajlada {
|
|
||||||
namespace Signals {
|
|
||||||
class SignalHolder;
|
|
||||||
}
|
|
||||||
} // namespace pajlada
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
class Button;
|
|
||||||
class UpdateDialog;
|
|
||||||
|
|
||||||
void initUpdateButton(Button &button,
|
|
||||||
pajlada::Signals::SignalHolder &signalHolder);
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
||||||
@@ -8,8 +8,9 @@
|
|||||||
#include "util/DebugCount.hpp"
|
#include "util/DebugCount.hpp"
|
||||||
#include "util/PostToThread.hpp"
|
#include "util/PostToThread.hpp"
|
||||||
#include "util/WindowsHelper.hpp"
|
#include "util/WindowsHelper.hpp"
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
#include "widgets/buttons/LabelButton.hpp"
|
||||||
#include "widgets/helper/TitlebarButtons.hpp"
|
#include "widgets/buttons/TitlebarButton.hpp"
|
||||||
|
#include "widgets/buttons/TitlebarButtons.hpp"
|
||||||
#include "widgets/Label.hpp"
|
#include "widgets/Label.hpp"
|
||||||
#include "widgets/Window.hpp"
|
#include "widgets/Window.hpp"
|
||||||
|
|
||||||
@@ -35,8 +36,6 @@
|
|||||||
# include <QOperatingSystemVersion>
|
# include <QOperatingSystemVersion>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "widgets/helper/TitlebarButton.hpp"
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace chatterino;
|
using namespace chatterino;
|
||||||
@@ -672,34 +671,21 @@ void BaseWindow::focusOutEvent(QFocusEvent *event)
|
|||||||
BaseWidget::focusOutEvent(event);
|
BaseWidget::focusOutEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBarButton *BaseWindow::addTitleBarButton(const TitleBarButtonStyle &style,
|
void BaseWindow::appendTitlebarButton(Button *button)
|
||||||
std::function<void()> onClicked)
|
|
||||||
{
|
{
|
||||||
TitleBarButton *button = new TitleBarButton;
|
|
||||||
button->setScaleIndependentSize(30, 30);
|
|
||||||
|
|
||||||
this->ui_.buttons.push_back(button);
|
this->ui_.buttons.push_back(button);
|
||||||
this->ui_.titlebarBox->insertWidget(1, button);
|
this->ui_.titlebarBox->insertWidget(1, button);
|
||||||
button->setButtonStyle(style);
|
|
||||||
|
|
||||||
QObject::connect(button, &TitleBarButton::leftClicked, this, [onClicked] {
|
|
||||||
onClicked();
|
|
||||||
});
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EffectLabel *BaseWindow::addTitleBarLabel(std::function<void()> onClicked)
|
LabelButton *BaseWindow::addTitleBarLabel(std::function<void()> onClicked)
|
||||||
{
|
{
|
||||||
EffectLabel *button = new EffectLabel;
|
auto *button = new LabelButton;
|
||||||
button->setScaleIndependentHeight(30);
|
button->setScaleIndependentHeight(30);
|
||||||
|
|
||||||
this->ui_.buttons.push_back(button);
|
this->appendTitlebarButton(button);
|
||||||
this->ui_.titlebarBox->insertWidget(1, button);
|
|
||||||
|
|
||||||
QObject::connect(button, &EffectLabel::leftClicked, this, [onClicked] {
|
QObject::connect(button, &LabelButton::leftClicked, this,
|
||||||
onClicked();
|
std::move(onClicked));
|
||||||
});
|
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ typedef struct tagMSG MSG;
|
|||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Button;
|
class Button;
|
||||||
class EffectLabel;
|
class LabelButton;
|
||||||
|
class PixmapButton;
|
||||||
class TitleBarButton;
|
class TitleBarButton;
|
||||||
class TitleBarButtons;
|
class TitleBarButtons;
|
||||||
enum class TitleBarButtonStyle;
|
enum class TitleBarButtonStyle : std::uint8_t;
|
||||||
|
|
||||||
class BaseWindow : public BaseWidget
|
class BaseWindow : public BaseWidget
|
||||||
{
|
{
|
||||||
@@ -52,9 +53,20 @@ public:
|
|||||||
|
|
||||||
QWidget *getLayoutContainer();
|
QWidget *getLayoutContainer();
|
||||||
bool hasCustomWindowFrame() const;
|
bool hasCustomWindowFrame() const;
|
||||||
TitleBarButton *addTitleBarButton(const TitleBarButtonStyle &style,
|
|
||||||
std::function<void()> onClicked);
|
template <typename T>
|
||||||
EffectLabel *addTitleBarLabel(std::function<void()> onClicked);
|
T *addTitleBarButton(std::function<void()> onClicked, auto &&...args)
|
||||||
|
{
|
||||||
|
auto *button = new T(std::forward<decltype(args)>(args)...);
|
||||||
|
button->setScaleIndependentSize(30, 30);
|
||||||
|
this->appendTitlebarButton(button);
|
||||||
|
|
||||||
|
QObject::connect(button, &T::leftClicked, this, std::move(onClicked));
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelButton *addTitleBarLabel(std::function<void()> onClicked);
|
||||||
|
|
||||||
void moveTo(QPoint point, widgets::BoundsChecking mode);
|
void moveTo(QPoint point, widgets::BoundsChecking mode);
|
||||||
|
|
||||||
@@ -169,6 +181,8 @@ private:
|
|||||||
bool handleNCHITTEST(MSG *msg, long *result);
|
bool handleNCHITTEST(MSG *msg, long *result);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void appendTitlebarButton(Button *button);
|
||||||
|
|
||||||
bool enableCustomFrame_;
|
bool enableCustomFrame_;
|
||||||
bool frameless_;
|
bool frameless_;
|
||||||
bool shown_ = false;
|
bool shown_ = false;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "singletons/Resources.hpp"
|
#include "singletons/Resources.hpp"
|
||||||
#include "singletons/Theme.hpp"
|
#include "singletons/Theme.hpp"
|
||||||
#include "widgets/helper/Button.hpp"
|
#include "widgets/buttons/PixmapButton.hpp"
|
||||||
|
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ void DraggablePopup::togglePinned()
|
|||||||
}
|
}
|
||||||
Button *DraggablePopup::createPinButton()
|
Button *DraggablePopup::createPinButton()
|
||||||
{
|
{
|
||||||
this->pinButton_ = new Button(this);
|
this->pinButton_ = new PixmapButton(this);
|
||||||
this->pinButton_->setPixmap(getTheme()->buttons.pin);
|
this->pinButton_->setPixmap(getTheme()->buttons.pin);
|
||||||
this->pinButton_->setScaleIndependentSize(18, 18);
|
this->pinButton_->setScaleIndependentSize(18, 18);
|
||||||
this->pinButton_->setToolTip("Pin Window");
|
this->pinButton_->setToolTip("Pin Window");
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
class PixmapButton;
|
||||||
|
|
||||||
class DraggablePopup : public BaseWindow
|
class DraggablePopup : public BaseWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -60,7 +62,7 @@ private:
|
|||||||
// dragTimer_ is called ~60 times per second once the user has initiated dragging
|
// dragTimer_ is called ~60 times per second once the user has initiated dragging
|
||||||
QTimer dragTimer_;
|
QTimer dragTimer_;
|
||||||
|
|
||||||
Button *pinButton_ = nullptr;
|
PixmapButton *pinButton_ = nullptr;
|
||||||
bool isPinned_ = false;
|
bool isPinned_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+11
-21
@@ -10,10 +10,11 @@
|
|||||||
#include "singletons/StreamerMode.hpp"
|
#include "singletons/StreamerMode.hpp"
|
||||||
#include "singletons/Theme.hpp"
|
#include "singletons/Theme.hpp"
|
||||||
#include "singletons/WindowManager.hpp"
|
#include "singletons/WindowManager.hpp"
|
||||||
#include "util/InitUpdateButton.hpp"
|
#include "widgets/buttons/InitUpdateButton.hpp"
|
||||||
|
#include "widgets/buttons/NotebookButton.hpp"
|
||||||
|
#include "widgets/buttons/PixmapButton.hpp"
|
||||||
#include "widgets/dialogs/SettingsDialog.hpp"
|
#include "widgets/dialogs/SettingsDialog.hpp"
|
||||||
#include "widgets/helper/ChannelView.hpp"
|
#include "widgets/helper/ChannelView.hpp"
|
||||||
#include "widgets/helper/NotebookButton.hpp"
|
|
||||||
#include "widgets/helper/NotebookTab.hpp"
|
#include "widgets/helper/NotebookTab.hpp"
|
||||||
#include "widgets/splits/Split.hpp"
|
#include "widgets/splits/Split.hpp"
|
||||||
#include "widgets/splits/SplitContainer.hpp"
|
#include "widgets/splits/SplitContainer.hpp"
|
||||||
@@ -1162,16 +1163,6 @@ NotebookButton *Notebook::getAddButton()
|
|||||||
return this->addButton_;
|
return this->addButton_;
|
||||||
}
|
}
|
||||||
|
|
||||||
NotebookButton *Notebook::addCustomButton()
|
|
||||||
{
|
|
||||||
NotebookButton *btn = new NotebookButton(this);
|
|
||||||
|
|
||||||
this->customButtons_.push_back(btn);
|
|
||||||
|
|
||||||
this->performLayout();
|
|
||||||
return btn;
|
|
||||||
}
|
|
||||||
|
|
||||||
NotebookTab *Notebook::getTabFromPage(QWidget *page)
|
NotebookTab *Notebook::getTabFromPage(QWidget *page)
|
||||||
{
|
{
|
||||||
for (auto &it : this->items_)
|
for (auto &it : this->items_)
|
||||||
@@ -1416,7 +1407,7 @@ void SplitNotebook::showEvent(QShowEvent * /*event*/)
|
|||||||
void SplitNotebook::addCustomButtons()
|
void SplitNotebook::addCustomButtons()
|
||||||
{
|
{
|
||||||
// settings
|
// settings
|
||||||
auto *settingsBtn = this->addCustomButton();
|
auto *settingsBtn = this->addCustomButton<NotebookButton>();
|
||||||
|
|
||||||
// This is to ensure you can't lock yourself out of the settings
|
// This is to ensure you can't lock yourself out of the settings
|
||||||
if (getApp()->getArgs().safeMode)
|
if (getApp()->getArgs().safeMode)
|
||||||
@@ -1442,7 +1433,7 @@ void SplitNotebook::addCustomButtons()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// account
|
// account
|
||||||
auto *userBtn = this->addCustomButton();
|
auto *userBtn = this->addCustomButton<NotebookButton>();
|
||||||
userBtn->setVisible(!getSettings()->hideUserButton.getValue());
|
userBtn->setVisible(!getSettings()->hideUserButton.getValue());
|
||||||
getSettings()->hideUserButton.connect(
|
getSettings()->hideUserButton.connect(
|
||||||
[userBtn](bool hide, auto) {
|
[userBtn](bool hide, auto) {
|
||||||
@@ -1457,17 +1448,16 @@ void SplitNotebook::addCustomButtons()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// updates
|
// updates
|
||||||
auto *updateBtn = this->addCustomButton();
|
auto *updateBtn = this->addCustomButton<PixmapButton>();
|
||||||
|
|
||||||
initUpdateButton(*updateBtn, this->signalHolder_);
|
initUpdateButton(*updateBtn, this->signalHolder_);
|
||||||
|
|
||||||
// streamer mode
|
// streamer mode
|
||||||
this->streamerModeIcon_ = this->addCustomButton();
|
this->streamerModeIcon_ = this->addCustomButton<PixmapButton>();
|
||||||
QObject::connect(this->streamerModeIcon_, &NotebookButton::leftClicked,
|
QObject::connect(this->streamerModeIcon_, &Button::leftClicked, [this] {
|
||||||
[this] {
|
getApp()->getWindows()->showSettingsDialog(
|
||||||
getApp()->getWindows()->showSettingsDialog(
|
this, SettingsDialogPreference::StreamerMode);
|
||||||
this, SettingsDialogPreference::StreamerMode);
|
});
|
||||||
});
|
|
||||||
QObject::connect(getApp()->getStreamerMode(), &IStreamerMode::changed, this,
|
QObject::connect(getApp()->getStreamerMode(), &IStreamerMode::changed, this,
|
||||||
&SplitNotebook::updateStreamerModeIcon);
|
&SplitNotebook::updateStreamerModeIcon);
|
||||||
this->updateStreamerModeIcon();
|
this->updateStreamerModeIcon();
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
class Button;
|
||||||
|
class PixmapButton;
|
||||||
|
class SvgButton;
|
||||||
class Window;
|
class Window;
|
||||||
class UpdateDialog;
|
class UpdateDialog;
|
||||||
class NotebookButton;
|
class NotebookButton;
|
||||||
@@ -131,7 +134,16 @@ protected:
|
|||||||
void paintEvent(QPaintEvent *) override;
|
void paintEvent(QPaintEvent *) override;
|
||||||
|
|
||||||
NotebookButton *getAddButton();
|
NotebookButton *getAddButton();
|
||||||
NotebookButton *addCustomButton();
|
|
||||||
|
template <typename T>
|
||||||
|
T *addCustomButton(auto &&...args)
|
||||||
|
{
|
||||||
|
auto *btn = new T(std::forward<decltype(args)>(args)..., this);
|
||||||
|
this->customButtons_.push_back(btn);
|
||||||
|
this->performLayout();
|
||||||
|
|
||||||
|
return btn;
|
||||||
|
}
|
||||||
|
|
||||||
struct Item {
|
struct Item {
|
||||||
NotebookTab *tab{};
|
NotebookTab *tab{};
|
||||||
@@ -206,7 +218,7 @@ private:
|
|||||||
QWidget *selectedPage_ = nullptr;
|
QWidget *selectedPage_ = nullptr;
|
||||||
|
|
||||||
NotebookButton *addButton_;
|
NotebookButton *addButton_;
|
||||||
std::vector<NotebookButton *> customButtons_;
|
std::vector<Button *> customButtons_;
|
||||||
|
|
||||||
bool allowUserTabManagement_ = false;
|
bool allowUserTabManagement_ = false;
|
||||||
bool showTabs_ = true;
|
bool showTabs_ = true;
|
||||||
@@ -261,7 +273,7 @@ private:
|
|||||||
pajlada::Signals::SignalHolder signalHolder_;
|
pajlada::Signals::SignalHolder signalHolder_;
|
||||||
|
|
||||||
// Main window on Windows has basically a duplicate of this in Window
|
// Main window on Windows has basically a duplicate of this in Window
|
||||||
NotebookButton *streamerModeIcon_{};
|
PixmapButton *streamerModeIcon_{};
|
||||||
void updateStreamerModeIcon();
|
void updateStreamerModeIcon();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+13
-10
@@ -17,16 +17,17 @@
|
|||||||
#include "singletons/Theme.hpp"
|
#include "singletons/Theme.hpp"
|
||||||
#include "singletons/Updates.hpp"
|
#include "singletons/Updates.hpp"
|
||||||
#include "singletons/WindowManager.hpp"
|
#include "singletons/WindowManager.hpp"
|
||||||
#include "util/InitUpdateButton.hpp"
|
|
||||||
#include "util/RapidJsonSerializeQSize.hpp"
|
#include "util/RapidJsonSerializeQSize.hpp"
|
||||||
#include "widgets/AccountSwitchPopup.hpp"
|
#include "widgets/AccountSwitchPopup.hpp"
|
||||||
|
#include "widgets/buttons/InitUpdateButton.hpp"
|
||||||
|
#include "widgets/buttons/LabelButton.hpp"
|
||||||
|
#include "widgets/buttons/PixmapButton.hpp"
|
||||||
|
#include "widgets/buttons/TitlebarButton.hpp"
|
||||||
#include "widgets/dialogs/SettingsDialog.hpp"
|
#include "widgets/dialogs/SettingsDialog.hpp"
|
||||||
#include "widgets/dialogs/switcher/QuickSwitcherPopup.hpp"
|
#include "widgets/dialogs/switcher/QuickSwitcherPopup.hpp"
|
||||||
#include "widgets/dialogs/UpdateDialog.hpp"
|
#include "widgets/dialogs/UpdateDialog.hpp"
|
||||||
#include "widgets/dialogs/WelcomeDialog.hpp"
|
#include "widgets/dialogs/WelcomeDialog.hpp"
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
|
||||||
#include "widgets/helper/NotebookTab.hpp"
|
#include "widgets/helper/NotebookTab.hpp"
|
||||||
#include "widgets/helper/TitlebarButton.hpp"
|
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
#include "widgets/splits/ClosedSplits.hpp"
|
#include "widgets/splits/ClosedSplits.hpp"
|
||||||
#include "widgets/splits/Split.hpp"
|
#include "widgets/splits/Split.hpp"
|
||||||
@@ -202,12 +203,14 @@ void Window::addCustomTitlebarButtons()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
this->addTitleBarButton(TitleBarButtonStyle::Settings, [this] {
|
this->addTitleBarButton<TitleBarButton>(
|
||||||
getApp()->getWindows()->showSettingsDialog(this);
|
[this] {
|
||||||
});
|
getApp()->getWindows()->showSettingsDialog(this);
|
||||||
|
},
|
||||||
|
TitleBarButtonStyle::Settings);
|
||||||
|
|
||||||
// updates
|
// updates
|
||||||
auto *update = this->addTitleBarButton(TitleBarButtonStyle::None, [] {});
|
auto *update = this->addTitleBarButton<PixmapButton>([] {});
|
||||||
|
|
||||||
initUpdateButton(*update, this->signalHolder_);
|
initUpdateButton(*update, this->signalHolder_);
|
||||||
|
|
||||||
@@ -221,7 +224,7 @@ void Window::addCustomTitlebarButtons()
|
|||||||
|
|
||||||
// streamer mode
|
// streamer mode
|
||||||
this->streamerModeTitlebarIcon_ =
|
this->streamerModeTitlebarIcon_ =
|
||||||
this->addTitleBarButton(TitleBarButtonStyle::StreamerMode, [this] {
|
this->addTitleBarButton<PixmapButton>([this] {
|
||||||
getApp()->getWindows()->showSettingsDialog(
|
getApp()->getWindows()->showSettingsDialog(
|
||||||
this, SettingsDialogPreference::StreamerMode);
|
this, SettingsDialogPreference::StreamerMode);
|
||||||
});
|
});
|
||||||
@@ -796,11 +799,11 @@ void Window::onAccountSelected()
|
|||||||
{
|
{
|
||||||
if (user->isAnon())
|
if (user->isAnon())
|
||||||
{
|
{
|
||||||
this->userLabel_->getLabel().setText("anonymous");
|
this->userLabel_->setText("anonymous");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->userLabel_->getLabel().setText(user->getUserName());
|
this->userLabel_->setText(user->getUserName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
|
class PixmapButton;
|
||||||
|
class LabelButton;
|
||||||
class Theme;
|
class Theme;
|
||||||
class UpdateDialog;
|
class UpdateDialog;
|
||||||
class SplitNotebook;
|
class SplitNotebook;
|
||||||
@@ -46,14 +48,14 @@ private:
|
|||||||
WindowType type_;
|
WindowType type_;
|
||||||
|
|
||||||
SplitNotebook *notebook_;
|
SplitNotebook *notebook_;
|
||||||
EffectLabel *userLabel_ = nullptr;
|
LabelButton *userLabel_ = nullptr;
|
||||||
std::shared_ptr<UpdateDialog> updateDialogHandle_;
|
std::shared_ptr<UpdateDialog> updateDialogHandle_;
|
||||||
|
|
||||||
pajlada::Signals::SignalHolder signalHolder_;
|
pajlada::Signals::SignalHolder signalHolder_;
|
||||||
std::vector<boost::signals2::scoped_connection> bSignals_;
|
std::vector<boost::signals2::scoped_connection> bSignals_;
|
||||||
|
|
||||||
// this is only used on Windows and only on the main window, for the one used otherwise, see SplitNotebook in Notebook.hpp
|
// this is only used on Windows and only on the main window, for the one used otherwise, see SplitNotebook in Notebook.hpp
|
||||||
TitleBarButton *streamerModeTitlebarIcon_ = nullptr;
|
PixmapButton *streamerModeTitlebarIcon_ = nullptr;
|
||||||
void updateStreamerModeIcon();
|
void updateStreamerModeIcon();
|
||||||
|
|
||||||
friend class Notebook;
|
friend class Notebook;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "widgets/helper/Button.hpp"
|
#include "widgets/buttons/Button.hpp"
|
||||||
|
|
||||||
#include "singletons/Theme.hpp"
|
#include "singletons/Theme.hpp"
|
||||||
#include "util/FunctionEventFilter.hpp"
|
#include "util/FunctionEventFilter.hpp"
|
||||||
@@ -8,42 +8,6 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
QSizeF deviceIndependentSize(const QPixmap &pixmap)
|
|
||||||
{
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 0)
|
|
||||||
return QSizeF(pixmap.width(), pixmap.height()) / pixmap.devicePixelRatio();
|
|
||||||
#else
|
|
||||||
return pixmap.deviceIndependentSize();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resizes a pixmap to a desired size.
|
|
||||||
* Does nothing if the target pixmap is already sized correctly.
|
|
||||||
*
|
|
||||||
* @param target The target pixmap.
|
|
||||||
* @param source The unscaled pixmap.
|
|
||||||
* @param size The desired device independent size.
|
|
||||||
* @param dpr The device pixel ratio of the target area. The size of the target in pixels will be `size * dpr`.
|
|
||||||
*/
|
|
||||||
void resizePixmap(QPixmap &target, const QPixmap &source, const QSize &size,
|
|
||||||
qreal dpr)
|
|
||||||
{
|
|
||||||
if (deviceIndependentSize(target) == size)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap resized = source;
|
|
||||||
resized.setDevicePixelRatio(dpr);
|
|
||||||
target = resized.scaled(size * dpr, Qt::IgnoreAspectRatio,
|
|
||||||
Qt::SmoothTransformation);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
Button::Button(BaseWidget *parent)
|
Button::Button(BaseWidget *parent)
|
||||||
@@ -58,98 +22,36 @@ Button::Button(BaseWidget *parent)
|
|||||||
this->setMouseTracking(true);
|
this->setMouseTracking(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::setMouseEffectColor(std::optional<QColor> color)
|
bool Button::enabled() const noexcept
|
||||||
{
|
|
||||||
this->mouseEffectColor_ = std::move(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::setPixmap(const QPixmap &_pixmap)
|
|
||||||
{
|
|
||||||
// Avoid updates if the pixmap didn't change
|
|
||||||
if (_pixmap.cacheKey() == this->pixmap_.cacheKey())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->pixmap_ = _pixmap;
|
|
||||||
this->resizedPixmap_ = {};
|
|
||||||
this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::setSvgResource(const QString &resourcePath)
|
|
||||||
{
|
|
||||||
if (resourcePath == this->svgResourcePath)
|
|
||||||
{
|
|
||||||
// Same resource path as before - nothing changed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->svgRenderer)
|
|
||||||
{
|
|
||||||
this->svgRenderer->deleteLater();
|
|
||||||
}
|
|
||||||
this->svgRenderer = new QSvgRenderer(resourcePath, this);
|
|
||||||
this->svgRenderer->setAspectRatioMode(Qt::KeepAspectRatio);
|
|
||||||
this->svgResourcePath = resourcePath;
|
|
||||||
|
|
||||||
this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
const QPixmap &Button::getPixmap() const
|
|
||||||
{
|
|
||||||
return this->pixmap_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::setDim(Dim value)
|
|
||||||
{
|
|
||||||
this->dimPixmap_ = value;
|
|
||||||
|
|
||||||
this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
Button::Dim Button::getDim() const
|
|
||||||
{
|
|
||||||
return this->dimPixmap_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Button::setEnable(bool value)
|
|
||||||
{
|
|
||||||
this->enabled_ = value;
|
|
||||||
|
|
||||||
this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Button::getEnable() const
|
|
||||||
{
|
{
|
||||||
return this->enabled_;
|
return this->enabled_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::setEnableMargin(bool value)
|
void Button::setEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
this->enableMargin_ = value;
|
this->enabled_ = enabled;
|
||||||
|
|
||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Button::getEnableMargin() const
|
bool Button::mouseOver() const noexcept
|
||||||
{
|
{
|
||||||
return this->enableMargin_;
|
return this->mouseOver_;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal Button::getCurrentDimAmount() const
|
bool Button::mouseDown() const noexcept
|
||||||
{
|
{
|
||||||
if (this->dimPixmap_ == Dim::None || this->mouseOver_)
|
return this->mouseDown_;
|
||||||
{
|
}
|
||||||
return 1;
|
|
||||||
}
|
bool Button::menuVisible() const noexcept
|
||||||
else if (this->dimPixmap_ == Dim::Some)
|
{
|
||||||
{
|
return this->menuVisible_;
|
||||||
return 0.7;
|
}
|
||||||
}
|
|
||||||
else
|
QColor Button::borderColor() const noexcept
|
||||||
{
|
{
|
||||||
return 0.15;
|
return this->borderColor_;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::setBorderColor(const QColor &color)
|
void Button::setBorderColor(const QColor &color)
|
||||||
@@ -159,9 +61,19 @@ void Button::setBorderColor(const QColor &color)
|
|||||||
this->update();
|
this->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QColor &Button::getBorderColor() const
|
std::optional<QColor> Button::mouseEffectColor() const
|
||||||
{
|
{
|
||||||
return this->borderColor_;
|
return this->mouseEffectColor_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::setMouseEffectColor(std::optional<QColor> color)
|
||||||
|
{
|
||||||
|
this->mouseEffectColor_ = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu *Button::menu() const
|
||||||
|
{
|
||||||
|
return this->menu_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::setMenu(std::unique_ptr<QMenu> menu)
|
void Button::setMenu(std::unique_ptr<QMenu> menu)
|
||||||
@@ -185,104 +97,45 @@ void Button::setMenu(std::unique_ptr<QMenu> menu)
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::paintEvent(QPaintEvent *)
|
void Button::paintEvent(QPaintEvent * /*event*/)
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
this->paintButton(painter);
|
this->paintButton(painter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::paintButton(QPainter &painter)
|
void Button::invalidateContent()
|
||||||
{
|
{
|
||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
this->pixmapValid_ = false;
|
||||||
|
this->update();
|
||||||
if (this->svgRenderer != nullptr)
|
|
||||||
{
|
|
||||||
painter.setOpacity(this->getCurrentDimAmount());
|
|
||||||
|
|
||||||
auto rect = this->rect();
|
|
||||||
|
|
||||||
if (this->enableMargin_)
|
|
||||||
{
|
|
||||||
auto s = this->getMargin();
|
|
||||||
rect = {{s, s}, rect.size() - QSize{2 * s, 2 * s}};
|
|
||||||
}
|
|
||||||
|
|
||||||
this->svgRenderer->render(&painter, rect);
|
|
||||||
}
|
|
||||||
else if (!this->pixmap_.isNull())
|
|
||||||
{
|
|
||||||
painter.setOpacity(this->getCurrentDimAmount());
|
|
||||||
|
|
||||||
QRect rect = this->rect();
|
|
||||||
|
|
||||||
resizePixmap(this->resizedPixmap_, this->pixmap_, rect.size(),
|
|
||||||
this->devicePixelRatio());
|
|
||||||
|
|
||||||
if (this->enableMargin_)
|
|
||||||
{
|
|
||||||
auto s = this->getMargin();
|
|
||||||
rect.moveLeft(s);
|
|
||||||
rect.setRight(rect.right() - s - s);
|
|
||||||
rect.moveTop(s);
|
|
||||||
rect.setBottom(rect.bottom() - s - s);
|
|
||||||
}
|
|
||||||
|
|
||||||
painter.drawPixmap(rect, this->resizedPixmap_);
|
|
||||||
|
|
||||||
painter.setOpacity(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->fancyPaint(painter);
|
|
||||||
|
|
||||||
if (this->borderColor_.isValid())
|
|
||||||
{
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
|
||||||
painter.setPen(this->borderColor_);
|
|
||||||
painter.drawRect(0, 0, this->width() - 1, this->height() - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::fancyPaint(QPainter &painter)
|
bool Button::contentCacheEnabled() const noexcept
|
||||||
{
|
{
|
||||||
if (!this->enabled_)
|
return this->cachePixmap_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::setContentCacheEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
if (this->cachePixmap_ == enabled)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
if (!enabled)
|
||||||
QColor c;
|
|
||||||
|
|
||||||
if (this->mouseEffectColor_)
|
|
||||||
{
|
{
|
||||||
c = *this->mouseEffectColor_;
|
this->cachedPixmap_ = {};
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c = this->theme->isLightTheme() ? QColor(0, 0, 0)
|
|
||||||
: QColor(255, 255, 255);
|
|
||||||
}
|
}
|
||||||
|
this->cachePixmap_ = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->hoverMultiplier_ > 0)
|
bool Button::opaqueContent() const noexcept
|
||||||
{
|
{
|
||||||
QRadialGradient gradient(QPointF(mousePos_), this->width() / 2);
|
return this->opaqueContent_;
|
||||||
|
}
|
||||||
|
|
||||||
gradient.setColorAt(0, QColor(c.red(), c.green(), c.blue(),
|
void Button::setOpaqueContent(bool opaqueContent)
|
||||||
int(50 * this->hoverMultiplier_)));
|
{
|
||||||
gradient.setColorAt(1, QColor(c.red(), c.green(), c.blue(),
|
this->opaqueContent_ = opaqueContent;
|
||||||
int(40 * this->hoverMultiplier_)));
|
|
||||||
|
|
||||||
painter.fillRect(this->rect(), gradient);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto effect : this->clickEffects_)
|
|
||||||
{
|
|
||||||
painter.setPen(Qt::NoPen);
|
|
||||||
painter.setBrush(QColor(c.red(), c.green(), c.blue(),
|
|
||||||
int((1 - effect.progress) * 95)));
|
|
||||||
painter.drawEllipse(QPointF(effect.position),
|
|
||||||
effect.progress * qreal(width()) * 2,
|
|
||||||
effect.progress * qreal(width()) * 2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
@@ -319,7 +172,7 @@ void Button::mousePressEvent(QMouseEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->clickEffects_.push_back(ClickEffect(event->pos()));
|
this->clickEffects_.emplace_back(event->pos());
|
||||||
|
|
||||||
this->mouseDown_ = true;
|
this->mouseDown_ = true;
|
||||||
|
|
||||||
@@ -374,16 +227,7 @@ void Button::onMouseEffectTimeout()
|
|||||||
{
|
{
|
||||||
bool performUpdate = false;
|
bool performUpdate = false;
|
||||||
|
|
||||||
if (selected_)
|
if (mouseOver_)
|
||||||
{
|
|
||||||
if (this->hoverMultiplier_ != 0)
|
|
||||||
{
|
|
||||||
this->hoverMultiplier_ =
|
|
||||||
std::max(0.0, this->hoverMultiplier_ - 0.1);
|
|
||||||
performUpdate = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mouseOver_)
|
|
||||||
{
|
{
|
||||||
if (this->hoverMultiplier_ != 1)
|
if (this->hoverMultiplier_ != 1)
|
||||||
{
|
{
|
||||||
@@ -402,7 +246,7 @@ void Button::onMouseEffectTimeout()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->clickEffects_.size() != 0)
|
if (!this->clickEffects_.empty())
|
||||||
{
|
{
|
||||||
performUpdate = true;
|
performUpdate = true;
|
||||||
|
|
||||||
@@ -456,13 +300,93 @@ void Button::showMenu()
|
|||||||
this->menuVisible_ = true;
|
this->menuVisible_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Button::getMargin() const
|
void Button::paintButton(QPainter &painter)
|
||||||
{
|
{
|
||||||
assert(this->enableMargin_);
|
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||||
|
|
||||||
int baseMargin = this->height() < 22 * this->scale() ? 3 : 6;
|
if (this->cachePixmap_)
|
||||||
|
{
|
||||||
|
if (this->cachedPixmap_.size() != this->size())
|
||||||
|
{
|
||||||
|
this->cachedPixmap_ = QPixmap(this->size());
|
||||||
|
this->cachedPixmap_.setDevicePixelRatio(this->devicePixelRatio());
|
||||||
|
this->pixmapValid_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
return static_cast<int>(baseMargin * this->scale());
|
if (!this->pixmapValid_)
|
||||||
|
{
|
||||||
|
if (!this->opaqueContent_)
|
||||||
|
{
|
||||||
|
this->cachedPixmap_.fill(Qt::transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
QPainter pixmapPainter(&this->cachedPixmap_);
|
||||||
|
this->paintContent(pixmapPainter);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->pixmapValid_ = true;
|
||||||
|
}
|
||||||
|
painter.drawPixmap(this->rect(), this->cachedPixmap_,
|
||||||
|
{{}, this->cachedPixmap_.size()});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->paintContent(painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->fancyPaint(painter);
|
||||||
|
|
||||||
|
if (this->borderColor_.isValid())
|
||||||
|
{
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
painter.setPen(this->borderColor_);
|
||||||
|
painter.drawRect(0, 0, this->width() - 1, this->height() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::fancyPaint(QPainter &painter)
|
||||||
|
{
|
||||||
|
if (!this->enabled_)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
QColor c;
|
||||||
|
|
||||||
|
if (this->mouseEffectColor_)
|
||||||
|
{
|
||||||
|
c = *this->mouseEffectColor_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = this->theme->isLightTheme() ? QColor(0, 0, 0)
|
||||||
|
: QColor(255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->hoverMultiplier_ > 0)
|
||||||
|
{
|
||||||
|
QRadialGradient gradient(QPointF(mousePos_),
|
||||||
|
static_cast<qreal>(this->width()) / 2.0);
|
||||||
|
|
||||||
|
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_)
|
||||||
|
{
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
painter.setBrush(QColor(c.red(), c.green(), c.blue(),
|
||||||
|
int((1 - effect.progress) * 95)));
|
||||||
|
painter.drawEllipse(QPointF(effect.position),
|
||||||
|
effect.progress * qreal(width()) * 2,
|
||||||
|
effect.progress * qreal(width()) * 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chatterino
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "widgets/BaseWidget.hpp"
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPoint>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/// @brief A generic button with click and hover effects.
|
||||||
|
///
|
||||||
|
/// This button doesn't display anything - subclasses add content to the button.
|
||||||
|
///
|
||||||
|
/// To add content in a derived class, implement #paintContent(). This gets
|
||||||
|
/// called before the click and hover effects are drawn.+
|
||||||
|
///
|
||||||
|
/// Subclasses can enable caching of the content drawn in #paintContent(), as
|
||||||
|
/// the button often repaints due to mouse movement (and the hover effects).
|
||||||
|
/// When updating the button, subclasses can invalidate the cache with
|
||||||
|
/// #invalidateContent(). Alternatively, a subclass opt out of this by calling
|
||||||
|
/// #setContentCacheEnabled().
|
||||||
|
class Button : public BaseWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
struct ClickEffect {
|
||||||
|
double progress = 0.0;
|
||||||
|
QPoint position;
|
||||||
|
|
||||||
|
ClickEffect(QPoint _position)
|
||||||
|
: position(_position)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Button(BaseWidget *parent = nullptr);
|
||||||
|
|
||||||
|
/// @brief Returns true if the button is enabled
|
||||||
|
///
|
||||||
|
/// An enabled button will emit interaction events and show mouse effects.
|
||||||
|
/// When disabled, only the content and border is shown.
|
||||||
|
///
|
||||||
|
/// By default, a button is enabled.
|
||||||
|
[[nodiscard]] bool enabled() const noexcept;
|
||||||
|
|
||||||
|
/// Setter for #enabled()
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
|
/// Returns true if the user is hovering over the button
|
||||||
|
[[nodiscard]] bool mouseOver() const noexcept;
|
||||||
|
|
||||||
|
/// Returns true if the left mouse button is held down
|
||||||
|
[[nodiscard]] bool mouseDown() const noexcept;
|
||||||
|
|
||||||
|
/// @brief Returns true if the menu is visible
|
||||||
|
///
|
||||||
|
/// @sa #menu(), #setMenu()
|
||||||
|
[[nodiscard]] bool menuVisible() const noexcept;
|
||||||
|
|
||||||
|
/// @brief Returns the current border color
|
||||||
|
///
|
||||||
|
/// If no color is set, this will return an invalid color.
|
||||||
|
///
|
||||||
|
/// The border is shown with a width of 1 above all other content if the
|
||||||
|
/// border color is valid.
|
||||||
|
///
|
||||||
|
/// By default, no border color is set.
|
||||||
|
[[nodiscard]] QColor borderColor() const noexcept;
|
||||||
|
|
||||||
|
/// Setter for #borderColor()
|
||||||
|
void setBorderColor(const QColor &color);
|
||||||
|
|
||||||
|
/// @brief Returns the current mouse effect color (if set)
|
||||||
|
///
|
||||||
|
/// The mouse effect color is used for hover and click effects.
|
||||||
|
///
|
||||||
|
/// By default, the color is based on the selected theme.
|
||||||
|
[[nodiscard]] std::optional<QColor> mouseEffectColor() const;
|
||||||
|
|
||||||
|
/// Setter for #mouseEffectColor()
|
||||||
|
void setMouseEffectColor(std::optional<QColor> color);
|
||||||
|
|
||||||
|
/// @brief Returns the menu associated with this button.
|
||||||
|
///
|
||||||
|
/// The menu is shown when pressing the left mouse button.
|
||||||
|
///
|
||||||
|
/// The return value is non-owned.
|
||||||
|
/// If no menu is associated, `nullptr` is returned.
|
||||||
|
///
|
||||||
|
/// @sa #menuVisible(), #leftMousePress()
|
||||||
|
[[nodiscard]] QMenu *menu() const;
|
||||||
|
|
||||||
|
/// Setter for #menu()
|
||||||
|
void setMenu(std::unique_ptr<QMenu> menu);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
/// @brief Emitted after the user left-clicked the button.
|
||||||
|
///
|
||||||
|
/// A click is only emitted if the user released the mouse above the button
|
||||||
|
/// and the button is enabled.
|
||||||
|
void leftClicked();
|
||||||
|
|
||||||
|
/// @brief Emitted after the user clicked the button with any mouse-button
|
||||||
|
///
|
||||||
|
/// A click is only emitted if the user released the mouse above the button
|
||||||
|
/// and the button is enabled.
|
||||||
|
///
|
||||||
|
/// @sa #leftClicked()
|
||||||
|
void clicked(Qt::MouseButton button);
|
||||||
|
|
||||||
|
/// @brief Emitted when the user presses the left mouse button.
|
||||||
|
///
|
||||||
|
/// Avoid using this event where possible and use #leftClicked().
|
||||||
|
void leftMousePress();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent * /*event*/) override;
|
||||||
|
|
||||||
|
/// @brief Paint the contents to be shown below the button
|
||||||
|
///
|
||||||
|
/// First, the content is painted, then hover and click effects and finally
|
||||||
|
/// the border.
|
||||||
|
/// The content is cached by default as it's assumed to be expensive to
|
||||||
|
/// repaint and repaints can occur frequently.
|
||||||
|
///
|
||||||
|
/// @sa #contentCacheEnabled()
|
||||||
|
virtual void paintContent(QPainter &painter) = 0;
|
||||||
|
|
||||||
|
/// @brief Paint hover and click effects.
|
||||||
|
///
|
||||||
|
/// This is provided for custom setups that override #paintEvent().
|
||||||
|
/// When possible, prefer #paintContent().
|
||||||
|
void fancyPaint(QPainter &painter);
|
||||||
|
|
||||||
|
/// @brief Indicate that the cache is invalid and needs to be repainted.
|
||||||
|
///
|
||||||
|
/// This calls update().
|
||||||
|
void invalidateContent();
|
||||||
|
|
||||||
|
/// @brief Returns true if the content drawn in #paintContent() should be
|
||||||
|
/// cached.
|
||||||
|
///
|
||||||
|
/// For complex static content, this makes sense, as the button is often
|
||||||
|
/// repainted when the user is hovering over it.
|
||||||
|
///
|
||||||
|
/// By default, the cache is disabled.
|
||||||
|
[[nodiscard]] bool contentCacheEnabled() const noexcept;
|
||||||
|
|
||||||
|
/// @brief Setter for #contentCacheEnabled()
|
||||||
|
///
|
||||||
|
/// When disabling the content-cache, the cached pixmap is destroyed.
|
||||||
|
void setContentCacheEnabled(bool enabled);
|
||||||
|
|
||||||
|
/// @brief Returns true if the content drawn in #paintContent() is fully
|
||||||
|
/// opaque.
|
||||||
|
///
|
||||||
|
/// If the content is fully opaque, the cached pixmap isn't filled with a
|
||||||
|
/// transparent color, but left in the default state.
|
||||||
|
///
|
||||||
|
/// @sa #setOpaqueContent()
|
||||||
|
[[nodiscard]] bool opaqueContent() const noexcept;
|
||||||
|
|
||||||
|
/// Setter for #opaqueContent()
|
||||||
|
void setOpaqueContent(bool opaqueContent);
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
void enterEvent(QEnterEvent * /*event*/) override;
|
||||||
|
#else
|
||||||
|
void enterEvent(QEvent * /*event*/) override;
|
||||||
|
#endif
|
||||||
|
void leaveEvent(QEvent *event) override;
|
||||||
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onMouseEffectTimeout();
|
||||||
|
void showMenu();
|
||||||
|
|
||||||
|
void paintButton(QPainter &painter);
|
||||||
|
|
||||||
|
QColor borderColor_;
|
||||||
|
|
||||||
|
QPoint mousePos_;
|
||||||
|
double hoverMultiplier_ = 0.0;
|
||||||
|
|
||||||
|
std::unique_ptr<QMenu> menu_;
|
||||||
|
|
||||||
|
QTimer effectTimer_;
|
||||||
|
std::vector<ClickEffect> clickEffects_;
|
||||||
|
std::optional<QColor> mouseEffectColor_;
|
||||||
|
|
||||||
|
bool enabled_ = true;
|
||||||
|
bool mouseOver_ = false;
|
||||||
|
bool mouseDown_ = false;
|
||||||
|
bool menuVisible_ = false;
|
||||||
|
|
||||||
|
QPixmap cachedPixmap_;
|
||||||
|
bool pixmapValid_ = false;
|
||||||
|
bool cachePixmap_ = false;
|
||||||
|
bool opaqueContent_ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#include "widgets/buttons/DimButton.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
DimButton::DimButton(BaseWidget *parent)
|
||||||
|
: Button(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DimButton::Dim DimButton::dim() const noexcept
|
||||||
|
{
|
||||||
|
return this->dim_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DimButton::setDim(Dim value)
|
||||||
|
{
|
||||||
|
this->dim_ = value;
|
||||||
|
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal DimButton::currentContentOpacity() const noexcept
|
||||||
|
{
|
||||||
|
if (this->dim_ == Dim::None || this->mouseOver())
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (this->dim_ == Dim::Some)
|
||||||
|
{
|
||||||
|
return 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.15;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "widgets/buttons/Button.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/// @brief A button with a #dim() setting for controlling the opacity of its
|
||||||
|
/// content.
|
||||||
|
///
|
||||||
|
/// This button doesn't paint anything.
|
||||||
|
///
|
||||||
|
/// @sa #currentContentOpacity()
|
||||||
|
class DimButton : public Button
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Dim : std::uint8_t {
|
||||||
|
/// Fully opaque (100% opcaity)
|
||||||
|
None,
|
||||||
|
/// Slightly transparent (70% opacity)
|
||||||
|
Some,
|
||||||
|
/// Almost transparent (15% opacity)
|
||||||
|
Lots,
|
||||||
|
};
|
||||||
|
|
||||||
|
DimButton(BaseWidget *parent = nullptr);
|
||||||
|
|
||||||
|
/// Returns the current dim level.
|
||||||
|
[[nodiscard]] Dim dim() const noexcept;
|
||||||
|
|
||||||
|
/// Setter for #dim()
|
||||||
|
void setDim(Dim value);
|
||||||
|
|
||||||
|
/// Returns the current opacity based on the current dim level.
|
||||||
|
[[nodiscard]] qreal currentContentOpacity() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Dim dim_ = Dim::Some;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
#include "util/InitUpdateButton.hpp"
|
#include "widgets/buttons/InitUpdateButton.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
|
#include "widgets/buttons/PixmapButton.hpp"
|
||||||
#include "widgets/dialogs/UpdateDialog.hpp"
|
#include "widgets/dialogs/UpdateDialog.hpp"
|
||||||
#include "widgets/helper/Button.hpp"
|
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
void initUpdateButton(Button &button,
|
void initUpdateButton(PixmapButton &button,
|
||||||
pajlada::Signals::SignalHolder &signalHolder)
|
pajlada::Signals::SignalHolder &signalHolder)
|
||||||
{
|
{
|
||||||
button.hide();
|
button.hide();
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace pajlada::Signals {
|
||||||
|
class SignalHolder;
|
||||||
|
} // namespace pajlada::Signals
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
class PixmapButton;
|
||||||
|
class UpdateDialog;
|
||||||
|
|
||||||
|
void initUpdateButton(PixmapButton &button,
|
||||||
|
pajlada::Signals::SignalHolder &signalHolder);
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#include "widgets/buttons/LabelButton.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
LabelButton::LabelButton(const QString &text, BaseWidget *parent, QSize padding)
|
||||||
|
: Button(parent)
|
||||||
|
, layout_(this)
|
||||||
|
, label_(text)
|
||||||
|
, padding_(padding)
|
||||||
|
{
|
||||||
|
this->layout_.setContentsMargins(0, 0, 0, 0);
|
||||||
|
this->layout_.addWidget(&this->label_);
|
||||||
|
this->label_.setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
this->label_.setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
this->updatePadding();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelButton::setText(const QString &text)
|
||||||
|
{
|
||||||
|
this->label_.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize LabelButton::padding() const noexcept
|
||||||
|
{
|
||||||
|
return this->padding_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelButton::setPadding(QSize padding)
|
||||||
|
{
|
||||||
|
if (this->padding_ == padding)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->padding_ = padding;
|
||||||
|
this->updatePadding();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelButton::enableRichText()
|
||||||
|
{
|
||||||
|
this->label_.setTextFormat(Qt::RichText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelButton::paintContent(QPainter &painter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void LabelButton::updatePadding()
|
||||||
|
{
|
||||||
|
auto x = this->padding_.width();
|
||||||
|
auto y = this->padding_.height();
|
||||||
|
this->label_.setContentsMargins(x, y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "widgets/buttons/Button.hpp"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/// @brief A button with a label on top.
|
||||||
|
///
|
||||||
|
/// The content can be set with #setText(), #setPixmap(), and #setMovie().
|
||||||
|
class LabelButton : public Button
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LabelButton(const QString &text = {}, BaseWidget *parent = nullptr,
|
||||||
|
QSize padding = {6, 0});
|
||||||
|
|
||||||
|
/// @brief Returns the current text
|
||||||
|
///
|
||||||
|
/// If no text has been set this will return an empty string.
|
||||||
|
[[nodiscard]] QString text() const;
|
||||||
|
|
||||||
|
/// @brief Sets the label's text to @a text.
|
||||||
|
///
|
||||||
|
/// Any previous content is cleared.
|
||||||
|
/// Supports Qt's HTML subset.
|
||||||
|
void setText(const QString &text);
|
||||||
|
|
||||||
|
/// @brief Returns the padding inside the button.
|
||||||
|
///
|
||||||
|
/// `width` is the padding applied horizontally (left and right).
|
||||||
|
/// `height` is the padding applied vertically (top and bottom).
|
||||||
|
///
|
||||||
|
/// By default, the button has no vertical padding and a horizontal padding of 6.
|
||||||
|
[[nodiscard]] QSize padding() const noexcept;
|
||||||
|
|
||||||
|
/// Setter for #padding()
|
||||||
|
void setPadding(QSize padding);
|
||||||
|
|
||||||
|
/// Sets the label to display rich text (Qt's HTML subset)
|
||||||
|
void enableRichText();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintContent(QPainter &painter) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updatePadding();
|
||||||
|
|
||||||
|
QHBoxLayout layout_;
|
||||||
|
QLabel label_;
|
||||||
|
QSize padding_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
#include "widgets/helper/NotebookButton.hpp"
|
#include "widgets/buttons/NotebookButton.hpp"
|
||||||
|
|
||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "common/QLogging.hpp"
|
#include "common/QLogging.hpp"
|
||||||
#include "singletons/Theme.hpp"
|
#include "singletons/Theme.hpp"
|
||||||
#include "widgets/helper/Button.hpp"
|
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
#include "widgets/splits/DraggedSplit.hpp"
|
#include "widgets/splits/DraggedSplit.hpp"
|
||||||
#include "widgets/splits/Split.hpp"
|
#include "widgets/splits/Split.hpp"
|
||||||
@@ -41,14 +40,12 @@ void NotebookButton::themeChangedEvent()
|
|||||||
this->setMouseEffectColor(this->theme->tabs.regular.text);
|
this->setMouseEffectColor(this->theme->tabs.regular.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotebookButton::paintEvent(QPaintEvent *event)
|
void NotebookButton::paintContent(QPainter &painter)
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
|
||||||
|
|
||||||
QColor background;
|
QColor background;
|
||||||
QColor foreground;
|
QColor foreground;
|
||||||
|
|
||||||
if (mouseDown_ || mouseOver_)
|
if (this->mouseDown() || this->mouseOver())
|
||||||
{
|
{
|
||||||
background = this->theme->tabs.regular.backgrounds.hover;
|
background = this->theme->tabs.regular.backgrounds.hover;
|
||||||
foreground = this->theme->tabs.regular.text;
|
foreground = this->theme->tabs.regular.text;
|
||||||
@@ -72,7 +69,7 @@ void NotebookButton::paintEvent(QPaintEvent *event)
|
|||||||
{
|
{
|
||||||
tmp = this->theme->tabs.selected.line.regular;
|
tmp = this->theme->tabs.selected.line.regular;
|
||||||
}
|
}
|
||||||
else if (!this->mouseOver_)
|
else if (!this->mouseOver())
|
||||||
{
|
{
|
||||||
tmp.setAlpha(180);
|
tmp.setAlpha(180);
|
||||||
}
|
}
|
||||||
@@ -136,22 +133,6 @@ void NotebookButton::paintEvent(QPaintEvent *event)
|
|||||||
|
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->paintButton(painter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NotebookButton::mouseReleaseEvent(QMouseEvent *event)
|
|
||||||
{
|
|
||||||
if (event->button() == Qt::LeftButton)
|
|
||||||
{
|
|
||||||
mouseDown_ = false;
|
|
||||||
|
|
||||||
update();
|
|
||||||
|
|
||||||
leftClicked();
|
|
||||||
}
|
|
||||||
|
|
||||||
Button::mouseReleaseEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotebookButton::dragEnterEvent(QDragEnterEvent *event)
|
void NotebookButton::dragEnterEvent(QDragEnterEvent *event)
|
||||||
@@ -173,7 +154,6 @@ void NotebookButton::dragEnterEvent(QDragEnterEvent *event)
|
|||||||
|
|
||||||
void NotebookButton::dragLeaveEvent(QDragLeaveEvent *)
|
void NotebookButton::dragLeaveEvent(QDragLeaveEvent *)
|
||||||
{
|
{
|
||||||
this->mouseDown_ = true;
|
|
||||||
this->update();
|
this->update();
|
||||||
|
|
||||||
auto *e =
|
auto *e =
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "widgets/helper/Button.hpp"
|
#include "widgets/buttons/Button.hpp"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
@@ -21,9 +21,9 @@ public:
|
|||||||
Icon getIcon() const;
|
Icon getIcon() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void paintContent(QPainter &painter) override;
|
||||||
|
|
||||||
void themeChangedEvent() override;
|
void themeChangedEvent() override;
|
||||||
void paintEvent(QPaintEvent *) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *) override;
|
|
||||||
void dragEnterEvent(QDragEnterEvent *) override;
|
void dragEnterEvent(QDragEnterEvent *) override;
|
||||||
void dragLeaveEvent(QDragLeaveEvent *) override;
|
void dragLeaveEvent(QDragLeaveEvent *) override;
|
||||||
void dropEvent(QDropEvent *) override;
|
void dropEvent(QDropEvent *) override;
|
||||||
@@ -31,9 +31,6 @@ protected:
|
|||||||
void hideEvent(QHideEvent *) override;
|
void hideEvent(QHideEvent *) override;
|
||||||
void showEvent(QShowEvent *) override;
|
void showEvent(QShowEvent *) override;
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void leftClicked();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Notebook *parent_ = nullptr;
|
Notebook *parent_ = nullptr;
|
||||||
QPoint mousePos_;
|
QPoint mousePos_;
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
#include "widgets/buttons/PixmapButton.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resizes a pixmap to a desired size.
|
||||||
|
* Does nothing if the target pixmap is already sized correctly.
|
||||||
|
*
|
||||||
|
* @param target The target pixmap.
|
||||||
|
* @param source The unscaled pixmap.
|
||||||
|
* @param size The desired device independent size.
|
||||||
|
* @param dpr The device pixel ratio of the target area. The size of the target in pixels will be `size * dpr`.
|
||||||
|
*/
|
||||||
|
void resizePixmap(QPixmap &target, const QPixmap &source, const QSize &size,
|
||||||
|
qreal dpr)
|
||||||
|
{
|
||||||
|
if (target.deviceIndependentSize() == size)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap resized = source;
|
||||||
|
resized.setDevicePixelRatio(dpr);
|
||||||
|
target = resized.scaled(size * dpr, Qt::IgnoreAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
PixmapButton::PixmapButton(BaseWidget *parent)
|
||||||
|
: DimButton(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap PixmapButton::pixmap() const
|
||||||
|
{
|
||||||
|
return this->pixmap_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixmapButton::setPixmap(const QPixmap &pixmap)
|
||||||
|
{
|
||||||
|
// Avoid updates if the pixmap didn't change
|
||||||
|
if (pixmap.cacheKey() == this->pixmap_.cacheKey())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->pixmap_ = pixmap;
|
||||||
|
this->resizedPixmap_ = {};
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PixmapButton::marginEnabled() const noexcept
|
||||||
|
{
|
||||||
|
return this->marginEnabled_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixmapButton::setMarginEnabled(bool enableMargin)
|
||||||
|
{
|
||||||
|
this->marginEnabled_ = enableMargin;
|
||||||
|
this->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PixmapButton::paintContent(QPainter &painter)
|
||||||
|
{
|
||||||
|
if (this->pixmap_.isNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
painter.setOpacity(this->currentContentOpacity());
|
||||||
|
|
||||||
|
QRect rect = this->rect();
|
||||||
|
|
||||||
|
int shift = 0;
|
||||||
|
if (this->marginEnabled_)
|
||||||
|
{
|
||||||
|
int margin =
|
||||||
|
this->height() < static_cast<int>(22 * this->scale()) ? 3 : 6;
|
||||||
|
|
||||||
|
shift = static_cast<int>(static_cast<float>(margin) * this->scale());
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.moveLeft(shift);
|
||||||
|
rect.setRight(rect.right() - (2 * shift));
|
||||||
|
rect.moveTop(shift);
|
||||||
|
rect.setBottom(rect.bottom() - (2 * shift));
|
||||||
|
|
||||||
|
resizePixmap(this->resizedPixmap_, this->pixmap_, rect.size(),
|
||||||
|
this->devicePixelRatio());
|
||||||
|
|
||||||
|
painter.drawPixmap(rect, this->resizedPixmap_);
|
||||||
|
|
||||||
|
painter.setOpacity(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "widgets/buttons/DimButton.hpp"
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/// @brief A (dimmable) button displaying a pixmap.
|
||||||
|
///
|
||||||
|
/// The pixmap is scaled to fit the button, ignoring any aspect ratio.
|
||||||
|
///
|
||||||
|
/// By default, a margin is added to the button (@see #marginEnabled()).
|
||||||
|
///
|
||||||
|
/// When possible, prefer using a `SvgButton` as it can scale its contents
|
||||||
|
/// to any size without blur and supports scaling and themeing.
|
||||||
|
///
|
||||||
|
/// @sa #setPixmap()
|
||||||
|
class PixmapButton : public DimButton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PixmapButton(BaseWidget *parent = nullptr);
|
||||||
|
|
||||||
|
/// Returns the current, non-scaled pixmap
|
||||||
|
[[nodiscard]] QPixmap pixmap() const;
|
||||||
|
|
||||||
|
/// Setter for #pixmap()
|
||||||
|
void setPixmap(const QPixmap &pixmap);
|
||||||
|
|
||||||
|
/// @brief Returns true if this button has margin.
|
||||||
|
///
|
||||||
|
/// The margin is dynamically calculated based on the UI-scale
|
||||||
|
/// and the size of the pixmap.
|
||||||
|
[[nodiscard]] bool marginEnabled() const noexcept;
|
||||||
|
|
||||||
|
/// Setter for #marginEnabled()
|
||||||
|
void setMarginEnabled(bool enableMargin);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintContent(QPainter &painter) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPixmap pixmap_;
|
||||||
|
QPixmap resizedPixmap_;
|
||||||
|
bool marginEnabled_ = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "widgets/helper/SignalLabel.hpp"
|
#include "widgets/buttons/SignalLabel.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
#include "widgets/buttons/SvgButton.hpp"
|
||||||
|
|
||||||
|
#include "singletons/Theme.hpp"
|
||||||
|
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
SvgButton::SvgButton(Src source, BaseWidget *parent, QSize padding)
|
||||||
|
: Button(parent)
|
||||||
|
, source_(std::move(source))
|
||||||
|
, svg_(new QSvgRenderer(this->currentSvgPath(), this))
|
||||||
|
, padding_(padding)
|
||||||
|
{
|
||||||
|
this->svg_->setAspectRatioMode(Qt::KeepAspectRatio);
|
||||||
|
this->setContentCacheEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgButton::setSource(Src source)
|
||||||
|
{
|
||||||
|
this->source_ = std::move(source);
|
||||||
|
this->svg_->load(this->currentSvgPath());
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgButton::setPadding(QSize padding)
|
||||||
|
{
|
||||||
|
if (this->padding_ == padding)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->padding_ = padding;
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgButton::themeChangedEvent()
|
||||||
|
{
|
||||||
|
Button::themeChangedEvent();
|
||||||
|
|
||||||
|
if (this->source_.dark == this->source_.light)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this->svg_->load(this->currentSvgPath());
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgButton::scaleChangedEvent(float scale)
|
||||||
|
{
|
||||||
|
Button::scaleChangedEvent(scale);
|
||||||
|
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgButton::resizeEvent(QResizeEvent *e)
|
||||||
|
{
|
||||||
|
Button::resizeEvent(e);
|
||||||
|
|
||||||
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgButton::paintContent(QPainter &painter)
|
||||||
|
{
|
||||||
|
QSize actualPadding = this->scale() * this->padding_;
|
||||||
|
QPoint topLeft{actualPadding.width(), actualPadding.height()};
|
||||||
|
QSize contentSize = this->size() - 2 * actualPadding;
|
||||||
|
this->svg_->render(&painter, {topLeft, contentSize});
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SvgButton::currentSvgPath() const
|
||||||
|
{
|
||||||
|
if (this->theme->isLightTheme())
|
||||||
|
{
|
||||||
|
return this->source_.light;
|
||||||
|
}
|
||||||
|
return this->source_.dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "widgets/buttons/Button.hpp"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class QSvgRenderer;
|
||||||
|
|
||||||
|
namespace chatterino {
|
||||||
|
|
||||||
|
/// @brief A button displaying SVGs.
|
||||||
|
///
|
||||||
|
/// The source can be specified per theme (dark/light)
|
||||||
|
/// and will get automatically updated when the theme changes.
|
||||||
|
///
|
||||||
|
/// To set the size, use #setInnerHeight(). The width is adjusted according
|
||||||
|
/// to the aspect ratio of the SVG. If the button should scale with the UI,
|
||||||
|
/// turn on auto-scaling (@see #setAutoScale()), which will scale the button
|
||||||
|
/// and padding according to the current UI-scale (linearly).
|
||||||
|
///
|
||||||
|
/// The button has #padding() around the SVG.
|
||||||
|
class SvgButton : public Button
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Source configuration for the button
|
||||||
|
struct Src {
|
||||||
|
/// Source to load in a dark theme
|
||||||
|
QString dark;
|
||||||
|
/// Source to load in a light theme
|
||||||
|
QString light;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] SvgButton(Src source, BaseWidget *parent = nullptr,
|
||||||
|
QSize padding = {6, 3});
|
||||||
|
|
||||||
|
/// Returns the current source configuration.
|
||||||
|
[[nodiscard]] Src source() const;
|
||||||
|
|
||||||
|
/// Setter for #source()
|
||||||
|
void setSource(Src source);
|
||||||
|
|
||||||
|
/// @brief Returns the padding inside the button.
|
||||||
|
///
|
||||||
|
/// `width` is the padding applied horizontally (left and right).
|
||||||
|
/// `height` is the padding applied vertically (top and bottom).
|
||||||
|
///
|
||||||
|
/// By default, the button has a vertical padding of 3 and a horizontal padding of 6.
|
||||||
|
[[nodiscard]] QSize padding() const;
|
||||||
|
|
||||||
|
/// Setter for #padding()
|
||||||
|
void setPadding(QSize padding);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void themeChangedEvent() override;
|
||||||
|
void scaleChangedEvent(float scale) override;
|
||||||
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
|
void paintContent(QPainter &painter) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]] QString currentSvgPath() const;
|
||||||
|
|
||||||
|
Src source_;
|
||||||
|
QSvgRenderer *svg_;
|
||||||
|
QSize padding_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace chatterino
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "widgets/helper/TitlebarButton.hpp"
|
#include "widgets/buttons/TitlebarButton.hpp"
|
||||||
|
|
||||||
#include "singletons/Theme.hpp"
|
#include "singletons/Theme.hpp"
|
||||||
|
|
||||||
@@ -6,9 +6,11 @@
|
|||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
TitleBarButton::TitleBarButton()
|
TitleBarButton::TitleBarButton(TitleBarButtonStyle style)
|
||||||
: Button(nullptr)
|
: DimButton(nullptr)
|
||||||
|
, style_(style)
|
||||||
{
|
{
|
||||||
|
this->setContentCacheEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBarButtonStyle TitleBarButton::getButtonStyle() const
|
TitleBarButtonStyle TitleBarButton::getButtonStyle() const
|
||||||
@@ -16,17 +18,20 @@ TitleBarButtonStyle TitleBarButton::getButtonStyle() const
|
|||||||
return this->style_;
|
return this->style_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleBarButton::setButtonStyle(TitleBarButtonStyle _style)
|
void TitleBarButton::setButtonStyle(TitleBarButtonStyle style)
|
||||||
{
|
{
|
||||||
this->style_ = _style;
|
this->style_ = style;
|
||||||
this->update();
|
this->invalidateContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleBarButton::paintEvent(QPaintEvent *event)
|
void TitleBarButton::themeChangedEvent()
|
||||||
{
|
{
|
||||||
QPainter painter(this);
|
this->invalidateContent();
|
||||||
|
}
|
||||||
|
|
||||||
painter.setOpacity(this->getCurrentDimAmount());
|
void TitleBarButton::paintContent(QPainter &painter)
|
||||||
|
{
|
||||||
|
painter.setOpacity(this->currentContentOpacity());
|
||||||
|
|
||||||
QColor color = this->theme->window.text;
|
QColor color = this->theme->window.text;
|
||||||
QColor background = this->theme->window.background;
|
QColor background = this->theme->window.background;
|
||||||
@@ -65,32 +70,8 @@ void TitleBarButton::paintEvent(QPaintEvent *event)
|
|||||||
painter.drawLine(rect.topRight(), rect.bottomLeft());
|
painter.drawLine(rect.topRight(), rect.bottomLeft());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TitleBarButtonStyle::User: {
|
|
||||||
color = "#999";
|
|
||||||
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
|
|
||||||
auto a = xD / 3;
|
|
||||||
QPainterPath path;
|
|
||||||
|
|
||||||
painter.save();
|
|
||||||
painter.translate(3, 3);
|
|
||||||
|
|
||||||
path.arcMoveTo(a, 4 * a, 6 * a, 6 * a, 0);
|
|
||||||
path.arcTo(a, 4 * a, 6 * a, 6 * a, 0, 180);
|
|
||||||
|
|
||||||
painter.fillPath(path, color);
|
|
||||||
|
|
||||||
painter.setBrush(background);
|
|
||||||
painter.drawEllipse(2 * a, 1 * a, 4 * a, 4 * a);
|
|
||||||
|
|
||||||
painter.setBrush(color);
|
|
||||||
painter.drawEllipse(2.5 * a, 1.5 * a, 3 * a + 1, 3 * a);
|
|
||||||
painter.restore();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TitleBarButtonStyle::Settings: {
|
case TitleBarButtonStyle::Settings: {
|
||||||
|
painter.setPen(color);
|
||||||
color = "#999";
|
color = "#999";
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
@@ -121,7 +102,7 @@ void TitleBarButton::paintEvent(QPaintEvent *event)
|
|||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->paintButton(painter);
|
painter.setOpacity(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleBarButton::ncEnter()
|
void TitleBarButton::ncEnter()
|
||||||
@@ -1,27 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "widgets/helper/Button.hpp"
|
#include "widgets/buttons/DimButton.hpp"
|
||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
enum class TitleBarButtonStyle {
|
enum class TitleBarButtonStyle : std::uint8_t {
|
||||||
None = 0,
|
None,
|
||||||
Minimize = 1,
|
Minimize,
|
||||||
Maximize = 2,
|
Maximize,
|
||||||
Unmaximize = 4,
|
Unmaximize,
|
||||||
Close = 8,
|
Close,
|
||||||
User = 16,
|
Settings,
|
||||||
Settings = 32,
|
|
||||||
StreamerMode = 64,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TitleBarButton : public Button
|
class TitleBarButton : public DimButton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TitleBarButton();
|
TitleBarButton(TitleBarButtonStyle style = {});
|
||||||
|
|
||||||
TitleBarButtonStyle getButtonStyle() const;
|
TitleBarButtonStyle getButtonStyle() const;
|
||||||
void setButtonStyle(TitleBarButtonStyle style_);
|
void setButtonStyle(TitleBarButtonStyle style);
|
||||||
|
|
||||||
/// Simulate a `mouseEnter` event.
|
/// Simulate a `mouseEnter` event.
|
||||||
void ncEnter();
|
void ncEnter();
|
||||||
@@ -42,7 +40,9 @@ public:
|
|||||||
void ncMouseRelease(QPoint at);
|
void ncMouseRelease(QPoint at);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *) override;
|
void themeChangedEvent() override;
|
||||||
|
|
||||||
|
void paintContent(QPainter &painter) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TitleBarButtonStyle style_{};
|
TitleBarButtonStyle style_{};
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "widgets/helper/TitlebarButtons.hpp"
|
#include "widgets/buttons/TitlebarButtons.hpp"
|
||||||
|
|
||||||
#ifdef USEWINSDK
|
#ifdef USEWINSDK
|
||||||
|
|
||||||
# include "widgets/helper/TitlebarButton.hpp"
|
# include "widgets/buttons/TitlebarButton.hpp"
|
||||||
|
|
||||||
# include <Windows.h>
|
# include <Windows.h>
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "providers/twitch/TwitchChannel.hpp"
|
#include "providers/twitch/TwitchChannel.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
#include "widgets/helper/Button.hpp"
|
#include "widgets/buttons/Button.hpp"
|
||||||
#include "widgets/helper/ChannelView.hpp"
|
#include "widgets/helper/ChannelView.hpp"
|
||||||
#include "widgets/helper/InvisibleSizeGrip.hpp"
|
#include "widgets/helper/InvisibleSizeGrip.hpp"
|
||||||
#include "widgets/Scrollbar.hpp"
|
#include "widgets/Scrollbar.hpp"
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
#include "widgets/BaseWindow.hpp"
|
#include "widgets/BaseWindow.hpp"
|
||||||
#include "widgets/helper/Button.hpp"
|
|
||||||
#include "widgets/helper/SettingsDialogTab.hpp"
|
#include "widgets/helper/SettingsDialogTab.hpp"
|
||||||
#include "widgets/settingspages/AboutPage.hpp"
|
#include "widgets/settingspages/AboutPage.hpp"
|
||||||
#include "widgets/settingspages/AccountsPage.hpp"
|
#include "widgets/settingspages/AccountsPage.hpp"
|
||||||
|
|||||||
@@ -26,9 +26,10 @@
|
|||||||
#include "util/Helpers.hpp"
|
#include "util/Helpers.hpp"
|
||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
#include "util/PostToThread.hpp"
|
#include "util/PostToThread.hpp"
|
||||||
|
#include "widgets/buttons/LabelButton.hpp"
|
||||||
|
#include "widgets/buttons/PixmapButton.hpp"
|
||||||
#include "widgets/dialogs/EditUserNotesDialog.hpp"
|
#include "widgets/dialogs/EditUserNotesDialog.hpp"
|
||||||
#include "widgets/helper/ChannelView.hpp"
|
#include "widgets/helper/ChannelView.hpp"
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
|
||||||
#include "widgets/helper/InvisibleSizeGrip.hpp"
|
#include "widgets/helper/InvisibleSizeGrip.hpp"
|
||||||
#include "widgets/helper/Line.hpp"
|
#include "widgets/helper/Line.hpp"
|
||||||
#include "widgets/Label.hpp"
|
#include "widgets/Label.hpp"
|
||||||
@@ -47,7 +48,6 @@
|
|||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr QStringView TEXT_FOLLOWERS = u"Followers: %1";
|
constexpr QStringView TEXT_FOLLOWERS = u"Followers: %1";
|
||||||
constexpr QStringView TEXT_CREATED = u"Created: %1";
|
constexpr QStringView TEXT_CREATED = u"Created: %1";
|
||||||
constexpr QStringView TEXT_TITLE = u"%1's Usercard - #%2";
|
constexpr QStringView TEXT_TITLE = u"%1's Usercard - #%2";
|
||||||
@@ -61,17 +61,17 @@ constexpr qsizetype NOTES_PREVIEW_LENGTH = 80;
|
|||||||
using namespace chatterino;
|
using namespace chatterino;
|
||||||
|
|
||||||
Label *addCopyableLabel(LayoutCreator<QHBoxLayout> box, const char *tooltip,
|
Label *addCopyableLabel(LayoutCreator<QHBoxLayout> box, const char *tooltip,
|
||||||
Button **copyButton = nullptr)
|
PixmapButton **copyButton = nullptr)
|
||||||
{
|
{
|
||||||
auto label = box.emplace<Label>();
|
auto label = box.emplace<Label>();
|
||||||
auto button = box.emplace<Button>();
|
auto button = box.emplace<PixmapButton>();
|
||||||
if (copyButton != nullptr)
|
if (copyButton != nullptr)
|
||||||
{
|
{
|
||||||
button.assign(copyButton);
|
button.assign(copyButton);
|
||||||
}
|
}
|
||||||
button->setPixmap(getApp()->getThemes()->buttons.copy);
|
button->setPixmap(getApp()->getThemes()->buttons.copy);
|
||||||
button->setScaleIndependentSize(18, 18);
|
button->setScaleIndependentSize(18, 18);
|
||||||
button->setDim(Button::Dim::Lots);
|
button->setDim(DimButton::Dim::Lots);
|
||||||
button->setToolTip(tooltip);
|
button->setToolTip(tooltip);
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
button.getElement(), &Button::leftClicked,
|
button.getElement(), &Button::leftClicked,
|
||||||
@@ -272,9 +272,9 @@ UserInfoPopup::UserInfoPopup(bool closeAutomatically, Split *split)
|
|||||||
{
|
{
|
||||||
// avatar
|
// avatar
|
||||||
auto avatar =
|
auto avatar =
|
||||||
head.emplace<Button>(nullptr).assign(&this->ui_.avatarButton);
|
head.emplace<PixmapButton>(nullptr).assign(&this->ui_.avatarButton);
|
||||||
avatar->setScaleIndependentSize(100, 100);
|
avatar->setScaleIndependentSize(100, 100);
|
||||||
avatar->setDim(Button::Dim::None);
|
avatar->setDim(DimButton::Dim::None);
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
avatar.getElement(), &Button::clicked,
|
avatar.getElement(), &Button::clicked,
|
||||||
[this](Qt::MouseButton button) {
|
[this](Qt::MouseButton button) {
|
||||||
@@ -409,22 +409,20 @@ UserInfoPopup::UserInfoPopup(bool closeAutomatically, Split *split)
|
|||||||
.assign(&this->ui_.ignoreHighlights);
|
.assign(&this->ui_.ignoreHighlights);
|
||||||
// visibility of this is updated in setData
|
// visibility of this is updated in setData
|
||||||
|
|
||||||
auto notesAdd =
|
user.emplace<LabelButton>("Add notes", this)
|
||||||
user.emplace<EffectLabel2>(this).assign(&this->ui_.notesAdd);
|
.assign(&this->ui_.notesAdd);
|
||||||
notesAdd->getLabel().setText("Add notes");
|
auto usercard = user.emplace<LabelButton>("Usercard", this)
|
||||||
auto usercard =
|
.assign(&this->ui_.usercardLabel);
|
||||||
user.emplace<EffectLabel2>(this).assign(&this->ui_.usercardLabel);
|
auto mod = user.emplace<PixmapButton>(this);
|
||||||
usercard->getLabel().setText("Usercard");
|
|
||||||
auto mod = user.emplace<Button>(this);
|
|
||||||
mod->setPixmap(getResources().buttons.mod);
|
mod->setPixmap(getResources().buttons.mod);
|
||||||
mod->setScaleIndependentSize(30, 30);
|
mod->setScaleIndependentSize(30, 30);
|
||||||
auto unmod = user.emplace<Button>(this);
|
auto unmod = user.emplace<PixmapButton>(this);
|
||||||
unmod->setPixmap(getResources().buttons.unmod);
|
unmod->setPixmap(getResources().buttons.unmod);
|
||||||
unmod->setScaleIndependentSize(30, 30);
|
unmod->setScaleIndependentSize(30, 30);
|
||||||
auto vip = user.emplace<Button>(this);
|
auto vip = user.emplace<PixmapButton>(this);
|
||||||
vip->setPixmap(getResources().buttons.vip);
|
vip->setPixmap(getResources().buttons.vip);
|
||||||
vip->setScaleIndependentSize(30, 30);
|
vip->setScaleIndependentSize(30, 30);
|
||||||
auto unvip = user.emplace<Button>(this);
|
auto unvip = user.emplace<PixmapButton>(this);
|
||||||
unvip->setPixmap(getResources().buttons.unvip);
|
unvip->setPixmap(getResources().buttons.unvip);
|
||||||
unvip->setScaleIndependentSize(30, 30);
|
unvip->setScaleIndependentSize(30, 30);
|
||||||
|
|
||||||
@@ -762,7 +760,7 @@ void UserInfoPopup::installEvents()
|
|||||||
|
|
||||||
// user notes
|
// user notes
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
this->ui_.notesAdd, &EffectLabel2::clicked, [this]() mutable {
|
this->ui_.notesAdd, &LabelButton::clicked, [this]() mutable {
|
||||||
if (this->editUserNotesDialog_.isNull())
|
if (this->editUserNotesDialog_.isNull())
|
||||||
{
|
{
|
||||||
this->editUserNotesDialog_ = new EditUserNotesDialog(this);
|
this->editUserNotesDialog_ = new EditUserNotesDialog(this);
|
||||||
@@ -1185,7 +1183,7 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||||||
|
|
||||||
const auto addButton = [&](Action action, const QString &title,
|
const auto addButton = [&](Action action, const QString &title,
|
||||||
const QPixmap &pixmap) {
|
const QPixmap &pixmap) {
|
||||||
auto button = addLayout(title).emplace<Button>(nullptr);
|
auto button = addLayout(title).emplace<PixmapButton>(nullptr);
|
||||||
button->setPixmap(pixmap);
|
button->setPixmap(pixmap);
|
||||||
button->setScaleIndependentSize(buttonHeight, buttonHeight);
|
button->setScaleIndependentSize(buttonHeight, buttonHeight);
|
||||||
button->setBorderColor(QColor(255, 255, 255, 127));
|
button->setBorderColor(QColor(255, 255, 255, 127));
|
||||||
@@ -1201,8 +1199,9 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||||||
|
|
||||||
for (const auto &item : getSettings()->timeoutButtons.getValue())
|
for (const auto &item : getSettings()->timeoutButtons.getValue())
|
||||||
{
|
{
|
||||||
auto a = hbox.emplace<EffectLabel2>();
|
auto a = hbox.emplace<LabelButton>();
|
||||||
a->getLabel().setText(QString::number(item.second) + item.first);
|
a->setPadding({0, 0});
|
||||||
|
a->setText(QString::number(item.second) + item.first);
|
||||||
|
|
||||||
a->setScaleIndependentSize(buttonWidth, buttonHeight);
|
a->setScaleIndependentSize(buttonWidth, buttonHeight);
|
||||||
a->setBorderColor(borderColor);
|
a->setBorderColor(borderColor);
|
||||||
@@ -1210,7 +1209,7 @@ UserInfoPopup::TimeoutWidget::TimeoutWidget()
|
|||||||
const auto pair =
|
const auto pair =
|
||||||
std::make_pair(Action::Timeout, calculateTimeoutDuration(item));
|
std::make_pair(Action::Timeout, calculateTimeoutDuration(item));
|
||||||
|
|
||||||
QObject::connect(a.getElement(), &EffectLabel2::leftClicked,
|
QObject::connect(a.getElement(), &LabelButton::leftClicked,
|
||||||
[this, pair] {
|
[this, pair] {
|
||||||
this->buttonClicked.invoke(pair);
|
this->buttonClicked.invoke(pair);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "widgets/DraggablePopup.hpp"
|
#include "widgets/DraggablePopup.hpp"
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
|
||||||
|
|
||||||
#include <pajlada/signals/scoped-connection.hpp>
|
#include <pajlada/signals/scoped-connection.hpp>
|
||||||
#include <pajlada/signals/signal.hpp>
|
#include <pajlada/signals/signal.hpp>
|
||||||
@@ -17,6 +16,8 @@ class Label;
|
|||||||
class EditUserNotesDialog;
|
class EditUserNotesDialog;
|
||||||
class ChannelView;
|
class ChannelView;
|
||||||
class Split;
|
class Split;
|
||||||
|
class LabelButton;
|
||||||
|
class PixmapButton;
|
||||||
|
|
||||||
class UserInfoPopup final : public DraggablePopup
|
class UserInfoPopup final : public DraggablePopup
|
||||||
{
|
{
|
||||||
@@ -72,8 +73,8 @@ private:
|
|||||||
const bool closeAutomatically_;
|
const bool closeAutomatically_;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
Button *avatarButton = nullptr;
|
PixmapButton *avatarButton = nullptr;
|
||||||
Button *localizedNameCopyButton = nullptr;
|
PixmapButton *localizedNameCopyButton = nullptr;
|
||||||
|
|
||||||
Label *nameLabel = nullptr;
|
Label *nameLabel = nullptr;
|
||||||
Label *localizedNameLabel = nullptr;
|
Label *localizedNameLabel = nullptr;
|
||||||
@@ -87,12 +88,12 @@ private:
|
|||||||
QCheckBox *block = nullptr;
|
QCheckBox *block = nullptr;
|
||||||
QCheckBox *ignoreHighlights = nullptr;
|
QCheckBox *ignoreHighlights = nullptr;
|
||||||
Label *notesPreview = nullptr;
|
Label *notesPreview = nullptr;
|
||||||
EffectLabel2 *notesAdd = nullptr;
|
LabelButton *notesAdd = nullptr;
|
||||||
|
|
||||||
Label *noMessagesLabel = nullptr;
|
Label *noMessagesLabel = nullptr;
|
||||||
ChannelView *latestMessages = nullptr;
|
ChannelView *latestMessages = nullptr;
|
||||||
|
|
||||||
EffectLabel2 *usercardLabel = nullptr;
|
LabelButton *usercardLabel = nullptr;
|
||||||
} ui_;
|
} ui_;
|
||||||
|
|
||||||
QPointer<EditUserNotesDialog> editUserNotesDialog_;
|
QPointer<EditUserNotesDialog> editUserNotesDialog_;
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "widgets/BaseWidget.hpp"
|
|
||||||
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QMouseEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPoint>
|
|
||||||
#include <QSvgRenderer>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
class Button : public BaseWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
struct ClickEffect {
|
|
||||||
double progress = 0.0;
|
|
||||||
QPoint position;
|
|
||||||
|
|
||||||
ClickEffect(QPoint _position)
|
|
||||||
: position(_position)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum class Dim { None, Some, Lots };
|
|
||||||
|
|
||||||
Button(BaseWidget *parent = nullptr);
|
|
||||||
|
|
||||||
void setMouseEffectColor(std::optional<QColor> color);
|
|
||||||
void setPixmap(const QPixmap &pixmap_);
|
|
||||||
void setSvgResource(const QString &resourcePath);
|
|
||||||
const QPixmap &getPixmap() const;
|
|
||||||
|
|
||||||
void setDim(Dim value);
|
|
||||||
Dim getDim() const;
|
|
||||||
qreal getCurrentDimAmount() const;
|
|
||||||
|
|
||||||
void setEnable(bool value);
|
|
||||||
bool getEnable() const;
|
|
||||||
|
|
||||||
void setEnableMargin(bool value);
|
|
||||||
bool getEnableMargin() const;
|
|
||||||
|
|
||||||
void setBorderColor(const QColor &color);
|
|
||||||
const QColor &getBorderColor() const;
|
|
||||||
|
|
||||||
void setMenu(std::unique_ptr<QMenu> menu);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void leftClicked();
|
|
||||||
void clicked(Qt::MouseButton button);
|
|
||||||
void leftMousePress();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void paintEvent(QPaintEvent * /*event*/) override;
|
|
||||||
|
|
||||||
/// Paint this button.
|
|
||||||
/// This is intended for child classes that may want to paint the overlay.
|
|
||||||
/// This function should be used after rendering the custom button,
|
|
||||||
/// because the painter's state will be modified by this function.
|
|
||||||
void paintButton(QPainter &painter);
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void enterEvent(QEnterEvent * /*event*/) override;
|
|
||||||
#else
|
|
||||||
void enterEvent(QEvent * /*event*/) override;
|
|
||||||
#endif
|
|
||||||
void leaveEvent(QEvent *) override;
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent *event) override;
|
|
||||||
|
|
||||||
void fancyPaint(QPainter &painter);
|
|
||||||
|
|
||||||
bool enabled_{true};
|
|
||||||
bool selected_{false};
|
|
||||||
bool mouseOver_{false};
|
|
||||||
bool mouseDown_{false};
|
|
||||||
bool menuVisible_{false};
|
|
||||||
|
|
||||||
private:
|
|
||||||
void onMouseEffectTimeout();
|
|
||||||
void showMenu();
|
|
||||||
|
|
||||||
int getMargin() const;
|
|
||||||
|
|
||||||
QColor borderColor_{};
|
|
||||||
QPixmap pixmap_{};
|
|
||||||
QSvgRenderer *svgRenderer{};
|
|
||||||
QString svgResourcePath;
|
|
||||||
QPixmap resizedPixmap_{};
|
|
||||||
Dim dimPixmap_{Dim::Some};
|
|
||||||
bool enableMargin_{true};
|
|
||||||
QPoint mousePos_{};
|
|
||||||
double hoverMultiplier_{0.0};
|
|
||||||
QTimer effectTimer_{};
|
|
||||||
std::vector<ClickEffect> clickEffects_{};
|
|
||||||
std::optional<QColor> mouseEffectColor_{};
|
|
||||||
std::unique_ptr<QMenu> menu_{};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
||||||
@@ -35,10 +35,10 @@
|
|||||||
#include "util/IncognitoBrowser.hpp"
|
#include "util/IncognitoBrowser.hpp"
|
||||||
#include "util/QMagicEnum.hpp"
|
#include "util/QMagicEnum.hpp"
|
||||||
#include "util/Twitch.hpp"
|
#include "util/Twitch.hpp"
|
||||||
|
#include "widgets/buttons/LabelButton.hpp"
|
||||||
#include "widgets/dialogs/ReplyThreadPopup.hpp"
|
#include "widgets/dialogs/ReplyThreadPopup.hpp"
|
||||||
#include "widgets/dialogs/SettingsDialog.hpp"
|
#include "widgets/dialogs/SettingsDialog.hpp"
|
||||||
#include "widgets/dialogs/UserInfoPopup.hpp"
|
#include "widgets/dialogs/UserInfoPopup.hpp"
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
|
||||||
#include "widgets/helper/ScrollbarHighlight.hpp"
|
#include "widgets/helper/ScrollbarHighlight.hpp"
|
||||||
#include "widgets/helper/SearchPopup.hpp"
|
#include "widgets/helper/SearchPopup.hpp"
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
@@ -372,19 +372,17 @@ ChannelView::ChannelView(InternalCtor /*tag*/, QWidget *parent, Split *split,
|
|||||||
|
|
||||||
void ChannelView::initializeLayout()
|
void ChannelView::initializeLayout()
|
||||||
{
|
{
|
||||||
this->goToBottom_ = new EffectLabel(this, 0);
|
this->goToBottom_ = new LabelButton("More messages below", this);
|
||||||
this->goToBottom_->setStyleSheet(
|
this->goToBottom_->setStyleSheet(
|
||||||
"background-color: rgba(0,0,0,0.66); color: #FFF;");
|
"background-color: rgba(0,0,0,0.66); color: #FFF;");
|
||||||
this->goToBottom_->getLabel().setText("More messages below");
|
|
||||||
this->goToBottom_->setVisible(false);
|
this->goToBottom_->setVisible(false);
|
||||||
|
|
||||||
QObject::connect(
|
QObject::connect(this->goToBottom_, &Button::leftClicked, this, [this] {
|
||||||
this->goToBottom_, &EffectLabel::leftClicked, this, [this] {
|
QTimer::singleShot(180, this, [this] {
|
||||||
QTimer::singleShot(180, this, [this] {
|
this->scrollBar_->scrollToBottom(
|
||||||
this->scrollBar_->scrollToBottom(
|
getSettings()->enableSmoothScrollingNewMessages.getValue());
|
||||||
getSettings()->enableSmoothScrollingNewMessages.getValue());
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelView::initializeScrollbar()
|
void ChannelView::initializeScrollbar()
|
||||||
@@ -624,7 +622,7 @@ void ChannelView::scaleChangedEvent(float scale)
|
|||||||
std::max<float>(
|
std::max<float>(
|
||||||
0.01, this->logicalDpiX() * this->devicePixelRatioF());
|
0.01, this->logicalDpiX() * this->devicePixelRatioF());
|
||||||
#endif
|
#endif
|
||||||
this->goToBottom_->getLabel().setFont(
|
this->goToBottom_->setFont(
|
||||||
getApp()->getFonts()->getFont(FontStyle::UiMedium, factor));
|
getApp()->getFonts()->getFont(FontStyle::UiMedium, factor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ enum class MessageElementFlag : int64_t;
|
|||||||
using MessageElementFlags = FlagsEnum<MessageElementFlag>;
|
using MessageElementFlags = FlagsEnum<MessageElementFlag>;
|
||||||
|
|
||||||
class Scrollbar;
|
class Scrollbar;
|
||||||
class EffectLabel;
|
class LabelButton;
|
||||||
struct Link;
|
struct Link;
|
||||||
class MessageLayoutElement;
|
class MessageLayoutElement;
|
||||||
class Split;
|
class Split;
|
||||||
@@ -381,7 +381,7 @@ private:
|
|||||||
Split *split_;
|
Split *split_;
|
||||||
|
|
||||||
Scrollbar *scrollBar_;
|
Scrollbar *scrollBar_;
|
||||||
EffectLabel *goToBottom_{};
|
LabelButton *goToBottom_{};
|
||||||
bool showScrollBar_ = false;
|
bool showScrollBar_ = false;
|
||||||
|
|
||||||
FilterSetPtr channelFilters_;
|
FilterSetPtr channelFilters_;
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
#include "widgets/helper/EffectLabel.hpp"
|
|
||||||
|
|
||||||
#include <QBrush>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
EffectLabel::EffectLabel(BaseWidget *parent, int spacing)
|
|
||||||
: Button(parent)
|
|
||||||
, label_(this)
|
|
||||||
{
|
|
||||||
setLayout(&this->hbox_);
|
|
||||||
|
|
||||||
this->label_.setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
this->hbox_.setContentsMargins(0, 0, 0, 0);
|
|
||||||
this->hbox_.addSpacing(spacing);
|
|
||||||
this->hbox_.addWidget(&this->label_);
|
|
||||||
this->hbox_.addSpacing(spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
EffectLabel2::EffectLabel2(BaseWidget *parent, int padding)
|
|
||||||
: Button(parent)
|
|
||||||
, label_(this)
|
|
||||||
{
|
|
||||||
auto *hbox = new QHBoxLayout(this);
|
|
||||||
this->setLayout(hbox);
|
|
||||||
|
|
||||||
// this->label_.setAlignment(Qt::AlignCenter);
|
|
||||||
this->label_.setCentered(true);
|
|
||||||
|
|
||||||
hbox->setContentsMargins(0, 0, 0, 0);
|
|
||||||
// hbox.addSpacing(spacing);
|
|
||||||
hbox->addWidget(&this->label_);
|
|
||||||
// hbox.addSpacing(spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
Label &EffectLabel2::getLabel()
|
|
||||||
{
|
|
||||||
return this->label_;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "widgets/helper/Button.hpp"
|
|
||||||
#include "widgets/helper/SignalLabel.hpp"
|
|
||||||
#include "widgets/Label.hpp"
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
namespace chatterino {
|
|
||||||
|
|
||||||
class EffectLabel : public Button
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit EffectLabel(BaseWidget *parent = nullptr, int spacing = 6);
|
|
||||||
|
|
||||||
SignalLabel &getLabel()
|
|
||||||
{
|
|
||||||
return this->label_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QHBoxLayout hbox_;
|
|
||||||
SignalLabel label_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EffectLabel2 : public Button
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit EffectLabel2(BaseWidget *parent = nullptr, int padding = 6);
|
|
||||||
|
|
||||||
Label &getLabel();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Label label_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace chatterino
|
|
||||||
@@ -87,6 +87,7 @@ NotebookTab::NotebookTab(Notebook *notebook)
|
|||||||
, notebook_(notebook)
|
, notebook_(notebook)
|
||||||
, menu_(this)
|
, menu_(this)
|
||||||
{
|
{
|
||||||
|
this->setContentCacheEnabled(false);
|
||||||
this->setAcceptDrops(true);
|
this->setAcceptDrops(true);
|
||||||
|
|
||||||
this->positionChangedAnimation_.setEasingCurve(
|
this->positionChangedAnimation_.setEasingCurve(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/Common.hpp"
|
#include "common/Common.hpp"
|
||||||
#include "widgets/helper/Button.hpp"
|
#include "widgets/buttons/Button.hpp"
|
||||||
#include "widgets/helper/ChannelView.hpp"
|
#include "widgets/helper/ChannelView.hpp"
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
|
|
||||||
@@ -91,6 +91,9 @@ protected:
|
|||||||
void themeChangedEvent() override;
|
void themeChangedEvent() override;
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *) override;
|
void paintEvent(QPaintEvent *) override;
|
||||||
|
void paintContent(QPainter &painter) override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent *event) override;
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "widgets/helper/TitlebarButton.hpp"
|
#include "widgets/buttons/TitlebarButton.hpp"
|
||||||
|
|
||||||
#include <QPropertyAnimation>
|
#include <QPropertyAnimation>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
#include "util/RemoveScrollAreaBackground.hpp"
|
#include "util/RemoveScrollAreaBackground.hpp"
|
||||||
#include "widgets/BasePopup.hpp"
|
#include "widgets/BasePopup.hpp"
|
||||||
|
#include "widgets/buttons/SignalLabel.hpp"
|
||||||
#include "widgets/layout/FlowLayout.hpp"
|
#include "widgets/layout/FlowLayout.hpp"
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "Application.hpp"
|
#include "Application.hpp"
|
||||||
#include "common/ChatterinoSetting.hpp"
|
#include "common/ChatterinoSetting.hpp"
|
||||||
#include "singletons/WindowManager.hpp"
|
#include "singletons/WindowManager.hpp"
|
||||||
#include "widgets/helper/SignalLabel.hpp"
|
#include "widgets/buttons/SignalLabel.hpp"
|
||||||
|
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
#include <pajlada/signals/signalholder.hpp>
|
#include <pajlada/signals/signalholder.hpp>
|
||||||
|
|||||||
@@ -20,9 +20,10 @@
|
|||||||
#include "singletons/WindowManager.hpp"
|
#include "singletons/WindowManager.hpp"
|
||||||
#include "util/Helpers.hpp"
|
#include "util/Helpers.hpp"
|
||||||
#include "util/LayoutHelper.hpp"
|
#include "util/LayoutHelper.hpp"
|
||||||
|
#include "widgets/buttons/LabelButton.hpp"
|
||||||
|
#include "widgets/buttons/PixmapButton.hpp"
|
||||||
#include "widgets/dialogs/SettingsDialog.hpp"
|
#include "widgets/dialogs/SettingsDialog.hpp"
|
||||||
#include "widgets/helper/CommonTexts.hpp"
|
#include "widgets/helper/CommonTexts.hpp"
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
|
||||||
#include "widgets/Label.hpp"
|
#include "widgets/Label.hpp"
|
||||||
#include "widgets/splits/Split.hpp"
|
#include "widgets/splits/Split.hpp"
|
||||||
#include "widgets/splits/SplitContainer.hpp"
|
#include "widgets/splits/SplitContainer.hpp"
|
||||||
@@ -296,13 +297,13 @@ void SplitHeader::initializeLayout()
|
|||||||
w->setScaleIndependentSize(8, 4);
|
w->setScaleIndependentSize(8, 4);
|
||||||
}),
|
}),
|
||||||
// mode
|
// mode
|
||||||
this->modeButton_ = makeWidget<EffectLabel>([&](auto w) {
|
this->modeButton_ = makeWidget<LabelButton>([&](auto w) {
|
||||||
w->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
w->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||||
w->hide();
|
w->hide();
|
||||||
w->setMenu(this->createChatModeMenu());
|
w->setMenu(this->createChatModeMenu());
|
||||||
}),
|
}),
|
||||||
// moderator
|
// moderator
|
||||||
this->moderationButton_ = makeWidget<Button>([&](auto w) {
|
this->moderationButton_ = makeWidget<PixmapButton>([&](auto w) {
|
||||||
QObject::connect(
|
QObject::connect(
|
||||||
w, &Button::clicked, this,
|
w, &Button::clicked, this,
|
||||||
[this, w](Qt::MouseButton button) mutable {
|
[this, w](Qt::MouseButton button) mutable {
|
||||||
@@ -323,7 +324,9 @@ void SplitHeader::initializeLayout()
|
|||||||
|
|
||||||
this->split_->setModerationMode(
|
this->split_->setModerationMode(
|
||||||
!moderationMode);
|
!moderationMode);
|
||||||
w->setDim(Button::Dim(moderationMode));
|
w->setDim(moderationMode
|
||||||
|
? DimButton::Dim::Some
|
||||||
|
: DimButton::Dim::None);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -337,22 +340,22 @@ void SplitHeader::initializeLayout()
|
|||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
// chatter list
|
// chatter list
|
||||||
this->chattersButton_ = makeWidget<Button>([&](auto w) {
|
this->chattersButton_ = makeWidget<PixmapButton>([&](auto w) {
|
||||||
QObject::connect(w, &Button::leftClicked, this, [this]() {
|
QObject::connect(w, &Button::leftClicked, this, [this]() {
|
||||||
this->split_->showChatterList();
|
this->split_->showChatterList();
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
// dropdown
|
// dropdown
|
||||||
this->dropdownButton_ = makeWidget<Button>([&](auto w) {
|
this->dropdownButton_ = makeWidget<PixmapButton>([&](auto w) {
|
||||||
/// XXX: this never gets disconnected
|
/// XXX: this never gets disconnected
|
||||||
QObject::connect(w, &Button::leftMousePress, this, [this] {
|
QObject::connect(w, &Button::leftMousePress, this, [this] {
|
||||||
this->dropdownButton_->setMenu(this->createMainMenu());
|
this->dropdownButton_->setMenu(this->createMainMenu());
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
// add split
|
// add split
|
||||||
this->addButton_ = makeWidget<Button>([&](auto w) {
|
this->addButton_ = makeWidget<PixmapButton>([&](auto w) {
|
||||||
w->setPixmap(getResources().buttons.addSplitDark);
|
w->setPixmap(getResources().buttons.addSplitDark);
|
||||||
w->setEnableMargin(false);
|
w->setMarginEnabled(false);
|
||||||
|
|
||||||
QObject::connect(w, &Button::leftClicked, this, [this]() {
|
QObject::connect(w, &Button::leftClicked, this, [this]() {
|
||||||
this->split_->addSibling();
|
this->split_->addSibling();
|
||||||
@@ -725,7 +728,7 @@ void SplitHeader::updateRoomModes()
|
|||||||
if (auto *twitchChannel =
|
if (auto *twitchChannel =
|
||||||
dynamic_cast<TwitchChannel *>(this->split_->getChannel().get()))
|
dynamic_cast<TwitchChannel *>(this->split_->getChannel().get()))
|
||||||
{
|
{
|
||||||
this->modeButton_->setEnable(twitchChannel->hasModRights());
|
this->modeButton_->setEnabled(twitchChannel->hasModRights());
|
||||||
|
|
||||||
QString text;
|
QString text;
|
||||||
{
|
{
|
||||||
@@ -746,7 +749,7 @@ void SplitHeader::updateRoomModes()
|
|||||||
|
|
||||||
if (!text.isEmpty())
|
if (!text.isEmpty())
|
||||||
{
|
{
|
||||||
this->modeButton_->getLabel().setText(text);
|
this->modeButton_->setText(text);
|
||||||
this->modeButton_->show();
|
this->modeButton_->show();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
namespace chatterino {
|
namespace chatterino {
|
||||||
|
|
||||||
class Button;
|
class PixmapButton;
|
||||||
class EffectLabel;
|
class LabelButton;
|
||||||
class Label;
|
class Label;
|
||||||
class Split;
|
class Split;
|
||||||
|
|
||||||
@@ -54,7 +54,6 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void initializeLayout();
|
void initializeLayout();
|
||||||
void initializeModeSignals(EffectLabel &label);
|
|
||||||
std::unique_ptr<QMenu> createMainMenu();
|
std::unique_ptr<QMenu> createMainMenu();
|
||||||
std::unique_ptr<QMenu> createChatModeMenu();
|
std::unique_ptr<QMenu> createChatModeMenu();
|
||||||
|
|
||||||
@@ -76,19 +75,19 @@ private:
|
|||||||
std::chrono::steady_clock::time_point lastReloadedSubEmotes_;
|
std::chrono::steady_clock::time_point lastReloadedSubEmotes_;
|
||||||
|
|
||||||
// ui
|
// ui
|
||||||
Button *dropdownButton_{};
|
PixmapButton *dropdownButton_{};
|
||||||
Label *titleLabel_{};
|
Label *titleLabel_{};
|
||||||
|
|
||||||
EffectLabel *modeButton_{};
|
LabelButton *modeButton_{};
|
||||||
QAction *modeActionSetEmote{};
|
QAction *modeActionSetEmote{};
|
||||||
QAction *modeActionSetSub{};
|
QAction *modeActionSetSub{};
|
||||||
QAction *modeActionSetSlow{};
|
QAction *modeActionSetSlow{};
|
||||||
QAction *modeActionSetR9k{};
|
QAction *modeActionSetR9k{};
|
||||||
QAction *modeActionSetFollowers{};
|
QAction *modeActionSetFollowers{};
|
||||||
|
|
||||||
Button *moderationButton_{};
|
PixmapButton *moderationButton_{};
|
||||||
Button *chattersButton_{};
|
PixmapButton *chattersButton_{};
|
||||||
Button *addButton_{};
|
PixmapButton *addButton_{};
|
||||||
|
|
||||||
// states
|
// states
|
||||||
QPoint dragStart_{};
|
QPoint dragStart_{};
|
||||||
|
|||||||
@@ -10,13 +10,15 @@
|
|||||||
#include "providers/twitch/TwitchChannel.hpp"
|
#include "providers/twitch/TwitchChannel.hpp"
|
||||||
#include "providers/twitch/TwitchCommon.hpp"
|
#include "providers/twitch/TwitchCommon.hpp"
|
||||||
#include "providers/twitch/TwitchIrcServer.hpp"
|
#include "providers/twitch/TwitchIrcServer.hpp"
|
||||||
|
#include "singletons/Fonts.hpp"
|
||||||
#include "singletons/Settings.hpp"
|
#include "singletons/Settings.hpp"
|
||||||
#include "singletons/Theme.hpp"
|
#include "singletons/Theme.hpp"
|
||||||
#include "util/Helpers.hpp"
|
#include "util/Helpers.hpp"
|
||||||
#include "util/LayoutCreator.hpp"
|
#include "util/LayoutCreator.hpp"
|
||||||
|
#include "widgets/buttons/LabelButton.hpp"
|
||||||
|
#include "widgets/buttons/SvgButton.hpp"
|
||||||
#include "widgets/dialogs/EmotePopup.hpp"
|
#include "widgets/dialogs/EmotePopup.hpp"
|
||||||
#include "widgets/helper/ChannelView.hpp"
|
#include "widgets/helper/ChannelView.hpp"
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
|
||||||
#include "widgets/helper/MessageView.hpp"
|
#include "widgets/helper/MessageView.hpp"
|
||||||
#include "widgets/helper/ResizingTextEdit.hpp"
|
#include "widgets/helper/ResizingTextEdit.hpp"
|
||||||
#include "widgets/Notebook.hpp"
|
#include "widgets/Notebook.hpp"
|
||||||
@@ -112,8 +114,14 @@ void SplitInput::initLayout()
|
|||||||
|
|
||||||
replyHbox->addStretch(1);
|
replyHbox->addStretch(1);
|
||||||
|
|
||||||
auto replyCancelButton =
|
auto replyCancelButton = replyHbox
|
||||||
replyHbox.emplace<Button>().assign(&this->ui_.cancelReplyButton);
|
.emplace<SvgButton>(
|
||||||
|
SvgButton::Src{
|
||||||
|
.dark = ":/buttons/cancel.svg",
|
||||||
|
.light = ":/buttons/cancelDark.svg",
|
||||||
|
},
|
||||||
|
nullptr, QSize{4, 0})
|
||||||
|
.assign(&this->ui_.cancelReplyButton);
|
||||||
|
|
||||||
replyCancelButton->hide();
|
replyCancelButton->hide();
|
||||||
replyLabel->hide();
|
replyLabel->hide();
|
||||||
@@ -133,11 +141,10 @@ void SplitInput::initLayout()
|
|||||||
connect(textEdit.getElement(), &ResizingTextEdit::textChanged, this,
|
connect(textEdit.getElement(), &ResizingTextEdit::textChanged, this,
|
||||||
&SplitInput::editTextChanged);
|
&SplitInput::editTextChanged);
|
||||||
|
|
||||||
hboxLayout.emplace<EffectLabel>().assign(&this->ui_.sendButton);
|
hboxLayout.emplace<LabelButton>("SEND").assign(&this->ui_.sendButton);
|
||||||
this->ui_.sendButton->getLabel().setText("SEND");
|
|
||||||
this->ui_.sendButton->hide();
|
this->ui_.sendButton->hide();
|
||||||
|
|
||||||
QObject::connect(this->ui_.sendButton, &EffectLabel::leftClicked, [this] {
|
QObject::connect(this->ui_.sendButton, &Button::leftClicked, [this] {
|
||||||
std::vector<QString> arguments;
|
std::vector<QString> arguments;
|
||||||
this->handleSendMessage(arguments);
|
this->handleSendMessage(arguments);
|
||||||
});
|
});
|
||||||
@@ -164,7 +171,13 @@ void SplitInput::initLayout()
|
|||||||
textEditLength->setAlignment(Qt::AlignRight);
|
textEditLength->setAlignment(Qt::AlignRight);
|
||||||
|
|
||||||
box->addStretch(1);
|
box->addStretch(1);
|
||||||
box.emplace<Button>().assign(&this->ui_.emoteButton);
|
box.emplace<SvgButton>(
|
||||||
|
SvgButton::Src{
|
||||||
|
.dark = ":/buttons/emote.svg",
|
||||||
|
.light = ":/buttons/emoteDark.svg",
|
||||||
|
},
|
||||||
|
nullptr, QSize{6, 3})
|
||||||
|
.assign(&this->ui_.emoteButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- misc
|
// ---- misc
|
||||||
@@ -186,15 +199,14 @@ void SplitInput::initLayout()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// open emote popup
|
// open emote popup
|
||||||
QObject::connect(this->ui_.emoteButton, &EffectLabel::leftClicked, [this] {
|
QObject::connect(this->ui_.emoteButton, &Button::leftClicked, [this] {
|
||||||
this->openEmotePopup();
|
this->openEmotePopup();
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove reply target
|
// clear input and remove reply thread
|
||||||
QObject::connect(this->ui_.cancelReplyButton, &EffectLabel::leftClicked,
|
QObject::connect(this->ui_.cancelReplyButton, &Button::leftClicked, [this] {
|
||||||
[this] {
|
this->setReply(nullptr);
|
||||||
this->setReply(nullptr);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
// Forward selection change signal
|
// Forward selection change signal
|
||||||
QObject::connect(this->ui_.textEdit, &QTextEdit::copyAvailable,
|
QObject::connect(this->ui_.textEdit, &QTextEdit::copyAvailable,
|
||||||
@@ -256,8 +268,6 @@ void SplitInput::themeChangedEvent()
|
|||||||
QPalette::PlaceholderText,
|
QPalette::PlaceholderText,
|
||||||
this->theme->messages.textColors.chatPlaceholder);
|
this->theme->messages.textColors.chatPlaceholder);
|
||||||
|
|
||||||
this->updateEmoteButton();
|
|
||||||
this->updateCancelReplyButton();
|
|
||||||
this->ui_.textEditLength->setPalette(palette);
|
this->ui_.textEditLength->setPalette(palette);
|
||||||
|
|
||||||
this->ui_.textEdit->setStyleSheet(this->theme->splits.input.styleSheet);
|
this->ui_.textEdit->setStyleSheet(this->theme->splits.input.styleSheet);
|
||||||
@@ -284,15 +294,6 @@ void SplitInput::updateEmoteButton()
|
|||||||
{
|
{
|
||||||
auto scale = this->scale();
|
auto scale = this->scale();
|
||||||
|
|
||||||
if (this->theme->isLightTheme())
|
|
||||||
{
|
|
||||||
this->ui_.emoteButton->setSvgResource(":/buttons/emoteDark.svg");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->ui_.emoteButton->setSvgResource(":/buttons/emote.svg");
|
|
||||||
}
|
|
||||||
|
|
||||||
this->ui_.emoteButton->setFixedHeight(int(18 * scale));
|
this->ui_.emoteButton->setFixedHeight(int(18 * scale));
|
||||||
// Make button slightly wider so it's easier to click
|
// Make button slightly wider so it's easier to click
|
||||||
this->ui_.emoteButton->setFixedWidth(int(24 * scale));
|
this->ui_.emoteButton->setFixedWidth(int(24 * scale));
|
||||||
@@ -302,15 +303,6 @@ void SplitInput::updateCancelReplyButton()
|
|||||||
{
|
{
|
||||||
float scale = this->scale();
|
float scale = this->scale();
|
||||||
|
|
||||||
if (this->theme->isLightTheme())
|
|
||||||
{
|
|
||||||
this->ui_.cancelReplyButton->setSvgResource(":/buttons/cancelDark.svg");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->ui_.cancelReplyButton->setSvgResource(":/buttons/cancel.svg");
|
|
||||||
}
|
|
||||||
this->ui_.cancelReplyButton->setEnableMargin(false);
|
|
||||||
this->ui_.cancelReplyButton->setFixedHeight(int(12 * scale));
|
this->ui_.cancelReplyButton->setFixedHeight(int(12 * scale));
|
||||||
this->ui_.cancelReplyButton->setFixedWidth(int(20 * scale));
|
this->ui_.cancelReplyButton->setFixedWidth(int(20 * scale));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "messages/Message.hpp"
|
#include "messages/Message.hpp"
|
||||||
#include "widgets/BaseWidget.hpp"
|
#include "widgets/BaseWidget.hpp"
|
||||||
#include "widgets/helper/Button.hpp"
|
|
||||||
|
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
@@ -20,10 +19,11 @@ namespace chatterino {
|
|||||||
class Split;
|
class Split;
|
||||||
class EmotePopup;
|
class EmotePopup;
|
||||||
class InputCompletionPopup;
|
class InputCompletionPopup;
|
||||||
class EffectLabel;
|
|
||||||
class MessageView;
|
class MessageView;
|
||||||
|
class LabelButton;
|
||||||
class ResizingTextEdit;
|
class ResizingTextEdit;
|
||||||
class ChannelView;
|
class ChannelView;
|
||||||
|
class SvgButton;
|
||||||
enum class CompletionKind;
|
enum class CompletionKind;
|
||||||
|
|
||||||
class SplitInput : public BaseWidget
|
class SplitInput : public BaseWidget
|
||||||
@@ -144,15 +144,15 @@ protected:
|
|||||||
QHBoxLayout *replyHbox;
|
QHBoxLayout *replyHbox;
|
||||||
MessageView *replyMessage;
|
MessageView *replyMessage;
|
||||||
QLabel *replyLabel;
|
QLabel *replyLabel;
|
||||||
Button *cancelReplyButton;
|
SvgButton *cancelReplyButton;
|
||||||
|
|
||||||
// input widgets
|
// input widgets
|
||||||
QWidget *inputWrapper;
|
QWidget *inputWrapper;
|
||||||
QHBoxLayout *inputHbox;
|
QHBoxLayout *inputHbox;
|
||||||
ResizingTextEdit *textEdit;
|
ResizingTextEdit *textEdit;
|
||||||
QLabel *textEditLength;
|
QLabel *textEditLength;
|
||||||
EffectLabel *sendButton;
|
LabelButton *sendButton;
|
||||||
Button *emoteButton;
|
SvgButton *emoteButton;
|
||||||
} ui_;
|
} ui_;
|
||||||
|
|
||||||
MessagePtr replyTarget_ = nullptr;
|
MessagePtr replyTarget_ = nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user