mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
feat(emote-popup): save size of popup (#5415)
* fix: remove added margins from emote window position * chore: add changelog entry * feat: store size of emote window * chore: update changelog entry * fix: disable layout save * fix: PCH moment * fix: multiply by scale
This commit is contained in:
parent
c3bb99eb01
commit
65bfec963b
|
@ -7,6 +7,7 @@
|
|||
- Minor: Add option to customise Moderation buttons with images. (#5369)
|
||||
- Minor: Colored usernames now update on the fly when changing the "Color @usernames" setting. (#5300)
|
||||
- Minor: Added `flags.action` filter variable, allowing you to filter on `/me` messages. (#5397)
|
||||
- Minor: The size of the emote popup is now saved. (#5415)
|
||||
- Minor: Added the ability to duplicate tabs. (#5277)
|
||||
- Bugfix: Fixed tab move animation occasionally failing to start after closing a tab. (#5426)
|
||||
- Bugfix: If a network request errors with 200 OK, Qt's error code is now reported instead of the HTTP status. (#5378)
|
||||
|
|
|
@ -219,9 +219,15 @@ WindowLayout WindowLayout::loadFromFile(const QString &path)
|
|||
}
|
||||
|
||||
// Load emote popup position
|
||||
QJsonObject emote_popup_obj = windowObj.value("emotePopup").toObject();
|
||||
layout.emotePopupPos_ = QPoint(emote_popup_obj.value("x").toInt(),
|
||||
emote_popup_obj.value("y").toInt());
|
||||
{
|
||||
auto emotePopup = windowObj["emotePopup"].toObject();
|
||||
layout.emotePopupBounds_ = QRect{
|
||||
emotePopup["x"].toInt(),
|
||||
emotePopup["y"].toInt(),
|
||||
emotePopup["width"].toInt(),
|
||||
emotePopup["height"].toInt(),
|
||||
};
|
||||
}
|
||||
|
||||
layout.windows_.emplace_back(std::move(window));
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ class WindowLayout
|
|||
{
|
||||
public:
|
||||
// A complete window layout has a single emote popup position that is shared among all windows
|
||||
QPoint emotePopupPos_;
|
||||
QRect emotePopupBounds_;
|
||||
|
||||
std::vector<WindowDescriptor> windows_;
|
||||
|
||||
|
|
|
@ -328,14 +328,18 @@ void WindowManager::scrollToMessage(const MessagePtr &message)
|
|||
this->scrollToMessageSignal.invoke(message);
|
||||
}
|
||||
|
||||
QPoint WindowManager::emotePopupPos()
|
||||
QRect WindowManager::emotePopupBounds() const
|
||||
{
|
||||
return this->emotePopupPos_;
|
||||
return this->emotePopupBounds_;
|
||||
}
|
||||
|
||||
void WindowManager::setEmotePopupPos(QPoint pos)
|
||||
void WindowManager::setEmotePopupBounds(QRect bounds)
|
||||
{
|
||||
this->emotePopupPos_ = pos;
|
||||
if (this->emotePopupBounds_ != bounds)
|
||||
{
|
||||
this->emotePopupBounds_ = bounds;
|
||||
this->queueSave();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::initialize(Settings &settings, const Paths &paths)
|
||||
|
@ -371,7 +375,7 @@ void WindowManager::initialize(Settings &settings, const Paths &paths)
|
|||
windowLayout.activateOrAddChannel(desired->provider, desired->name);
|
||||
}
|
||||
|
||||
this->emotePopupPos_ = windowLayout.emotePopupPos_;
|
||||
this->emotePopupBounds_ = windowLayout.emotePopupBounds_;
|
||||
|
||||
this->applyWindowLayout(windowLayout);
|
||||
}
|
||||
|
@ -483,10 +487,12 @@ void WindowManager::save()
|
|||
windowObj.insert("width", rect.width());
|
||||
windowObj.insert("height", rect.height());
|
||||
|
||||
QJsonObject emotePopupObj;
|
||||
emotePopupObj.insert("x", this->emotePopupPos_.x());
|
||||
emotePopupObj.insert("y", this->emotePopupPos_.y());
|
||||
windowObj.insert("emotePopup", emotePopupObj);
|
||||
windowObj["emotePopup"] = QJsonObject{
|
||||
{"x", this->emotePopupBounds_.x()},
|
||||
{"y", this->emotePopupBounds_.y()},
|
||||
{"width", this->emotePopupBounds_.width()},
|
||||
{"height", this->emotePopupBounds_.height()},
|
||||
};
|
||||
|
||||
// window tabs
|
||||
QJsonArray tabsArr;
|
||||
|
@ -753,7 +759,7 @@ void WindowManager::applyWindowLayout(const WindowLayout &layout)
|
|||
}
|
||||
|
||||
// Set emote popup position
|
||||
this->emotePopupPos_ = layout.emotePopupPos_;
|
||||
this->emotePopupBounds_ = layout.emotePopupBounds_;
|
||||
|
||||
for (const auto &windowData : layout.windows_)
|
||||
{
|
||||
|
@ -802,10 +808,14 @@ void WindowManager::applyWindowLayout(const WindowLayout &layout)
|
|||
// Have to offset x by one because qt moves the window 1px too
|
||||
// far to the left:w
|
||||
|
||||
window.setInitialBounds({windowData.geometry_.x(),
|
||||
windowData.geometry_.y(),
|
||||
windowData.geometry_.width(),
|
||||
windowData.geometry_.height()});
|
||||
window.setInitialBounds(
|
||||
{
|
||||
windowData.geometry_.x(),
|
||||
windowData.geometry_.y(),
|
||||
windowData.geometry_.width(),
|
||||
windowData.geometry_.height(),
|
||||
},
|
||||
widgets::BoundsChecking::Off);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,8 +99,8 @@ public:
|
|||
*/
|
||||
void scrollToMessage(const MessagePtr &message);
|
||||
|
||||
QPoint emotePopupPos();
|
||||
void setEmotePopupPos(QPoint pos);
|
||||
QRect emotePopupBounds() const;
|
||||
void setEmotePopupBounds(QRect bounds);
|
||||
|
||||
void initialize(Settings &settings, const Paths &paths) override;
|
||||
void save() override;
|
||||
|
@ -154,7 +154,7 @@ private:
|
|||
bool initialized_ = false;
|
||||
bool shuttingDown_ = false;
|
||||
|
||||
QPoint emotePopupPos_;
|
||||
QRect emotePopupBounds_;
|
||||
|
||||
std::atomic<int> generation_{0};
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
namespace {
|
||||
|
||||
/// Move the `window` into the `screen` geometry if it's not already in there.
|
||||
void moveWithinScreen(QWidget *window, QScreen *screen, QPoint point)
|
||||
QPoint applyBounds(QScreen *screen, QPoint point, QSize frameSize, int height)
|
||||
{
|
||||
if (screen == nullptr)
|
||||
{
|
||||
|
@ -21,9 +20,6 @@ void moveWithinScreen(QWidget *window, QScreen *screen, QPoint point)
|
|||
bool stickRight = false;
|
||||
bool stickBottom = false;
|
||||
|
||||
const auto w = window->frameGeometry().width();
|
||||
const auto h = window->frameGeometry().height();
|
||||
|
||||
if (point.x() < bounds.left())
|
||||
{
|
||||
point.setX(bounds.left());
|
||||
|
@ -32,30 +28,72 @@ void moveWithinScreen(QWidget *window, QScreen *screen, QPoint point)
|
|||
{
|
||||
point.setY(bounds.top());
|
||||
}
|
||||
if (point.x() + w > bounds.right())
|
||||
if (point.x() + frameSize.width() > bounds.right())
|
||||
{
|
||||
stickRight = true;
|
||||
point.setX(bounds.right() - w);
|
||||
point.setX(bounds.right() - frameSize.width());
|
||||
}
|
||||
if (point.y() + h > bounds.bottom())
|
||||
if (point.y() + frameSize.height() > bounds.bottom())
|
||||
{
|
||||
stickBottom = true;
|
||||
point.setY(bounds.bottom() - h);
|
||||
point.setY(bounds.bottom() - frameSize.height());
|
||||
}
|
||||
|
||||
if (stickRight && stickBottom)
|
||||
{
|
||||
const QPoint globalCursorPos = QCursor::pos();
|
||||
point.setY(globalCursorPos.y() - window->height() - 16);
|
||||
point.setY(globalCursorPos.y() - height - 16);
|
||||
}
|
||||
|
||||
window->move(point);
|
||||
return point;
|
||||
}
|
||||
|
||||
/// Move the `window` into the `screen` geometry if it's not already in there.
|
||||
void moveWithinScreen(QWidget *window, QScreen *screen, QPoint point)
|
||||
{
|
||||
auto checked =
|
||||
applyBounds(screen, point, window->frameSize(), window->height());
|
||||
window->move(checked);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace chatterino::widgets {
|
||||
|
||||
QRect checkInitialBounds(QRect initialBounds, BoundsChecking mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case BoundsChecking::Off: {
|
||||
return initialBounds;
|
||||
}
|
||||
break;
|
||||
|
||||
case BoundsChecking::CursorPosition: {
|
||||
return QRect{
|
||||
applyBounds(QGuiApplication::screenAt(QCursor::pos()),
|
||||
initialBounds.topLeft(), initialBounds.size(),
|
||||
initialBounds.height()),
|
||||
initialBounds.size(),
|
||||
};
|
||||
}
|
||||
break;
|
||||
|
||||
case BoundsChecking::DesiredPosition: {
|
||||
return QRect{
|
||||
applyBounds(QGuiApplication::screenAt(initialBounds.topLeft()),
|
||||
initialBounds.topLeft(), initialBounds.size(),
|
||||
initialBounds.height()),
|
||||
initialBounds.size(),
|
||||
};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false && "Invalid bounds checking mode");
|
||||
return initialBounds;
|
||||
}
|
||||
}
|
||||
|
||||
void moveWindowTo(QWidget *window, QPoint position, BoundsChecking mode)
|
||||
{
|
||||
switch (mode)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
class QWidget;
|
||||
class QPoint;
|
||||
class QScreen;
|
||||
class QRect;
|
||||
|
||||
namespace chatterino::widgets {
|
||||
|
||||
|
@ -17,6 +18,14 @@ enum class BoundsChecking {
|
|||
DesiredPosition,
|
||||
};
|
||||
|
||||
/// Applies bounds checking to @a initialBounds.
|
||||
///
|
||||
/// @param initialBounds The bounds to check.
|
||||
/// @param mode The desired bounds checking.
|
||||
/// @returns The potentially modified bounds.
|
||||
QRect checkInitialBounds(QRect initialBounds,
|
||||
BoundsChecking mode = BoundsChecking::DesiredPosition);
|
||||
|
||||
/// Moves the `window` to the (global) `position`
|
||||
/// while doing bounds-checking according to `mode` to ensure the window stays on one screen.
|
||||
///
|
||||
|
|
|
@ -29,7 +29,9 @@
|
|||
# pragma comment(lib, "Dwmapi.lib")
|
||||
|
||||
# include <QHBoxLayout>
|
||||
# include <QMargins>
|
||||
# include <QOperatingSystemVersion>
|
||||
# include <QWindow>
|
||||
#endif
|
||||
|
||||
#include "widgets/helper/TitlebarButton.hpp"
|
||||
|
@ -251,8 +253,9 @@ BaseWindow::~BaseWindow()
|
|||
DebugCount::decrease("BaseWindow");
|
||||
}
|
||||
|
||||
void BaseWindow::setInitialBounds(const QRect &bounds)
|
||||
void BaseWindow::setInitialBounds(QRect bounds, widgets::BoundsChecking mode)
|
||||
{
|
||||
bounds = widgets::checkInitialBounds(bounds, mode);
|
||||
#ifdef USEWINSDK
|
||||
this->initalBounds_ = bounds;
|
||||
#else
|
||||
|
@ -260,7 +263,7 @@ void BaseWindow::setInitialBounds(const QRect &bounds)
|
|||
#endif
|
||||
}
|
||||
|
||||
QRect BaseWindow::getBounds()
|
||||
QRect BaseWindow::getBounds() const
|
||||
{
|
||||
#ifdef USEWINSDK
|
||||
return this->currentBounds_;
|
||||
|
@ -444,7 +447,7 @@ QWidget *BaseWindow::getLayoutContainer()
|
|||
}
|
||||
}
|
||||
|
||||
bool BaseWindow::hasCustomWindowFrame()
|
||||
bool BaseWindow::hasCustomWindowFrame() const
|
||||
{
|
||||
return BaseWindow::supportsCustomWindowFrame() && this->enableCustomFrame_;
|
||||
}
|
||||
|
|
|
@ -45,11 +45,11 @@ public:
|
|||
QWidget *parent = nullptr);
|
||||
~BaseWindow() override;
|
||||
|
||||
void setInitialBounds(const QRect &bounds);
|
||||
QRect getBounds();
|
||||
void setInitialBounds(QRect bounds, widgets::BoundsChecking mode);
|
||||
QRect getBounds() const;
|
||||
|
||||
QWidget *getLayoutContainer();
|
||||
bool hasCustomWindowFrame();
|
||||
bool hasCustomWindowFrame() const;
|
||||
TitleBarButton *addTitleBarButton(const TitleBarButtonStyle &style,
|
||||
std::function<void()> onClicked);
|
||||
EffectLabel *addTitleBarLabel(std::function<void()> onClicked);
|
||||
|
|
|
@ -203,13 +203,18 @@ EmoteMap filterEmoteMap(const QString &text,
|
|||
namespace chatterino {
|
||||
|
||||
EmotePopup::EmotePopup(QWidget *parent)
|
||||
: BasePopup(BaseWindow::EnableCustomFrame, parent)
|
||||
: BasePopup({BaseWindow::EnableCustomFrame, BaseWindow::DisableLayoutSave},
|
||||
parent)
|
||||
, search_(new QLineEdit())
|
||||
, notebook_(new Notebook(this))
|
||||
{
|
||||
// this->setStayInScreenRect(true);
|
||||
this->moveTo(getIApp()->getWindows()->emotePopupPos(),
|
||||
widgets::BoundsChecking::DesiredPosition);
|
||||
auto bounds = getIApp()->getWindows()->emotePopupBounds();
|
||||
if (bounds.size().isEmpty())
|
||||
{
|
||||
bounds.setSize(QSize{300, 500} * this->scale());
|
||||
}
|
||||
this->setInitialBounds(bounds, widgets::BoundsChecking::DesiredPosition);
|
||||
|
||||
auto *layout = new QVBoxLayout();
|
||||
this->getLayoutContainer()->setLayout(layout);
|
||||
|
@ -594,10 +599,27 @@ void EmotePopup::filterEmotes(const QString &searchText)
|
|||
this->searchView_->show();
|
||||
}
|
||||
|
||||
void EmotePopup::saveBounds() const
|
||||
{
|
||||
getIApp()->getWindows()->setEmotePopupBounds(this->getBounds());
|
||||
}
|
||||
|
||||
void EmotePopup::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
this->saveBounds();
|
||||
BasePopup::resizeEvent(event);
|
||||
}
|
||||
|
||||
void EmotePopup::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
this->saveBounds();
|
||||
BasePopup::moveEvent(event);
|
||||
}
|
||||
|
||||
void EmotePopup::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
getIApp()->getWindows()->setEmotePopupPos(this->pos());
|
||||
BaseWindow::closeEvent(event);
|
||||
this->saveBounds();
|
||||
BasePopup::closeEvent(event);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -25,6 +25,10 @@ public:
|
|||
|
||||
pajlada::Signals::Signal<Link> linkClicked;
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
void moveEvent(QMoveEvent *event) override;
|
||||
|
||||
private:
|
||||
ChannelView *globalEmotesView_{};
|
||||
ChannelView *channelEmotesView_{};
|
||||
|
@ -47,6 +51,8 @@ private:
|
|||
void filterEmotes(const QString &text);
|
||||
void addShortcuts() override;
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
void saveBounds() const;
|
||||
};
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -309,8 +309,6 @@ void SplitInput::openEmotePopup()
|
|||
});
|
||||
}
|
||||
|
||||
this->emotePopup_->resize(int(300 * this->emotePopup_->scale()),
|
||||
int(500 * this->emotePopup_->scale()));
|
||||
this->emotePopup_->loadChannel(this->split_->getChannel());
|
||||
this->emotePopup_->show();
|
||||
this->emotePopup_->raise();
|
||||
|
|
Loading…
Reference in a new issue