From 75202eb4ce2324b3560dce62630003c16b9b3030 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Fri, 29 Dec 2017 03:15:04 +0100 Subject: [PATCH] Ref T215, overlay message frame can be used with multiple widgets (not only QFrame) --- src/blackgui/blackguiexport.h | 22 ++- src/blackgui/overlaymessagesframe.cpp | 161 +------------------ src/blackgui/overlaymessagesframe.h | 216 +++++++++++++++++++++----- 3 files changed, 206 insertions(+), 193 deletions(-) diff --git a/src/blackgui/blackguiexport.h b/src/blackgui/blackguiexport.h index 0babf5839..4a1d8fdba 100644 --- a/src/blackgui/blackguiexport.h +++ b/src/blackgui/blackguiexport.h @@ -29,4 +29,24 @@ # define BLACKGUI_EXPORT #endif -#endif // BLACKGUI_MACROS_H +/*! + * \def BLACKGUI_EXPORT_DECLARE_TEMPLATE + * BLACKGUI Export Explicit Template Declaration Macro + */ + +/*! + * \def BLACKGUI_EXPORT_DEFINE_TEMPLATE + * BLACKGUI Export Explicit Template Definition Macro + */ +#if defined(Q_OS_WIN) && defined(Q_CC_GNU) +# define BLACKGUI_EXPORT_DECLARE_TEMPLATE BLACKGUI_EXPORT +# define BLACKGUI_EXPORT_DEFINE_TEMPLATE +#elif defined(Q_OS_WIN) && defined(Q_CC_CLANG) +# define BLACKGUI_EXPORT_DECLARE_TEMPLATE +# define BLACKGUI_EXPORT_DEFINE_TEMPLATE BLACKGUI_EXPORT +#else +# define BLACKGUI_EXPORT_DECLARE_TEMPLATE +# define BLACKGUI_EXPORT_DEFINE_TEMPLATE +#endif + +#endif // guard diff --git a/src/blackgui/overlaymessagesframe.cpp b/src/blackgui/overlaymessagesframe.cpp index 01155e8d0..65eb05348 100644 --- a/src/blackgui/overlaymessagesframe.cpp +++ b/src/blackgui/overlaymessagesframe.cpp @@ -22,164 +22,15 @@ #include using namespace BlackMisc; +using namespace BlackMisc::Network; namespace BlackGui { - COverlayMessagesFrame::COverlayMessagesFrame(QWidget *parent) : - QFrame(parent) - { - const bool isFrameless = CGuiUtility::isMainWindowFrameless(); - m_middleFactor = isFrameless ? 1.25 : 1.5; // 2 is middle in normal window - } - - COverlayMessagesFrame::~COverlayMessagesFrame() + COverlayMessagesFrame::COverlayMessagesFrame(QWidget *parent) : COverlayMessagesBase(parent) { } - void COverlayMessagesFrame::showStatusMessagesFrame() - { - this->initInnerFrame(); - } - - void COverlayMessagesFrame::setOverlaySizeFactors(double widthFactor, double heightFactor, double middleFactor) - { - m_widthFactor = widthFactor; - m_heightFactor = heightFactor; - m_middleFactor = middleFactor; - } - - void COverlayMessagesFrame::showKillButton(bool killButton) - { - m_showKillButton = killButton; - if (m_overlayMessages) - { - m_overlayMessages->showKillButton(killButton); - } - } - - void COverlayMessagesFrame::setForceSmall(bool force) - { - m_forceSmallMsgs = force; - if (m_overlayMessages) - { - m_overlayMessages->setForceSmall(force); - } - } - - void COverlayMessagesFrame::showOverlayMessagesWithConfirmation( - const CStatusMessageList &messages, bool appendOldMessages, - const QString &confirmationMessage, std::function okLambda, - QMessageBox::StandardButton defaultButton, int timeOutMs) - { - if (messages.isEmpty()) { return; } - this->initInnerFrame(); - m_overlayMessages->showOverlayMessagesWithConfirmation(messages, appendOldMessages, confirmationMessage, okLambda, defaultButton, timeOutMs); - this->repaint(); - } - - void COverlayMessagesFrame::clearOverlayMessages() - { - if (!m_overlayMessages) { return; } - m_overlayMessages->clearOverlayMessages(); - } - - void COverlayMessagesFrame::closeOverlay() - { - if (!m_overlayMessages) { return; } - m_overlayMessages->close(); - } - - void COverlayMessagesFrame::showOverlayMessage(const CStatusMessage &message, int timeOutMs) - { - if (message.isEmpty()) { return; } - this->initInnerFrame(); - m_overlayMessages->showOverlayMessage(message, timeOutMs); - this->repaint(); - } - - void COverlayMessagesFrame::showOverlayMessages(const CStatusMessageList &messages, bool appendOldMessages, int timeOutMs) - { - if (messages.isEmpty()) { return; } - this->initInnerFrame(); - m_overlayMessages->showOverlayMessages(messages, appendOldMessages, timeOutMs); - this->repaint(); - } - - void COverlayMessagesFrame::showOverlayTextMessage(const Network::CTextMessage &textMessage, int timeOutMs) - { - if (textMessage.isEmpty()) { return; } - this->initInnerFrame(); - m_overlayMessages->showOverlayTextMessage(textMessage, timeOutMs); - this->repaint(); - } - - void COverlayMessagesFrame::showOverlayVariant(const CVariant &variant, int timeOutMs) - { - this->initInnerFrame(); - m_overlayMessages->showOverlayVariant(variant, timeOutMs); - this->repaint(); - } - - void COverlayMessagesFrame::showOverlayImage(const CPixmap &pixmap, int timeOutMs) - { - this->initInnerFrame(); - m_overlayMessages->showOverlayImage(pixmap, timeOutMs); - this->repaint(); - } - - void COverlayMessagesFrame::keyPressEvent(QKeyEvent *event) - { - if (m_overlayMessages && event->key() == Qt::Key_Escape) - { - m_overlayMessages->close(); - event->accept(); - } - else - { - QFrame::keyPressEvent(event); - } - } - - void COverlayMessagesFrame::resizeEvent(QResizeEvent *event) - { - QFrame::resizeEvent(event); - if (m_overlayMessages && m_overlayMessages->isVisible()) - { - this->initInnerFrame(); - } - } - - QSize COverlayMessagesFrame::innerFrameSize() const - { - // check against minimum if widget is initialized, but not yet resized - const int w = std::max(this->width(), this->minimumWidth()); - const int h = std::max(this->height(), this->minimumHeight()); - - int wInner = m_widthFactor * w; - int hInner = m_heightFactor * h; - if (wInner > this->maximumWidth()) { wInner = this->maximumWidth(); } - if (hInner > this->maximumHeight()) { hInner = this->maximumHeight(); } - return QSize(wInner, hInner); - } - - void COverlayMessagesFrame::initInnerFrame() - { - const QSize inner(innerFrameSize()); - if (!m_overlayMessages) - { - // lazy init - m_overlayMessages = new COverlayMessages(inner.width(), inner.height(), this); - m_overlayMessages->addShadow(); - m_overlayMessages->showKillButton(m_showKillButton); - m_overlayMessages->setForceSmall(m_forceSmallMsgs); - } - - Q_ASSERT(m_overlayMessages); - - const QPoint middle = this->geometry().center(); - const int w = inner.width(); - const int h = inner.height(); - const int x = middle.x() - w / 2; - const int y = middle.y() - h / m_middleFactor; - m_overlayMessages->setGeometry(x, y, w, h); - } + COverlayMessagesTabWidget::COverlayMessagesTabWidget(QWidget *parent) : COverlayMessagesBase(parent) + { } } // ns + + diff --git a/src/blackgui/overlaymessagesframe.h b/src/blackgui/overlaymessagesframe.h index 2d7d3a2b7..50cf44685 100644 --- a/src/blackgui/overlaymessagesframe.h +++ b/src/blackgui/overlaymessagesframe.h @@ -13,12 +13,16 @@ #define BLACKGUI_OVERLAYMESSAGES_FRAME_H #include "blackgui/blackguiexport.h" +#include "blackgui/overlaymessages.h" +#include "blackgui/guiutility.h" #include "blackmisc/pixmap.h" #include "blackmisc/statusmessage.h" #include "blackmisc/statusmessagelist.h" +#include "blackmisc/network/textmessage.h" #include "blackmisc/variant.h" #include +#include #include #include #include @@ -29,37 +33,53 @@ class QKeyEvent; class QPaintEvent; class QWidget; -namespace BlackMisc { namespace Network { class CTextMessage; } } namespace BlackGui { - class COverlayMessages; - /*! - * Display status messages (nested in this widget). - * Using this class provides a QFrame with the overlay functionality already integrated. + * Base class to display overlay messages in different widgets + * (nested in this widget). + * \fixme KB 2017-12 all header version, if someone manages to create a cpp version go ahead, I failed on gcc with "undefined reference to `BlackGui::COverlayMessagesBase::showOverlayMessages`" */ - class BLACKGUI_EXPORT COverlayMessagesFrame : public QFrame + template class COverlayMessagesBase : public WIDGET { - Q_OBJECT - public: - //! Constructor - explicit COverlayMessagesFrame(QWidget *parent = nullptr); - //! Destructor - virtual ~COverlayMessagesFrame(); + virtual ~COverlayMessagesBase() + { } //! Show the inner frame - void showStatusMessagesFrame(); + void showStatusMessagesFrame() + { + this->initInnerFrame(); + } //! Set the size factors - void setOverlaySizeFactors(double widthFactor, double heightFactor, double middleFactor); + void setOverlaySizeFactors(double widthFactor, double heightFactor, double middleFactor = 2) + { + m_widthFactor = widthFactor; + m_heightFactor = heightFactor; + if (middleFactor >=0) { m_middleFactor = middleFactor; } + } - //! Show kill button - void showKillButton(bool killButton); + //! \copydoc BlackGui::COverlayMessages::showKillButton + void showKillButton(bool killButton) + { + m_showKillButton = killButton; + if (m_overlayMessages) + { + m_overlayMessages->showKillButton(killButton); + } + } //! \copydoc COverlayMessages::setForceSmall - void setForceSmall(bool force); + void setForceSmall(bool force) + { + m_forceSmallMsgs = force; + if (m_overlayMessages) + { + m_overlayMessages->setForceSmall(force); + } + } //! \copydoc COverlayMessages::showOverlayMessagesWithConfirmation void showOverlayMessagesWithConfirmation( @@ -69,50 +89,172 @@ namespace BlackGui std::function okLambda, QMessageBox::StandardButton defaultButton = QMessageBox::Cancel, int timeOutMs = -1 - ); + ) + { + if (messages.isEmpty()) { return; } + this->initInnerFrame(); + m_overlayMessages->showOverlayMessagesWithConfirmation(messages, appendOldMessages, confirmationMessage, okLambda, defaultButton, timeOutMs); + WIDGET::repaint(); + } //! \copydoc COverlayMessages::clearOverlayMessages - void clearOverlayMessages(); + void clearOverlayMessages() + { + if (!m_overlayMessages) { return; } + m_overlayMessages->clearOverlayMessages(); + } //! \copydoc COverlayMessages::close - void closeOverlay(); + void closeOverlay() + { + if (!m_overlayMessages) { return; } + m_overlayMessages->close(); + } //! \copydoc COverlayMessages::showOverlayMessages - void showOverlayMessages(const BlackMisc::CStatusMessageList &messages, bool appendOldMessages = false, int timeOutMs = -1); + void showOverlayMessages(const BlackMisc::CStatusMessageList &messages, bool appendOldMessages = false, int timeOutMs = -1) + { + if (messages.isEmpty()) { return; } + this->initInnerFrame(); + m_overlayMessages->showOverlayMessages(messages, appendOldMessages, timeOutMs); + WIDGET::repaint(); + } //! \copydoc COverlayMessages::showOverlayMessage - void showOverlayMessage(const BlackMisc::CStatusMessage &message, int timeOutMs = -1); + void showOverlayMessage(const BlackMisc::CStatusMessage &message, int timeOutMs = -1) + { + if (message.isEmpty()) { return; } + this->initInnerFrame(); + m_overlayMessages->showOverlayMessage(message, timeOutMs); + WIDGET::repaint(); + } //! \copydoc COverlayMessages::showOverlayTextMessage - void showOverlayTextMessage(const BlackMisc::Network::CTextMessage &textMessage, int timeOutMs = -1); + void showOverlayTextMessage(const BlackMisc::Network::CTextMessage &textMessage, int timeOutMs = -1) + { + if (textMessage.isEmpty()) { return; } + this->initInnerFrame(); + m_overlayMessages->showOverlayTextMessage(textMessage, timeOutMs); + WIDGET::repaint(); + } //! \copydoc COverlayMessages::showOverlayVariant - void showOverlayVariant(const BlackMisc::CVariant &variant, int timeOutMs = -1); + void showOverlayVariant(const BlackMisc::CVariant &variant, int timeOutMs = -1) + { + this->initInnerFrame(); + m_overlayMessages->showOverlayVariant(variant, timeOutMs); + WIDGET::repaint(); + } //! \copydoc COverlayMessages::showOverlayImage - void showOverlayImage(const BlackMisc::CPixmap &pixmap, int timeOutMs = -1); + void showOverlayImage(const BlackMisc::CPixmap &pixmap, int timeOutMs = -1) + { + this->initInnerFrame(); + m_overlayMessages->showOverlayImage(pixmap, timeOutMs); + WIDGET::repaint(); + } protected: + COverlayMessages *m_overlayMessages = nullptr; //!< embedded QFrame with status messages + + //! Constructor + COverlayMessagesBase(QWidget *parent) : WIDGET(parent) + { + const bool isFrameless = CGuiUtility::isMainWindowFrameless(); + m_middleFactor = isFrameless ? 1.25 : 1.5; // 2 is middle in normal window + } + + //! Init the inner frame (if not yet initialized) + void initInnerFrame() + { + const QSize inner(innerFrameSize()); + if (!m_overlayMessages) + { + // lazy init + m_overlayMessages = new COverlayMessages(inner.width(), inner.height(), this); + m_overlayMessages->addShadow(); + m_overlayMessages->showKillButton(m_showKillButton); + m_overlayMessages->setForceSmall(m_forceSmallMsgs); + } + + Q_ASSERT(m_overlayMessages); + + const QPoint middle = WIDGET::geometry().center(); + const int w = inner.width(); + const int h = inner.height(); + const int x = middle.x() - w / 2; + const int y = middle.y() - h / m_middleFactor; + m_overlayMessages->setGeometry(x, y, w, h); + } + //! \copydoc QFrame::keyPressEvent - virtual void keyPressEvent(QKeyEvent *event) override; + virtual void keyPressEvent(QKeyEvent *event) override + { + if (m_overlayMessages && event->key() == Qt::Key_Escape) + { + m_overlayMessages->close(); + event->accept(); + } + else + { + WIDGET::keyPressEvent(event); + } + } //! \copydoc QFrame::resizeEvent - virtual void resizeEvent(QResizeEvent *event) override; - - COverlayMessages *m_overlayMessages = nullptr; //!< embedded QFrame with Status messages + virtual void resizeEvent(QResizeEvent *event) override + { + WIDGET::resizeEvent(event); + if (m_overlayMessages && m_overlayMessages->isVisible()) + { + this->initInnerFrame(); + } + } private: //! Calculate inner frame size - QSize innerFrameSize() const; + QSize innerFrameSize() const + { + // check against minimum if widget is initialized, but not yet resized + const int w = std::max(WIDGET::width(), WIDGET::minimumWidth()); + const int h = std::max(WIDGET::height(), WIDGET::minimumHeight()); - //! Init the inner frame (if not yet initialized) - void initInnerFrame(); + int wInner = m_widthFactor * w; + int hInner = m_heightFactor * h; + if (wInner > WIDGET::maximumWidth()) { wInner = WIDGET::maximumWidth(); } + if (hInner > WIDGET::maximumHeight()) { hInner = WIDGET::maximumHeight(); } + return QSize(wInner, hInner); + } - bool m_showKillButton = false; //!< show kill button - bool m_forceSmallMsgs = false; //!< force small messages - double m_widthFactor = 0.7; //!< inner frame x factor - double m_heightFactor = 0.6; //!< inner frame x factor - double m_middleFactor = 2; //!< 2 means middle, 1 means on top + bool m_showKillButton = false; //!< show kill button + bool m_forceSmallMsgs = false; //!< force small messages + double m_widthFactor = 0.7; //!< inner frame x factor + double m_heightFactor = 0.6; //!< inner frame x factor + double m_middleFactor = 2; //!< 2 means middle, 1 means on top + }; + + /*! + * Using this class provides a QFrame with the overlay functionality already integrated. + */ + class BLACKGUI_EXPORT COverlayMessagesFrame : public COverlayMessagesBase + { + Q_OBJECT + + public: + //! Constructor + explicit COverlayMessagesFrame(QWidget *parent = nullptr); + }; + + /*! + * Using this class provides a QTabWidget with the overlay functionality already integrated. + */ + class BLACKGUI_EXPORT COverlayMessagesTabWidget : public COverlayMessagesBase + { + Q_OBJECT + + public: + //! Constructor + explicit COverlayMessagesTabWidget(QWidget *parent = nullptr); }; } // ns