Gui: Remove old signal for critical messages in favour of Notification Area
=========================================================================== The former system of autoclosing messageboxes is removed in favour of the Notification Area.
This commit is contained in:
committed by
abdullahtahiriyo
parent
340ccb8ed6
commit
eb7bf5d977
@@ -71,13 +71,6 @@ public:
|
||||
IgnoreErrorOnRecompute = 12, // Don't report errors if the recompute failed
|
||||
};
|
||||
|
||||
enum class NotificationType {
|
||||
Information,
|
||||
Warning,
|
||||
Error,
|
||||
Critical,
|
||||
};
|
||||
|
||||
/** @name Properties */
|
||||
//@{
|
||||
/// holds the long name of the document (utf-8 coded)
|
||||
@@ -177,8 +170,6 @@ public:
|
||||
boost::signals2::signal<void (const App::Document&, const std::vector<App::DocumentObject*>&)> signalSkipRecompute;
|
||||
boost::signals2::signal<void (const App::DocumentObject&)> signalFinishRestoreObject;
|
||||
boost::signals2::signal<void (const App::Document&,const App::Property&)> signalChangePropertyEditor;
|
||||
// signal user message
|
||||
boost::signals2::signal<void (const App::DocumentObject&, const QString &, NotificationType)> signalUserMessage;
|
||||
//@}
|
||||
boost::signals2::signal<void (std::string)> signalLinkXsetValue;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
# include <QMessageBox>
|
||||
# include <QTextStream>
|
||||
# include <QTimer>
|
||||
# include <QStatusBar>
|
||||
# include <Inventor/actions/SoSearchAction.h>
|
||||
# include <Inventor/nodes/SoSeparator.h>
|
||||
#endif
|
||||
@@ -55,6 +56,7 @@
|
||||
#include "FileDialog.h"
|
||||
#include "MainWindow.h"
|
||||
#include "MDIView.h"
|
||||
#include "NotificationArea.h"
|
||||
#include "Selection.h"
|
||||
#include "Thumbnail.h"
|
||||
#include "Tree.h"
|
||||
@@ -72,175 +74,6 @@ namespace bp = boost::placeholders;
|
||||
|
||||
namespace Gui {
|
||||
|
||||
/** This class is an implementation only class to handle user notifications offered by App::Document.
|
||||
*
|
||||
* It provides a mechanism requiring confirmation for critical notifications only during User initiated restore/document loading ( it
|
||||
* does not require confirmation for macro/Python initiated restore, not to interfere with automations).
|
||||
*
|
||||
* Additionally, it provides a mechanism to show autoclosing non-modal user notifications in a non-intrusive way.
|
||||
**/
|
||||
class MessageManager {
|
||||
public:
|
||||
MessageManager() = default;
|
||||
~MessageManager();
|
||||
|
||||
void setDocument(Gui::Document * pDocument);
|
||||
void slotUserMessage(const App::DocumentObject&, const QString &, App::Document::NotificationType);
|
||||
|
||||
|
||||
private:
|
||||
void reorderAutoClosingMessages();
|
||||
QMessageBox* createNonModalMessage(const QString & msg, App::Document::NotificationType notificationtype);
|
||||
void pushAutoClosingMessage(const QString & msg, App::Document::NotificationType notificationtype);
|
||||
void pushAutoClosingMessageTooManyMessages();
|
||||
|
||||
private:
|
||||
using Connection = boost::signals2::connection;
|
||||
Gui::Document * pDoc;
|
||||
Connection connectUserMessage;
|
||||
bool requireConfirmationCriticalMessageDuringRestoring = true;
|
||||
std::vector<QMessageBox*> openAutoClosingMessages;
|
||||
std::mutex mutexAutoClosingMessages;
|
||||
const int autoClosingTimeout = 5000; // ms
|
||||
const int autoClosingMessageStackingOffset = 10;
|
||||
const unsigned int maxNumberOfOpenAutoClosingMessages = 3;
|
||||
bool maxNumberOfOpenAutoClosingMessagesLimitReached = false;
|
||||
};
|
||||
|
||||
MessageManager::~MessageManager(){
|
||||
connectUserMessage.disconnect();
|
||||
}
|
||||
|
||||
void MessageManager::setDocument(Gui::Document * pDocument)
|
||||
{
|
||||
|
||||
pDoc = pDocument;
|
||||
|
||||
connectUserMessage = pDoc->getDocument()->signalUserMessage.connect
|
||||
(boost::bind(&Gui::MessageManager::slotUserMessage, this, bp::_1, bp::_2, bp::_3));
|
||||
|
||||
}
|
||||
|
||||
void MessageManager::slotUserMessage(const App::DocumentObject& obj, const QString & msg, App::Document::NotificationType notificationtype)
|
||||
{
|
||||
(void) obj;
|
||||
|
||||
auto userInitiatedRestore = Application::Instance->testStatus(Gui::Application::UserInitiatedOpenDocument);
|
||||
|
||||
if(notificationtype == App::Document::NotificationType::Critical && userInitiatedRestore && requireConfirmationCriticalMessageDuringRestoring) {
|
||||
auto confirmMsg = msg + QStringLiteral("\n\n") + QObject::tr("Do you want to skip confirmation of further critical message notifications while loading the file?");
|
||||
auto button = QMessageBox::critical(pDoc->getActiveView(), QObject::tr("Critical Message"), confirmMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No );
|
||||
|
||||
if(button == QMessageBox::Yes)
|
||||
requireConfirmationCriticalMessageDuringRestoring = false;
|
||||
}
|
||||
else { // Non-critical errors and warnings - auto-closing non-blocking message box
|
||||
|
||||
auto messageNumber = openAutoClosingMessages.size();
|
||||
|
||||
// Not opening more than the number of maximum autoclosing messages
|
||||
// If maximum reached, the mechanism only resets after all present messages are auto-closed
|
||||
if( messageNumber < maxNumberOfOpenAutoClosingMessages) {
|
||||
if(messageNumber == 0 && maxNumberOfOpenAutoClosingMessagesLimitReached) {
|
||||
maxNumberOfOpenAutoClosingMessagesLimitReached = false;
|
||||
}
|
||||
|
||||
if(!maxNumberOfOpenAutoClosingMessagesLimitReached) {
|
||||
pushAutoClosingMessage(msg, notificationtype);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!maxNumberOfOpenAutoClosingMessagesLimitReached)
|
||||
pushAutoClosingMessageTooManyMessages();
|
||||
|
||||
maxNumberOfOpenAutoClosingMessagesLimitReached = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageManager::pushAutoClosingMessage(const QString & msg, App::Document::NotificationType notificationtype)
|
||||
{
|
||||
std::lock_guard<std::mutex> g(mutexAutoClosingMessages); // guard to avoid creating new messages while closing old messages (via timer)
|
||||
|
||||
auto msgBox = createNonModalMessage(msg, notificationtype);
|
||||
|
||||
msgBox->show();
|
||||
|
||||
int numberOpenAutoClosingMessages = openAutoClosingMessages.size();
|
||||
|
||||
openAutoClosingMessages.push_back(msgBox);
|
||||
|
||||
reorderAutoClosingMessages();
|
||||
|
||||
QTimer::singleShot(autoClosingTimeout*numberOpenAutoClosingMessages, [msgBox, this](){
|
||||
std::lock_guard<std::mutex> g(mutexAutoClosingMessages); // guard to avoid closing old messages while creating new ones
|
||||
if(msgBox) {
|
||||
msgBox->done(0);
|
||||
openAutoClosingMessages.erase(
|
||||
std::remove(openAutoClosingMessages.begin(), openAutoClosingMessages.end(), msgBox),
|
||||
openAutoClosingMessages.end());
|
||||
|
||||
reorderAutoClosingMessages();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MessageManager::pushAutoClosingMessageTooManyMessages()
|
||||
{
|
||||
pushAutoClosingMessage(QObject::tr("Too many message notifications. Notification temporarily stopped. Look at the report view for more information."), App::Document::NotificationType::Warning);
|
||||
}
|
||||
|
||||
|
||||
QMessageBox* MessageManager::createNonModalMessage(const QString & msg, App::Document::NotificationType notificationtype)
|
||||
{
|
||||
auto parent = pDoc->getActiveView();
|
||||
|
||||
QMessageBox* msgBox = new QMessageBox(parent);
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose); // msgbox deleted automatically upon closed
|
||||
msgBox->setStandardButtons(QMessageBox::NoButton);
|
||||
msgBox->setWindowFlag(Qt::FramelessWindowHint,true);
|
||||
msgBox->setText(msg);
|
||||
|
||||
if(notificationtype == App::Document::NotificationType::Error) {
|
||||
msgBox->setWindowTitle(QObject::tr("Error"));
|
||||
msgBox->setIcon(QMessageBox::Critical);
|
||||
}
|
||||
else if(notificationtype == App::Document::NotificationType::Warning) {
|
||||
msgBox->setWindowTitle(QObject::tr("Warning"));
|
||||
msgBox->setIcon(QMessageBox::Warning);
|
||||
}
|
||||
else if(notificationtype == App::Document::NotificationType::Information) {
|
||||
msgBox->setWindowTitle(QObject::tr("Information"));
|
||||
msgBox->setIcon(QMessageBox::Information);
|
||||
}
|
||||
else if(notificationtype == App::Document::NotificationType::Critical) {
|
||||
msgBox->setWindowTitle(QObject::tr("Critical"));
|
||||
msgBox->setIcon(QMessageBox::Critical);
|
||||
}
|
||||
|
||||
msgBox->setModal( false ); // if you want it non-modal
|
||||
|
||||
return msgBox;
|
||||
}
|
||||
|
||||
void MessageManager::reorderAutoClosingMessages()
|
||||
{
|
||||
auto parent = pDoc->getActiveView();
|
||||
|
||||
int numberOpenAutoClosingMessages = openAutoClosingMessages.size();
|
||||
|
||||
auto x = parent->width() / 2;
|
||||
auto y = parent->height() / 7;
|
||||
|
||||
int posindex = numberOpenAutoClosingMessages - 1;
|
||||
for (auto rit = openAutoClosingMessages.rbegin(); rit != openAutoClosingMessages.rend(); ++rit, posindex--) {
|
||||
int xw = x - (*rit)->width() / 2 + autoClosingMessageStackingOffset*posindex;;
|
||||
int yw = y + autoClosingMessageStackingOffset*posindex;
|
||||
(*rit)->move(xw, yw);
|
||||
(*rit)->raise();
|
||||
}
|
||||
}
|
||||
|
||||
// Pimpl class
|
||||
struct DocumentP
|
||||
{
|
||||
@@ -301,8 +134,6 @@ struct DocumentP
|
||||
using ConnectionBlock = boost::signals2::shared_connection_block;
|
||||
ConnectionBlock connectActObjectBlocker;
|
||||
ConnectionBlock connectChangeDocumentBlocker;
|
||||
|
||||
MessageManager messageManager;
|
||||
};
|
||||
} // namespace Gui
|
||||
|
||||
@@ -384,7 +215,6 @@ Document::Document(App::Document* pcDocument,Application * app)
|
||||
d->connectTransactionRemove = pcDocument->signalTransactionRemove.connect
|
||||
(boost::bind(&Gui::Document::slotTransactionRemove, this, bp::_1, bp::_2));
|
||||
|
||||
d->messageManager.setDocument(this);
|
||||
// pointer to the python class
|
||||
// NOTE: As this Python object doesn't get returned to the interpreter we
|
||||
// mustn't increment it (Werner Jan-12-2006)
|
||||
|
||||
Reference in New Issue
Block a user