From d7e0c4cadf8f469f958ca4a6b9fce5c0f12c4d1f Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sat, 13 Aug 2022 19:06:10 +0200 Subject: [PATCH 01/11] Fix minimizing the chat widget The chat widget had acquired a minimum size in f29091e4587bff6cf8075ff3bd931fc39c040066, which prevented it from minimizing correctly. Change the minimum size to fix minimization, and prevent resizing the widget while it is minimized. --- client/chatline.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/client/chatline.cpp b/client/chatline.cpp index 43756d5f37..d8b41a1769 100644 --- a/client/chatline.cpp +++ b/client/chatline.cpp @@ -339,6 +339,17 @@ chat_widget::chat_widget(QWidget *parent) */ void chat_widget::set_chat_visible(bool visible) { + if (visible) { + setMinimumSize(200, 100); + setResizable(resizable_flag::top | resizable_flag::topLeft + | resizable_flag::topRight | resizable_flag::bottom + | resizable_flag::bottomLeft | resizable_flag::bottomRight + | resizable_flag::left | resizable_flag::right); + } else { + setMinimumSize(200, 0); + setResizable({}); + } + chat_line->setVisible(visible); chat_output->setVisible(visible); cb->setVisible(visible && !is_server_running()); From 9597984a60b8c57d1931e9036984c8cd07aecf16 Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sat, 13 Aug 2022 19:08:19 +0200 Subject: [PATCH 02/11] Prevent minimizing the chat widget from hiding it Minimizing the chat widget should never send it out of screen. Make sure that it sticks to the side if that would happen. Closes #1074. --- client/chatline.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/chatline.cpp b/client/chatline.cpp index d8b41a1769..7507a05768 100644 --- a/client/chatline.cpp +++ b/client/chatline.cpp @@ -371,6 +371,10 @@ void chat_widget::set_chat_visible(bool visible) if (expand_up) { geo.setTop(std::max(geo.bottom() - h, 0)); geo.setHeight(h); + // Prevent it from going out of screen + if (geo.bottom() > parentWidget()->height()) { + geo.translate(0, parentWidget()->height() - geo.bottom()); + } } else { geo.setBottom(std::min(geo.top() + h, parentWidget()->height())); } From b389cd07570835376bddeb543da0dcc18f85cc0c Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sat, 13 Aug 2022 19:43:00 +0200 Subject: [PATCH 03/11] Simplify resizable_widget Instead of letting the user of the class allow resizing of each corner separately, only use the edges to specify which resizes are allowed. Usable corners are deduced from the list of edges. This makes for a more concise implementation and lets us use Qt::Edges instead of a custom enum. Closes #1145. --- client/chatline.cpp | 12 +- client/messagewin.cpp | 3 +- client/widgetdecorations.cpp | 223 +++++++++-------------------------- client/widgetdecorations.h | 27 +---- 4 files changed, 64 insertions(+), 201 deletions(-) diff --git a/client/chatline.cpp b/client/chatline.cpp index 7507a05768..8982c1b959 100644 --- a/client/chatline.cpp +++ b/client/chatline.cpp @@ -19,6 +19,7 @@ #include #include #include +#include // common #include "chat.h" #include "chatline_common.h" @@ -256,10 +257,7 @@ chat_widget::chat_widget(QWidget *parent) QGridLayout *gl; setParent(parent); setMinimumSize(200, 100); - setResizable(resizable_flag::top | resizable_flag::topLeft - | resizable_flag::topRight | resizable_flag::bottom - | resizable_flag::bottomLeft | resizable_flag::bottomRight - | resizable_flag::left | resizable_flag::right); + setResizable(Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge | Qt::BottomEdge); gl = new QGridLayout; gl->setVerticalSpacing(0); @@ -341,10 +339,8 @@ void chat_widget::set_chat_visible(bool visible) { if (visible) { setMinimumSize(200, 100); - setResizable(resizable_flag::top | resizable_flag::topLeft - | resizable_flag::topRight | resizable_flag::bottom - | resizable_flag::bottomLeft | resizable_flag::bottomRight - | resizable_flag::left | resizable_flag::right); + setResizable(Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge + | Qt::BottomEdge); } else { setMinimumSize(200, 0); setResizable({}); diff --git a/client/messagewin.cpp b/client/messagewin.cpp index 1f8bdad6ce..5c0d01a6b5 100644 --- a/client/messagewin.cpp +++ b/client/messagewin.cpp @@ -40,8 +40,7 @@ message_widget::message_widget(QWidget *parent) layout = new QGridLayout; layout->setMargin(2); setLayout(layout); - setResizable(resizable_flag::bottom | resizable_flag::bottomLeft - | resizable_flag::left); + setResizable(Qt::LeftEdge | Qt::BottomEdge); auto title = new QLabel(_("Messages")); title->setAlignment(Qt::AlignCenter); diff --git a/client/widgetdecorations.cpp b/client/widgetdecorations.cpp index 7e8ec29e0c..4e52e9d483 100644 --- a/client/widgetdecorations.cpp +++ b/client/widgetdecorations.cpp @@ -16,6 +16,7 @@ // Qt #include #include +#include // gui-qt #include "fc_client.h" #include "icons.h" @@ -173,32 +174,18 @@ void close_widget::notify_parent() /** Set resizable flags */ -void resizable_widget::setResizable(QFlags flags) -{ - resizeFlags = flags; -} +void resizable_widget::setResizable(Qt::Edges edges) { resizeFlags = edges; } /** Get resizable flags of wdiget */ -QFlags resizable_widget::getResizable() const -{ - return resizeFlags; -} +Qt::Edges resizable_widget::getResizable() const { return resizeFlags; } /** Remove all resizable flags */ void resizable_widget::removeResizable() { resizeFlags = {}; } -/** - Check if resizable flag is active - */ -bool resizable_widget::hasResizable(resizable_flag flag) const -{ - return resizeFlags.testFlag(flag); -} - /** Checks if info_tab can be moved */ @@ -209,12 +196,12 @@ void resizable_widget::mousePressEvent(QMouseEvent *event) } if (event->button() == Qt::LeftButton) { // Get flag from mouse position - auto flag = get_in_event_mouse(event); + auto flags = get_in_event_mouse(event); // Check the flag and widget for the presence of a flag - if (flag != resizable_flag::none && resizeFlags.testFlag(flag)) { + if (resizeFlags | flags) { // Save flag and mouse position for mouse move event - eventFlag = flag; + eventFlags = flags; last_position = event->globalPos(); } } @@ -224,54 +211,26 @@ void resizable_widget::mousePressEvent(QMouseEvent *event) /** Get resizable_flag from mouse position */ -resizable_flag +Qt::Edges resizable_widget::get_in_event_mouse(const QMouseEvent *event) const { - if (event->x() >= width() / 2 - event_width - && event->x() <= width() / 2 + event_width && event->y() >= 0 - && event->y() <= event_width) { - return resizable_flag::top; - } - - if (event->x() >= 0 && event->x() <= event_width && event->y() >= 0 - && event->y() <= event_width) { - return resizable_flag::topLeft; - } + auto flags = Qt::Edges(); - if (event->x() >= width() - event_width && event->x() <= width() - && event->y() >= 0 && event->y() <= event_width) { - return resizable_flag::topRight; + if (std::abs(event->x()) < event_width && event->x() < width() / 2) { + flags |= Qt::LeftEdge; + } else if (std::abs(event->x() - width()) < event_width + && event->x() >= width() / 2) { + flags |= Qt::RightEdge; } - if (event->x() >= width() / 2 - event_width - && event->x() <= width() / 2 + event_width - && event->y() >= height() - event_width && event->y() <= height()) { - return resizable_flag::bottom; + if (std::abs(event->y()) < event_width) { + flags |= Qt::TopEdge; + } else if (std::abs(event->y() - height()) < event_width + && event->y() >= height() / 2) { + flags |= Qt::BottomEdge; } - if (event->x() >= 0 && event->x() <= event_width - && event->y() >= height() - event_width && event->y() <= height()) { - return resizable_flag::bottomLeft; - } - - if (event->x() >= width() - event_width && event->x() <= width() - && event->y() >= height() - event_width && event->y() <= height()) { - return resizable_flag::bottomRight; - } - - if (event->x() >= 0 && event->x() <= event_width - && event->y() >= height() / 2 - event_width - && event->y() <= height() / 2 + event_width) { - return resizable_flag::left; - } - - if (event->x() >= width() - event_width && event->x() <= width() - && event->y() >= height() / 2 - event_width - && event->y() <= height() / 2 + event_width) { - return resizable_flag::right; - } - - return resizable_flag::none; + return flags; } /** @@ -284,8 +243,8 @@ void resizable_widget::mouseReleaseEvent(QMouseEvent *event) } // If the event flag is active, then reset all - if (eventFlag != resizable_flag::none) { - eventFlag = resizable_flag::none; + if (eventFlags != Qt::Edges()) { + eventFlags = Qt::Edges(); last_position = QPoint{}; setCursor(Qt::ArrowCursor); } @@ -305,125 +264,51 @@ void resizable_widget::mouseMoveEvent(QMouseEvent *event) // Check left button state if (event->buttons() & Qt::LeftButton) { // If the event flag is active - if (eventFlag != resizable_flag::none) { - QSize size{width(), height()}; - QPoint pos{x(), y()}; + if (eventFlags != Qt::Edges()) { + auto new_size = size(); + auto new_pos = pos(); // Calculate diff betwen position and update last position auto diff = event->globalPos() - last_position; last_position = event->globalPos(); // Resizing and moving depending on the type of event - switch (eventFlag) { - case resizable_flag::top: { - if (minimumHeight() < height() - diff.y()) { - size.setHeight(height() - diff.y()); - pos.setY(y() + diff.y()); - } - - resize(size.width(), size.height()); - move(pos.x(), pos.y()); - } break; - - case resizable_flag::topLeft: { - if (minimumWidth() < width() - diff.x()) { - size.setWidth(width() - diff.x()); - pos.setX(x() + diff.x()); - } - - if (minimumHeight() < height() - diff.y()) { - size.setHeight(height() - diff.y()); - pos.setY(y() + diff.y()); - } - - resize(size.width(), size.height()); - move(pos.x(), pos.y()); - } break; - - case resizable_flag::topRight: { - if (minimumWidth() < width() + diff.x()) { - size.setWidth(width() + diff.x()); - } - - if (minimumHeight() < height() - diff.y()) { - size.setHeight(height() - diff.y()); - pos.setY(y() + diff.y()); - } - - resize(size.width(), size.height()); - move(pos.x(), pos.y()); - } break; - - case resizable_flag::bottom: { - if (minimumHeight() < height() + diff.y()) { - size.setHeight(height() + diff.y()); - } - - resize(size.width(), size.height()); - } break; - - case resizable_flag::bottomLeft: { - if (minimumWidth() < width() - diff.x()) { - size.setWidth(width() - diff.x()); - pos.setX(x() + diff.x()); - } - - if (minimumHeight() < height() + diff.y()) { - size.setHeight(height() + diff.y()); - } - - resize(size.width(), size.height()); - move(pos.x(), pos.y()); - } break; - - case resizable_flag::bottomRight: { - if (minimumWidth() < width() + diff.x()) { - size.setWidth(width() + diff.x()); - } - - if (minimumHeight() < height() + diff.y()) { - size.setHeight(height() + diff.y()); - } - - resize(size.width(), size.height()); - } break; - - case resizable_flag::left: { - if (minimumWidth() < width() - diff.x()) { - size.setWidth(width() - diff.x()); - pos.setX(x() + diff.x()); - } - - resize(size.width(), size.height()); - move(pos.x(), pos.y()); - } break; - - case resizable_flag::right: { - resize((std::max)(minimumWidth(), width() + diff.x()), height()); - } break; - - default: - break; + if (eventFlags & Qt::TopEdge + && height() - diff.y() >= minimumHeight()) { + new_size.setHeight(height() - diff.y()); + new_pos.setY(y() + diff.y()); + } else if (eventFlags & Qt::BottomEdge + && height() + diff.y() >= minimumHeight()) { + new_size.setHeight(height() + diff.y()); + } + + if (eventFlags & Qt::LeftEdge + && width() - diff.x() >= minimumWidth()) { + new_size.setWidth(width() - diff.x()); + new_pos.setX(x() + diff.x()); + } else if (eventFlags & Qt::RightEdge + && width() + diff.x() >= minimumWidth()) { + new_size.setWidth(width() + diff.x()); } + + resize(new_size); + move(new_pos); } } else { // Get flag from mouse position - auto flag = get_in_event_mouse(event); + auto flags = get_in_event_mouse(event) & resizeFlags; // Change the cursor if the flag is active and the widget has this flag - if (flag != resizable_flag::none && resizeFlags.testFlag(flag)) { - if (flag == resizable_flag::top || flag == resizable_flag::bottom) { - setCursor(Qt::SizeVerCursor); - } else if (flag == resizable_flag::topLeft - || flag == resizable_flag::bottomRight) { - setCursor(Qt::SizeFDiagCursor); - } else if (flag == resizable_flag::topRight - || flag == resizable_flag::bottomLeft) { - setCursor(Qt::SizeBDiagCursor); - } else if (flag == resizable_flag::left - || flag == resizable_flag::right) { - setCursor(Qt::SizeHorCursor); - } + if (flags == Qt::LeftEdge || flags == Qt::RightEdge) { + setCursor(Qt::SizeHorCursor); + } else if (flags == Qt::TopEdge || flags == Qt::BottomEdge) { + setCursor(Qt::SizeVerCursor); + } else if (flags == (Qt::TopEdge | Qt::LeftEdge) + || flags == (Qt::BottomEdge | Qt::RightEdge)) { + setCursor(Qt::SizeFDiagCursor); + } else if (flags == (Qt::TopEdge | Qt::RightEdge) + || flags == (Qt::BottomEdge | Qt::LeftEdge)) { + setCursor(Qt::SizeBDiagCursor); } else { // Otherwise change cursor to default setCursor(Qt::ArrowCursor); diff --git a/client/widgetdecorations.h b/client/widgetdecorations.h index cbf73ac3ec..424c990405 100644 --- a/client/widgetdecorations.h +++ b/client/widgetdecorations.h @@ -71,18 +71,6 @@ class fcwidget : public QFrame { /************************************************************************** Abstract class for widgets that can be resized by dragging the edges. **************************************************************************/ -enum class resizable_flag : std::uint8_t { - none = 0, - top = 1, - topLeft = 2, - topRight = 4, - bottom = 8, - bottomLeft = 16, - bottomRight = 32, - left = 64, - right = 128 -}; - class resizable_widget : public fcwidget { Q_OBJECT @@ -93,23 +81,20 @@ class resizable_widget : public fcwidget { public: // make widget resizable (multiple flags supported) - void setResizable(QFlags resizeFlags); + void setResizable(Qt::Edges edges); // get resizable flags - QFlags getResizable() const; + Qt::Edges getResizable() const; // remove resizable for widget void removeResizable(); - // check exist a resizable_type - bool hasResizable(resizable_flag flag) const; - private: - resizable_flag get_in_event_mouse(const QMouseEvent *event) const; + Qt::Edges get_in_event_mouse(const QMouseEvent *event) const; QPoint last_position{}; - resizable_flag eventFlag{}; - QFlags resizeFlags{}; + Qt::Edges eventFlags{}; + Qt::Edges resizeFlags{}; protected: void mousePressEvent(QMouseEvent *event) override; @@ -117,8 +102,6 @@ class resizable_widget : public fcwidget { void mouseReleaseEvent(QMouseEvent *event) override; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QFlags) - /************************************************************************** Widget allowing closing other widgets **************************************************************************/ From c73cc12c99007ec56e3ed548b0c7ec819af9d90b Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sat, 13 Aug 2022 19:55:59 +0200 Subject: [PATCH 04/11] Add a small margin on resizable widgets' active edges The few extra pixels make grabbing the edges a lot easier, greatly improving usability. --- client/widgetdecorations.cpp | 19 ++++++++++++++++++- client/widgetdecorations.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/client/widgetdecorations.cpp b/client/widgetdecorations.cpp index 4e52e9d483..188d9d8b48 100644 --- a/client/widgetdecorations.cpp +++ b/client/widgetdecorations.cpp @@ -174,7 +174,24 @@ void close_widget::notify_parent() /** Set resizable flags */ -void resizable_widget::setResizable(Qt::Edges edges) { resizeFlags = edges; } +void resizable_widget::setResizable(Qt::Edges edges) +{ + resizeFlags = edges; + auto margins = QMargins(); + if (edges & Qt::LeftEdge) { + margins.setLeft(margin_width); + } + if (edges & Qt::RightEdge) { + margins.setRight(margin_width); + } + if (edges & Qt::TopEdge) { + margins.setTop(margin_width); + } + if (edges & Qt::BottomEdge) { + margins.setBottom(margin_width); + } + setContentsMargins(margins); +} /** Get resizable flags of wdiget diff --git a/client/widgetdecorations.h b/client/widgetdecorations.h index 424c990405..cacfff0b08 100644 --- a/client/widgetdecorations.h +++ b/client/widgetdecorations.h @@ -75,6 +75,7 @@ class resizable_widget : public fcwidget { Q_OBJECT static constexpr int event_width = 25; + static constexpr int margin_width = 3; signals: void resized(QRect rect); From 6c61d46c8153e1e50f793268f9bc1d7c6dd90c21 Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sat, 13 Aug 2022 20:08:28 +0200 Subject: [PATCH 05/11] Remove unused resizable::removeResizable() setResizable({}) is just as easy. --- client/widgetdecorations.cpp | 5 ----- client/widgetdecorations.h | 3 --- 2 files changed, 8 deletions(-) diff --git a/client/widgetdecorations.cpp b/client/widgetdecorations.cpp index 188d9d8b48..cc250a8193 100644 --- a/client/widgetdecorations.cpp +++ b/client/widgetdecorations.cpp @@ -198,11 +198,6 @@ void resizable_widget::setResizable(Qt::Edges edges) */ Qt::Edges resizable_widget::getResizable() const { return resizeFlags; } -/** - Remove all resizable flags - */ -void resizable_widget::removeResizable() { resizeFlags = {}; } - /** Checks if info_tab can be moved */ diff --git a/client/widgetdecorations.h b/client/widgetdecorations.h index cacfff0b08..99db74cfa9 100644 --- a/client/widgetdecorations.h +++ b/client/widgetdecorations.h @@ -87,9 +87,6 @@ class resizable_widget : public fcwidget { // get resizable flags Qt::Edges getResizable() const; - // remove resizable for widget - void removeResizable(); - private: Qt::Edges get_in_event_mouse(const QMouseEvent *event) const; From 83ec604d234f46ba2effc75908779f91d9f53cbe Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sat, 13 Aug 2022 20:26:33 +0200 Subject: [PATCH 06/11] Prevent resizing the chat out of the window Closes #1044. --- client/widgetdecorations.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/widgetdecorations.cpp b/client/widgetdecorations.cpp index cc250a8193..75e0b864d1 100644 --- a/client/widgetdecorations.cpp +++ b/client/widgetdecorations.cpp @@ -277,8 +277,7 @@ void resizable_widget::mouseMoveEvent(QMouseEvent *event) if (event->buttons() & Qt::LeftButton) { // If the event flag is active if (eventFlags != Qt::Edges()) { - auto new_size = size(); - auto new_pos = pos(); + auto new_rect = QRect(pos(), size()); // Calculate diff betwen position and update last position auto diff = event->globalPos() - last_position; @@ -287,24 +286,25 @@ void resizable_widget::mouseMoveEvent(QMouseEvent *event) // Resizing and moving depending on the type of event if (eventFlags & Qt::TopEdge && height() - diff.y() >= minimumHeight()) { - new_size.setHeight(height() - diff.y()); - new_pos.setY(y() + diff.y()); + new_rect.setTop(new_rect.top() + diff.y()); } else if (eventFlags & Qt::BottomEdge && height() + diff.y() >= minimumHeight()) { - new_size.setHeight(height() + diff.y()); + new_rect.setBottom(new_rect.bottom() + diff.y()); } if (eventFlags & Qt::LeftEdge && width() - diff.x() >= minimumWidth()) { - new_size.setWidth(width() - diff.x()); - new_pos.setX(x() + diff.x()); + new_rect.setLeft(new_rect.left() + diff.x()); } else if (eventFlags & Qt::RightEdge && width() + diff.x() >= minimumWidth()) { - new_size.setWidth(width() + diff.x()); + new_rect.setRight(new_rect.right() + diff.x()); } - resize(new_size); - move(new_pos); + // Prevent resizing out of the parent + new_rect &= parentWidget()->rect(); + + resize(new_rect.size()); + move(new_rect.topLeft()); } } else { // Get flag from mouse position From e07377f2ebe8c75cc4066508d471db0cd6278be5 Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sat, 13 Aug 2022 20:36:55 +0200 Subject: [PATCH 07/11] Don't rely on mouse position differences to resize the chat This arithmetic is complicated and I'm not sure how to get it right. Use a simpler algorithm: try to put the edge where it should be, and move it back if the resulting height or width would become smaller than the minimum. Closes #1143. --- client/widgetdecorations.cpp | 39 ++++++++++++++++++++---------------- client/widgetdecorations.h | 1 - 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/client/widgetdecorations.cpp b/client/widgetdecorations.cpp index 75e0b864d1..1a9d15b4ed 100644 --- a/client/widgetdecorations.cpp +++ b/client/widgetdecorations.cpp @@ -214,7 +214,6 @@ void resizable_widget::mousePressEvent(QMouseEvent *event) if (resizeFlags | flags) { // Save flag and mouse position for mouse move event eventFlags = flags; - last_position = event->globalPos(); } } event->setAccepted(true); @@ -257,7 +256,6 @@ void resizable_widget::mouseReleaseEvent(QMouseEvent *event) // If the event flag is active, then reset all if (eventFlags != Qt::Edges()) { eventFlags = Qt::Edges(); - last_position = QPoint{}; setCursor(Qt::ArrowCursor); } emit resized(rect()); @@ -279,25 +277,32 @@ void resizable_widget::mouseMoveEvent(QMouseEvent *event) if (eventFlags != Qt::Edges()) { auto new_rect = QRect(pos(), size()); - // Calculate diff betwen position and update last position - auto diff = event->globalPos() - last_position; - last_position = event->globalPos(); + // The x and y that we should reach, relative to the parent widget + const auto target = event->pos() + pos(); // Resizing and moving depending on the type of event - if (eventFlags & Qt::TopEdge - && height() - diff.y() >= minimumHeight()) { - new_rect.setTop(new_rect.top() + diff.y()); - } else if (eventFlags & Qt::BottomEdge - && height() + diff.y() >= minimumHeight()) { - new_rect.setBottom(new_rect.bottom() + diff.y()); + if (eventFlags & Qt::TopEdge) { + new_rect.setTop(target.y()); + if (new_rect.height() < minimumHeight()) { + new_rect.setTop(new_rect.bottom() - minimumHeight()); + } + } else if (eventFlags & Qt::BottomEdge) { + new_rect.setBottom(target.y()); + if (new_rect.height() < minimumHeight()) { + new_rect.setBottom(new_rect.top() + minimumHeight()); + } } - if (eventFlags & Qt::LeftEdge - && width() - diff.x() >= minimumWidth()) { - new_rect.setLeft(new_rect.left() + diff.x()); - } else if (eventFlags & Qt::RightEdge - && width() + diff.x() >= minimumWidth()) { - new_rect.setRight(new_rect.right() + diff.x()); + if (eventFlags & Qt::LeftEdge) { + new_rect.setLeft(target.x()); + if (new_rect.width() < minimumWidth()) { + new_rect.setLeft(new_rect.right() - minimumWidth()); + } + } else if (eventFlags & Qt::RightEdge) { + new_rect.setRight(target.x()); + if (new_rect.width() < minimumWidth()) { + new_rect.setRight(new_rect.left() + minimumWidth()); + } } // Prevent resizing out of the parent diff --git a/client/widgetdecorations.h b/client/widgetdecorations.h index 99db74cfa9..b98402c04e 100644 --- a/client/widgetdecorations.h +++ b/client/widgetdecorations.h @@ -90,7 +90,6 @@ class resizable_widget : public fcwidget { private: Qt::Edges get_in_event_mouse(const QMouseEvent *event) const; - QPoint last_position{}; Qt::Edges eventFlags{}; Qt::Edges resizeFlags{}; From 4fc17a9133fdb8bafaf37de0ad170f70ad5302e2 Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sat, 13 Aug 2022 20:45:03 +0200 Subject: [PATCH 08/11] Move the messages widget on top of the mapview This way it looks more like a popdown. Closes #1159. --- client/page_game.cpp | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/client/page_game.cpp b/client/page_game.cpp index c874b865d0..461ad5d629 100644 --- a/client/page_game.cpp +++ b/client/page_game.cpp @@ -113,6 +113,27 @@ pageGame::pageGame(QWidget *parent) sw_diplo->setRightClick(top_bar_right_click_diplomacy); sw_science->setRightClick(top_bar_right_click_science); + minimap_panel = new ::minimap_panel(mapview_wdg, mapview_wdg); + + city_overlay = new city_dialog(mapview_wdg); + connect(mapview_wdg, &map_view::scale_changed, city_overlay, + &city_dialog::refresh); + city_overlay->hide(); + unitinfo_wdg = new hud_units(mapview_wdg); + unitinfo_wdg->setAttribute(Qt::WA_NoMousePropagation); + battlelog_wdg = new hud_battle_log(mapview_wdg); + battlelog_wdg->setAttribute(Qt::WA_NoMousePropagation); + battlelog_wdg->hide(); + chat = new chat_widget(mapview_wdg); + chat->setAttribute(Qt::WA_NoMousePropagation); + chat->show(); + x_vote = new xvote(mapview_wdg); + x_vote->setAttribute(Qt::WA_NoMousePropagation); + x_vote->hide(); + gtd = new goto_dialog(mapview_wdg); + gtd->setAttribute(Qt::WA_NoMousePropagation); + gtd->hide(); + message = new message_widget(mapview_wdg); message->setAttribute(Qt::WA_NoMousePropagation); message->hide(); @@ -141,8 +162,6 @@ pageGame::pageGame(QWidget *parent) } }); - minimap_panel = new ::minimap_panel(mapview_wdg, mapview_wdg); - top_bar_wdg->addWidget(sw_map); top_bar_wdg->addWidget(sw_cunit); top_bar_wdg->addWidget(sw_cities); @@ -153,25 +172,6 @@ pageGame::pageGame(QWidget *parent) top_bar_wdg->addWidget(sw_indicators); top_bar_wdg->addWidget(sw_message); - city_overlay = new city_dialog(mapview_wdg); - connect(mapview_wdg, &map_view::scale_changed, city_overlay, - &city_dialog::refresh); - city_overlay->hide(); - unitinfo_wdg = new hud_units(mapview_wdg); - unitinfo_wdg->setAttribute(Qt::WA_NoMousePropagation); - battlelog_wdg = new hud_battle_log(mapview_wdg); - battlelog_wdg->setAttribute(Qt::WA_NoMousePropagation); - battlelog_wdg->hide(); - chat = new chat_widget(mapview_wdg); - chat->setAttribute(Qt::WA_NoMousePropagation); - chat->show(); - x_vote = new xvote(mapview_wdg); - x_vote->setAttribute(Qt::WA_NoMousePropagation); - x_vote->hide(); - gtd = new goto_dialog(mapview_wdg); - gtd->setAttribute(Qt::WA_NoMousePropagation); - gtd->hide(); - game_layout->addWidget(mapview_wdg, 1, 0); game_main_widget->setLayout(game_layout); game_tab_widget = new fc_game_tab_widget; From f1cd5bfe8fe23f20e0563f20319d31c99fb28b6a Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sun, 14 Aug 2022 00:04:30 +0200 Subject: [PATCH 09/11] Fix storing the chat_widget size and position to disk The geometry of the chat_widget (relative to the game page) is stored to disk. The values are also used when resizing the widget and when expanding it, making everything quite complicated. Keep the same design but make sure that the values to be saved are always up-to-date. Closes #1158. --- client/chatline.cpp | 5 +++++ client/chatline.h | 6 ++++++ client/fc_client.cpp | 28 +++++++++++++++++++++++++++- client/fc_client.h | 2 ++ client/page_game.cpp | 12 ++++++------ 5 files changed, 46 insertions(+), 7 deletions(-) diff --git a/client/chatline.cpp b/client/chatline.cpp index 8982c1b959..14b0155ef3 100644 --- a/client/chatline.cpp +++ b/client/chatline.cpp @@ -337,6 +337,9 @@ chat_widget::chat_widget(QWidget *parent) */ void chat_widget::set_chat_visible(bool visible) { + // Don't update chat_fheight + m_chat_visible = false; + if (visible) { setMinimumSize(200, 100); setResizable(Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge @@ -375,6 +378,8 @@ void chat_widget::set_chat_visible(bool visible) geo.setBottom(std::min(geo.top() + h, parentWidget()->height())); } setGeometry(geo); + + m_chat_visible = visible; } /** diff --git a/client/chatline.h b/client/chatline.h index a950d28528..b02ae6df52 100644 --- a/client/chatline.h +++ b/client/chatline.h @@ -118,6 +118,10 @@ class chat_widget : public resizable_widget, private chat_listener { int default_size(int lines); void take_focus(); void update_font(); + + /// Returns whether the chat widget is currently visible. + bool is_chat_visible() const { return m_chat_visible; } + private slots: void set_chat_visible(bool visible); void update_menu() override {} @@ -131,6 +135,8 @@ private slots: private: void chat_message_received(const QString &message, const struct text_tag_list *tags) override; + + bool m_chat_visible = true; QTextBrowser *chat_output; QPushButton *remove_links; QPushButton *show_hide; diff --git a/client/fc_client.cpp b/client/fc_client.cpp index 77b8262675..9166ba937c 100644 --- a/client/fc_client.cpp +++ b/client/fc_client.cpp @@ -100,8 +100,12 @@ fc_client::fc_client() : QMainWindow(), current_file(QLatin1String("")) if (!path.isEmpty()) { QSettings::setPath(QSettings::NativeFormat, QSettings::UserScope, path); } + init_mapcanvas_and_overview(); - pages[PAGE_GAME] = new pageGame(central_wdg); + auto page_game = new pageGame(central_wdg); + page_game->chat->installEventFilter(this); // To save its location + pages[PAGE_GAME] = page_game; + pages[PAGE_GAME + 1] = new QWidget(central_wdg); create_loading_page(); pages[PAGE_GAME + 1]->setLayout(pages_layout[PAGE_GAME + 1]); @@ -353,6 +357,28 @@ void fc_client::delete_cursors() } } +/** + * Used to keep track of the size and location of the chat widget. + */ +bool fc_client::eventFilter(QObject *obj, QEvent *event) +{ + const auto page_game = qobject_cast(pages[PAGE_GAME]); + if (page_game && obj == page_game->chat + && page_game->chat->is_chat_visible()) { + const auto chat = page_game->chat; + if (event->type() == QEvent::Move) { + const auto xy = QPointF(chat->pos()); + qt_settings.chat_fx_pos = xy.x() / page_game->width(); + qt_settings.chat_fy_pos = xy.y() / page_game->height(); + } else if (event->type() == QEvent::Resize) { + const auto size = QSizeF(chat->size()); + qt_settings.chat_fwidth = size.width() / page_game->width(); + qt_settings.chat_fheight = size.height() / page_game->height(); + } + } + return false; +} + /** Loads qt-specific options */ diff --git a/client/fc_client.h b/client/fc_client.h index f2fa4f0bcb..c18ff10513 100644 --- a/client/fc_client.h +++ b/client/fc_client.h @@ -145,6 +145,8 @@ public slots: void read_settings(); protected: + bool eventFilter(QObject *obj, QEvent *event) override; + void timerEvent(QTimerEvent *) override; void closeEvent(QCloseEvent *event) override; diff --git a/client/page_game.cpp b/client/page_game.cpp index 461ad5d629..806cb6959c 100644 --- a/client/page_game.cpp +++ b/client/page_game.cpp @@ -514,15 +514,15 @@ bool fc_game_tab_widget::event(QEvent *event) : this->size(); if (event->type() == QEvent::Resize) { queen()->message->resize( - qRound((size.width() * king()->qt_settings.chat_fwidth)), - qRound((size.height() * king()->qt_settings.chat_fheight))); + qRound(size.width() * king()->qt_settings.chat_fwidth), + qRound(size.height() * king()->qt_settings.chat_fheight)); queen()->message->move(size.width() - queen()->message->width(), 0); queen()->chat->resize( - qRound((size.width() * king()->qt_settings.chat_fwidth)), - qRound((size.height() * king()->qt_settings.chat_fheight))); + qRound(size.width() * king()->qt_settings.chat_fwidth), + qRound(size.height() * king()->qt_settings.chat_fheight)); queen()->chat->move( - qRound((size.width() * king()->qt_settings.chat_fx_pos)), - qRound((size.height() * king()->qt_settings.chat_fy_pos))); + qRound(size.width() * king()->qt_settings.chat_fx_pos), + qRound(size.height() * king()->qt_settings.chat_fy_pos)); queen()->battlelog_wdg->set_scale(king()->qt_settings.battlelog_scale); queen()->battlelog_wdg->move( qRound(king()->qt_settings.battlelog_x * mapview.width), From 017d03c58b4b8b1aca0d1b7e6ceb9ab4c532bfd8 Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sun, 14 Aug 2022 00:21:09 +0200 Subject: [PATCH 10/11] Store the chat widget position relative to the mapview That's what we use when restoring it. --- client/fc_client.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/fc_client.cpp b/client/fc_client.cpp index 9166ba937c..ce75b031a3 100644 --- a/client/fc_client.cpp +++ b/client/fc_client.cpp @@ -366,14 +366,15 @@ bool fc_client::eventFilter(QObject *obj, QEvent *event) if (page_game && obj == page_game->chat && page_game->chat->is_chat_visible()) { const auto chat = page_game->chat; + const auto mapview = page_game->mapview_wdg; if (event->type() == QEvent::Move) { const auto xy = QPointF(chat->pos()); - qt_settings.chat_fx_pos = xy.x() / page_game->width(); - qt_settings.chat_fy_pos = xy.y() / page_game->height(); + qt_settings.chat_fx_pos = xy.x() / mapview->width(); + qt_settings.chat_fy_pos = xy.y() / mapview->height(); } else if (event->type() == QEvent::Resize) { const auto size = QSizeF(chat->size()); - qt_settings.chat_fwidth = size.width() / page_game->width(); - qt_settings.chat_fheight = size.height() / page_game->height(); + qt_settings.chat_fwidth = size.width() / mapview->width(); + qt_settings.chat_fheight = size.height() / mapview->height(); } } return false; From f5b9015a59497a15b7506e76fbcca56ca729a270 Mon Sep 17 00:00:00 2001 From: Louis Moureaux Date: Sun, 14 Aug 2022 00:21:33 +0200 Subject: [PATCH 11/11] Fix the chat widget jumping around when unfolded Setting the minimum size was making the widget taller and changing bottom(), breaking geometry computations afterwards. Save the geometry before calling setMinimumSize(). --- client/chatline.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/chatline.cpp b/client/chatline.cpp index 14b0155ef3..c7c0280d91 100644 --- a/client/chatline.cpp +++ b/client/chatline.cpp @@ -340,6 +340,9 @@ void chat_widget::set_chat_visible(bool visible) // Don't update chat_fheight m_chat_visible = false; + // Save the geometry before setting the minimum size + auto geo = geometry(); + if (visible) { setMinimumSize(200, 100); setResizable(Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge @@ -366,7 +369,6 @@ void chat_widget::set_chat_visible(bool visible) : QLatin1String("expand-down"); show_hide->setIcon(fcIcons::instance()->getIcon(icon_name)); - auto geo = geometry(); if (expand_up) { geo.setTop(std::max(geo.bottom() - h, 0)); geo.setHeight(h);