From 31af1687a62e3f524de57ee101f16974091b6131 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 28 Sep 2015 21:54:41 +0300 Subject: [PATCH] Improve handling error messages in console mode. --HG-- branch : develop --- src/app/tape/mapplication.cpp | 23 ++++-- src/app/tape/tmainwindow.cpp | 7 +- src/app/valentina/core/vapplication.cpp | 44 +++++++--- src/app/valentina/core/vcmdexport.cpp | 2 +- src/app/valentina/core/vcmdexport.h | 28 +------ .../valentina/dialogs/dialogsavelayout.cpp | 8 +- src/app/valentina/mainwindow.cpp | 4 +- src/app/valentina/mainwindowsnogui.cpp | 5 +- src/libs/vmisc/vmisc.pri | 3 +- src/libs/vmisc/vsysexits.h | 81 +++++++++++++++++++ 10 files changed, 148 insertions(+), 57 deletions(-) create mode 100644 src/libs/vmisc/vsysexits.h diff --git a/src/app/tape/mapplication.cpp b/src/app/tape/mapplication.cpp index e12175a75..eaf00bdff 100644 --- a/src/app/tape/mapplication.cpp +++ b/src/app/tape/mapplication.cpp @@ -35,6 +35,7 @@ #include "../ifc/exception/vexceptionemptyparameter.h" #include "../ifc/exception/vexceptionwrongid.h" #include "../vmisc/logging.h" +#include "../vmisc/vsysexits.h" #include "../qmuparser/qmuparsererror.h" #include @@ -89,6 +90,20 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con QCoreApplication *instance = QCoreApplication::instance(); const bool isGuiThread = instance && (QThread::currentThread() == instance->thread()); + switch (type) + { + case QtDebugMsg: + vStdOut() << msg << "\n"; + return; + case QtWarningMsg: + case QtCriticalMsg: + case QtFatalMsg: + vStdErr() << msg << "\n"; + break; + default: + break; + } + if (isGuiThread) { //fixme: trying to make sure there are no save/load dialogs are opened, because error message during them will @@ -98,9 +113,6 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con QMessageBox messageBox; switch (type) { - case QtDebugMsg: - std::cout << msg.toUtf8().constData() << std::endl; - return; case QtWarningMsg: messageBox.setIcon(QMessageBox::Warning); break; @@ -110,6 +122,7 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con case QtFatalMsg: messageBox.setIcon(QMessageBox::Critical); break; + case QtDebugMsg: default: break; } @@ -127,10 +140,6 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con messageBox.exec(); } } - else - { - std::cerr << msg.toUtf8().constData() << std::endl; - } } if (QtFatalMsg == type) diff --git a/src/app/tape/tmainwindow.cpp b/src/app/tape/tmainwindow.cpp index b3c02fba8..dd158f4a9 100644 --- a/src/app/tape/tmainwindow.cpp +++ b/src/app/tape/tmainwindow.cpp @@ -38,6 +38,7 @@ #include "../ifc/xml/vvstconverter.h" #include "../ifc/xml/vpatternconverter.h" #include "../vmisc/vlockguard.h" +#include "../vmisc/vsysexits.h" #include "vlitepattern.h" #include "../qmuparser/qmudef.h" #include "../vtools/dialogs/support/dialogeditwrongformula.h" @@ -162,7 +163,11 @@ void TMainWindow::LoadFile(const QString &path) { if (not QFileInfo(path).exists()) { - qCritical() << "File " << path << " doesn't exist"; + qCritical()<IsTestMode()) + { + std::exit(V_EX_NOINPUT); + } return; } diff --git a/src/app/valentina/core/vapplication.cpp b/src/app/valentina/core/vapplication.cpp index 32aa47158..f6e06609e 100644 --- a/src/app/valentina/core/vapplication.cpp +++ b/src/app/valentina/core/vapplication.cpp @@ -87,13 +87,9 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con QCoreApplication *instance = QCoreApplication::instance(); const bool isGuiThread = instance && (QThread::currentThread() == instance->thread()); - - if (isGuiThread) { - //fixme: trying to make sure there are no save/load dialogs are opened, because error message during them will lead to crash - const bool topWinAllowsPop = (qApp->activeModalWidget() == nullptr) || !qApp->activeModalWidget()->inherits("QFileDialog"); QString debugdate = "[" + QDateTime::currentDateTime().toString("yyyy.MM.dd hh:mm:ss"); - QMessageBox messageBox; + switch (type) { case QtDebugMsg: @@ -103,27 +99,53 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con case QtWarningMsg: debugdate += QString(":WARNING:%1(%2)] %3: %4: %5").arg(context.file).arg(context.line) .arg(context.function).arg(context.category).arg(msg); - messageBox.setIcon(QMessageBox::Warning); break; case QtCriticalMsg: debugdate += QString(":CRITICAL:%1(%2)] %3: %4: %5").arg(context.file).arg(context.line) .arg(context.function).arg(context.category).arg(msg); - messageBox.setIcon(QMessageBox::Critical); break; case QtFatalMsg: debugdate += QString(":FATAL:%1(%2)] %3: %4: %5").arg(context.file).arg(context.line) .arg(context.function).arg(context.category).arg(msg); - messageBox.setIcon(QMessageBox::Critical); break; default: break; } (*qApp->LogFile()) << debugdate << endl; + } + + if (type == QtWarningMsg || type == QtCriticalMsg || type == QtFatalMsg) + { + vStdErr() << msg << "\n"; + } + + if (isGuiThread) + { + //fixme: trying to make sure there are no save/load dialogs are opened, because error message during them will + //lead to crash + const bool topWinAllowsPop = (qApp->activeModalWidget() == nullptr) || + !qApp->activeModalWidget()->inherits("QFileDialog"); + + QMessageBox messageBox; + switch (type) + { + case QtWarningMsg: + messageBox.setIcon(QMessageBox::Warning); + break; + case QtCriticalMsg: + messageBox.setIcon(QMessageBox::Critical); + break; + case QtFatalMsg: + messageBox.setIcon(QMessageBox::Critical); + break; + case QtDebugMsg: + default: + break; + } if (type == QtWarningMsg || type == QtCriticalMsg || type == QtFatalMsg) { - if (VApplication::CheckGUI()) { if (topWinAllowsPop) @@ -135,10 +157,6 @@ inline void noisyFailureMsgHandler(QtMsgType type, const QMessageLogContext &con messageBox.exec(); } } - else - { - vStdErr() << msg << "\n"; - } } if (QtFatalMsg == type) diff --git a/src/app/valentina/core/vcmdexport.cpp b/src/app/valentina/core/vcmdexport.cpp index 8543deff6..8be5479f9 100644 --- a/src/app/valentina/core/vcmdexport.cpp +++ b/src/app/valentina/core/vcmdexport.cpp @@ -297,7 +297,7 @@ VCommandLine::~VCommandLine() Q_NORETURN void VCommandLine::Error(const QString &text) const { vStdErr() << text << "\n"; - const_cast(this)->parser.showHelp(FAILED_HELP_SHOWN_STATUS); + const_cast(this)->parser.showHelp(V_EX_USAGE); } //------------------------------------------------------------------------------------------------------ diff --git a/src/app/valentina/core/vcmdexport.h b/src/app/valentina/core/vcmdexport.h index bc268d5ed..6d7163487 100644 --- a/src/app/valentina/core/vcmdexport.h +++ b/src/app/valentina/core/vcmdexport.h @@ -5,6 +5,7 @@ #include #include "dialogs/dialoglayoutsettings.h" +#include "../vmisc/vsysexits.h" #if QT_VERSION < QT_VERSION_CHECK(5, 2, 0) # include "../libs/vmisc/backport/qcommandlineparser.h" @@ -12,33 +13,6 @@ # include #endif -constexpr auto GENERAL_ERROR_STATUS = 255; -constexpr auto INVALID_PARAMS_STATUS = 254; -constexpr auto FAILED_TO_GEN_LAYOUT_STATUS = 253; -constexpr auto FAILED_HELP_SHOWN_STATUS = 250; -constexpr auto FAILED_GEN_BASE_STATUS = 240; - -//--------------------------------------------------------------------------------------------------------------------- -inline QTextStream& vStdErr() -{ - static QTextStream ts( stderr ); - return ts; -} - -//--------------------------------------------------------------------------------------------------------------------- -Q_NORETURN inline void AppAbort(const QString& text = QString(), int code = GENERAL_ERROR_STATUS) -{ - //well ..std::runtime_error was leading to zombies in memory and a lot of dumping all the time ...better to do just exit - //possibly compiler do not have -fexceptions set - if (!text.isEmpty()) - { - vStdErr() << text << "\n"; - } - std::exit(code); -} -//--------------------------------------------------------------------------------------------------------------------- - - class VCommandLine; typedef std::shared_ptr VCommandLinePtr; diff --git a/src/app/valentina/dialogs/dialogsavelayout.cpp b/src/app/valentina/dialogs/dialogsavelayout.cpp index db1522b94..c0a7f71ff 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.cpp +++ b/src/app/valentina/dialogs/dialogsavelayout.cpp @@ -97,13 +97,15 @@ void DialogSaveLayout::SelectFormate(const size_t formate) { if (formate >= availFormats.size()) { - AppAbort(tr("Tried to use out of range format number."), INVALID_PARAMS_STATUS); + qCritical() << tr("Tried to use out of range format number."); + std::exit(V_EX_USAGE); } int i = ui->comboBoxFormat->findData(availFormats[formate].pair.second); if (i < 0) { - AppAbort(tr("Selected not present format."), INVALID_PARAMS_STATUS); + qCritical() << tr("Selected not present format."); + std::exit(V_EX_USAGE); } ui->comboBoxFormat->setCurrentIndex(i); } @@ -169,7 +171,7 @@ QString DialogSaveLayout::Formate() const void DialogSaveLayout::Save() { for (int i=0; i < count; ++i) - { + { const QString name = Path()+"/"+FileName()+QString::number(i+1)+Formate(); if (QFile::exists(name)) { diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index e4f10d6fe..00a1a72eb 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -3560,8 +3560,8 @@ void MainWindow::DoExport(const VCommandLinePtr &expParams) { if (details->count() == 0) { - AppAbort(tr("You can't export empty scene.")); - return; + qCCritical(vMainWindow, "%s", tr("You can't export empty scene.").toUtf8().constData()); + std::exit(V_EX_DATAERR); } } PrepareDetailsForLayout(details); diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp index 7c30007ce..4d74eb013 100644 --- a/src/app/valentina/mainwindowsnogui.cpp +++ b/src/app/valentina/mainwindowsnogui.cpp @@ -163,8 +163,9 @@ void MainWindowsNoGUI::ErrorConsoleMode(const LayoutErrors &state) default: break; } - //just added different return status in console mode - AppAbort(text, FAILED_GEN_BASE_STATUS + static_cast(state)); + + qCritical() << text; + std::exit(V_EX_DATAERR); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vmisc/vmisc.pri b/src/libs/vmisc/vmisc.pri index 775357374..742fd2fe5 100644 --- a/src/libs/vmisc/vmisc.pri +++ b/src/libs/vmisc/vmisc.pri @@ -27,4 +27,5 @@ HEADERS += \ $$PWD/vcommonsettings.h \ $$PWD/vtapesettings.h \ $$PWD/debugbreak.h \ - $$PWD/vlockguard.h + $$PWD/vlockguard.h \ + $$PWD/vsysexits.h diff --git a/src/libs/vmisc/vsysexits.h b/src/libs/vmisc/vsysexits.h new file mode 100644 index 000000000..6e5f33f60 --- /dev/null +++ b/src/libs/vmisc/vsysexits.h @@ -0,0 +1,81 @@ +/************************************************************************ + ** + ** @file vsysexits.h + ** @author Roman Telezhynskyi + ** @date 28 9, 2015 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2015 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#ifndef VSYSEXITS_H +#define VSYSEXITS_H + +#include + +constexpr auto V_EX_USAGE = 64; /*The command was used incorrectly, e.g., with the wrong number of arguments, a + bad flag, a bad syntax in a parameter, or whatever.*/ + +constexpr auto V_EX_DATAERR = 65; /*The input data was incorrect in some way. This should only be used for + user's data and not system files.*/ + +constexpr auto V_EX_NOINPUT = 66; /*An input file (not a system file) did not exist or was not readable.*/ + +constexpr auto V_EX_UNAVAILABLE = 69; /*A service is unavailable. This can occur if a support program or file does + not exist. This can also be used as a catchall message when something you + wanted to do doesn't work, but you don't know why.*/ + +constexpr auto V_EX_SOFTWARE = 70; /*An internal software error has been detected. This should be limited to + nonoperating operating system related errors as possible.*/ + +constexpr auto V_EX_OSERR = 71; /*An operating system error has been detected. This is intended to be used for + such things as ``cannot fork'', ``cannot create pipe'', or the like. It + includes things like getuid returning a user that does not exist in the passwd + file.*/ + +constexpr auto V_EX_OSFILE = 72; /*Some system file (e.g., /etc/passwd, /var/run/utmp, etc.) does not exist, cannot + be opened, or has some sort of error (e.g., syntax error).*/ + +constexpr auto V_EX_CANTCREAT = 73; /*A (user specified) output file cannot be created.*/ + +constexpr auto V_EX_IOERR = 74; /*An error occurred while doing I/O on some file.*/ + +constexpr auto V_EX_NOPERM = 77; /*You did not have sufficient permission to perform the operation. This is not + intended for file system problems, which should use EX_NOINPUT or EX_CANTCREAT, + but rather for higher level permissions.*/ + +constexpr auto V_EX_CONFIG = 78; /*Something was found in an unconfigured or misconfigured state.*/ + +//--------------------------------------------------------------------------------------------------------------------- +inline QTextStream& vStdErr() +{ + static QTextStream ts( stderr ); + return ts; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline QTextStream& vStdOut() +{ + static QTextStream ts( stdout ); + return ts; +} + +#endif // VSYSEXITS_H