diff --git a/CMakeLists.txt b/CMakeLists.txt index d1c9142a059bcef15a1f58ef63e4cf79e1e68410..657813908d6f52ec5ca4406aa35a159820c952c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -302,6 +302,7 @@ target_sources(petrack_core PRIVATE include/trackingRoiItem.h include/analysePlot.h include/IO.h + include/pMessageBox.h ) target_sources(petrack_core PRIVATE @@ -351,6 +352,7 @@ target_sources(petrack_core PRIVATE src/extrCalibration.cpp src/trackingRoiItem.cpp src/IO.cpp + src/pMessageBox.cpp ui/codeMarker.ui ui/colorMarker.ui ui/colorRange.ui diff --git a/include/pMessageBox.h b/include/pMessageBox.h new file mode 100644 index 0000000000000000000000000000000000000000..7cccd3ea2374ddcbe2ea765ca674ae952679b1e9 --- /dev/null +++ b/include/pMessageBox.h @@ -0,0 +1,43 @@ +#ifndef PMESSAGEBOX_H +#define PMESSAGEBOX_H + +#include <QDialog> +#include <QDialogButtonBox> + +class QLabel; + +// need to define these macros to get the file/line/function of caller +// Should be replaced with std::source_location once C++20 is used +#define PInformation(...) PMessageBox::information(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define PWarning(...) PMessageBox::warning(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define PCritical(...) PMessageBox::critical(__FILE__, __func__, __LINE__, __VA_ARGS__) +#define PQuestion(...) PMessageBox::question(__FILE__, __func__, __LINE__, __VA_ARGS__) + + +/** + * @brief The PMessageBox class is similar to QMessageBox, but also allows usage in unsupervied scripts. + * + * The PMessageBox can be constructed like a QMessageBox. If the user is using PeTrack interactively, + * it also opens a messagebox, like QMessageBox. But it also logs the message. If the user uses + * PeTrack with an auto-option, the graphical boxes are not displayed anymore and only logging remains (TO BE DONE). + */ +class PMessageBox final : public QDialog +{ + Q_OBJECT + +public: + using StandardButton = QDialogButtonBox::StandardButton; + using StandardButtons = QDialogButtonBox::StandardButtons; + + PMessageBox(QWidget *parent, const QString& title, const QString& msg, const QIcon& icon, const QString& informativeText = QString(), StandardButtons buttons = StandardButton::Ok, StandardButton defaultButton = StandardButton::NoButton); + + static int information(const char*file, const char*func, int line, QWidget *parent, const QString& title, const QString& text, StandardButtons buttons = StandardButton::Ok, StandardButton defaultButton = StandardButton::NoButton); + static int warning(const char*file, const char*func, int line, QWidget *parent, const QString& title, const QString& text, StandardButtons buttons = StandardButton::Ok, StandardButton defaultButton = StandardButton::NoButton); + static int critical(const char*file, const char*func, int line, QWidget *parent, const QString& title, const QString& text, StandardButtons buttons = StandardButton::Ok, StandardButton defaultButton = StandardButton::NoButton); + [[nodiscard]] static int question(const char*file, const char*func, int line, QWidget *parent, const QString& title, const QString& text, StandardButtons buttons = (StandardButton::Yes | StandardButton::No), StandardButton defaultButton = StandardButton::NoButton); + +private: + static void setMinimumWidth(QLabel *textLabel); +}; + +#endif // PMESSAGEBOX_H diff --git a/src/animation.cpp b/src/animation.cpp index bd717b0386ad7d30e480d8d9f97b73a48e509320..f4f6cc0bc819c66984faa53c8ffa4904c38d4749 100644 --- a/src/animation.cpp +++ b/src/animation.cpp @@ -44,7 +44,6 @@ they can be represented in QT. #include <QList> #include <QTime> #include <QThread> -#include <QMessageBox> #include <string> #include <fstream> @@ -56,6 +55,7 @@ they can be represented in QT. #include "opencv2/opencv.hpp" +#include "pMessageBox.h" #include "animation.h" using namespace::cv; @@ -748,7 +748,7 @@ Mat Animation::getFramePhoto(int index) debout << "Could not load image: image size differs in image sequence" << endl; debout << "Please ensure to have images of the same size!" << endl; - QMessageBox::critical(NULL,"An error has occurred!", + PCritical(nullptr,"An error has occurred!", QString("The size of the images in the selected image sequence does not agree." "<br /><br />[0]: %1 (%2x%3 pixel)<br />[%4]: %5 (%6x%7 pixel)") .arg(mImgFilesList.at(0)).arg(mSize.width()).arg(mSize.height()).arg(index) diff --git a/src/autoCalib.cpp b/src/autoCalib.cpp index 2da073133196e0235b43de2a73f546f25d6c6731..970c4f28f5769468857948ba8838261501627477 100644 --- a/src/autoCalib.cpp +++ b/src/autoCalib.cpp @@ -20,7 +20,6 @@ #include <QFileInfo> #include <QFileDialog> -#include <QMessageBox> #include <QProgressDialog> #include <QApplication> @@ -29,6 +28,7 @@ #include "autoCalib.h" #include "petrack.h" #include "control.h" +#include "pMessageBox.h" using namespace::cv; using namespace std; @@ -122,7 +122,7 @@ void AutoCalib::autoCalib() // no files are selected for calibration if (mCalibFiles.isEmpty()) { - QMessageBox::information(mMainWindow, Petrack::tr("Petrack"), Petrack::tr("At first you have to select files.")); + PInformation(mMainWindow, Petrack::tr("Petrack"), Petrack::tr("At first you have to select files.")); return; } @@ -164,7 +164,7 @@ void AutoCalib::autoCalib() if (view.empty()) { progress.setValue(mCalibFiles.size()); - QMessageBox::critical(mMainWindow, Petrack::tr("Petrack"), Petrack::tr("Cannot load %1.\nTerminate Calibration.").arg(mCalibFiles.at(i))); + PCritical(mMainWindow, Petrack::tr("Petrack"), Petrack::tr("Cannot load %1.\nTerminate Calibration.").arg(mCalibFiles.at(i))); #ifdef SHOW_CALIB_MAINWINDOW // reset view to animation image if (!origImg.empty()) @@ -211,10 +211,9 @@ void AutoCalib::autoCalib() if( !min_one_pattern_found ) { debout << "Calibration failed. No patterns found!" << endl; - QMessageBox::warning(mMainWindow, + PWarning(mMainWindow, QString("Calibration failed"), - QString("Chessboard pattern (%1x%2) not found in calibration files.").arg(board_size.width).arg(board_size.height), - QMessageBox::Ok); + QString("Chessboard pattern (%1x%2) not found in calibration files.").arg(board_size.width).arg(board_size.height)); return; } diff --git a/src/control.cpp b/src/control.cpp index 6827ee08aee2a761d7b4cb147c9fe36442b48e96..daf6d80cad7c0f7480af3d4a18b2c85a04607ead 100644 --- a/src/control.cpp +++ b/src/control.cpp @@ -37,6 +37,7 @@ #include "multiColorMarkerWidget.h" #include "view.h" #include "IO.h" +#include "pMessageBox.h" using namespace std; @@ -1500,7 +1501,7 @@ void Control::on_mapReadHeights_clicked() } else //heights contains an error string { - QMessageBox::critical(mMainWindow, Petrack::tr("PeTrack"), + PCritical(mMainWindow, Petrack::tr("PeTrack"), Petrack::tr(std::get<std::string>(heights).c_str())); } diff --git a/src/extrCalibration.cpp b/src/extrCalibration.cpp index 245003c03a2fd3f40c8486812074551034818a53..e49e193277c447d59844b8c295d275b3790301c3 100644 --- a/src/extrCalibration.cpp +++ b/src/extrCalibration.cpp @@ -20,10 +20,9 @@ #include <QtWidgets> #include <QFileDialog> -#include <QMessageBox> #include "extrCalibration.h" - +#include "pMessageBox.h" #include "petrack.h" #include "control.h" @@ -131,7 +130,7 @@ bool ExtrCalibration::loadExtrCalibFile(){ QFile file(mExtrCalibFile); if( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) { - QMessageBox::critical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Error: Cannot open %1:\n%2.").arg(mExtrCalibFile).arg(file.errorString())); + PCritical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Error: Cannot open %1:\n%2.").arg(mExtrCalibFile, file.errorString())); return false; } @@ -233,22 +232,25 @@ bool ExtrCalibration::loadExtrCalibFile(){ // Check if there are more than 4 points for calibration in the file if( points3D_tmp.size() < 4 ) { - QMessageBox::critical(mMainWindow, QObject::tr("PeTrack"), QObject::tr("Error: Not enough points given: %1 (minimum 4 needed!). Please check your extrinsic calibration file!").arg(points3D_tmp.size())); + PCritical(mMainWindow, QObject::tr("PeTrack"), QObject::tr("Error: Not enough points given: %1 (minimum 4 needed!). Please check your extrinsic calibration file!").arg(points3D_tmp.size())); all_ok = false; } // Check if 2D points delivered and if the number of 2D and 3D points agree else if( points2D_tmp.size() > 0 && points2D_tmp.size() != points3D_tmp.size() ) { - QMessageBox::critical(mMainWindow, QObject::tr("PeTrack"), QObject::tr("Error: Unsupported File Format in: %1 (number of 3D (%2) and 2D (%3) points disagree!)").arg(mExtrCalibFile).arg(points3D_tmp.size()).arg(points2D_tmp.size())); + PCritical(mMainWindow, QObject::tr("PeTrack"), QObject::tr("Error: Unsupported File Format in: %1 (number of 3D (%2) and 2D (%3) points disagree!)").arg(mExtrCalibFile).arg(points3D_tmp.size()).arg(points2D_tmp.size())); all_ok = false; } // Check if number of loaded 3D points agree with stored 2D points else if( !with_2D_data && points2D.size()>0 && points3D_tmp.size() != points2D.size() ) { // ask if stored 2D points should be deleted? - int result = QMessageBox::warning(mMainWindow, QObject::tr("PeTrack"), QObject::tr("Number of 3D points (%1) disagree with number of stored 2D points (%2)!<br />The 2D points will be deleted! You have to fetch new ones from the image!").arg(points3D_tmp.size()).arg(points2D.size()),QMessageBox::Ok, QMessageBox::Abort); - if (result != QMessageBox::Ok) + int result = PWarning(mMainWindow, + QObject::tr("PeTrack"), + QObject::tr("Number of 3D points (%1) disagree with number of stored 2D points (%2)!<br />The 2D points will be deleted! You have to fetch new ones from the image!").arg(points3D_tmp.size()).arg(points2D.size()), + PMessageBox::StandardButton::Ok | PMessageBox::StandardButton::Abort); + if (result != PMessageBox::StandardButton::Ok) all_ok = false; else points2D.clear(); @@ -285,14 +287,14 @@ bool ExtrCalibration::fetch2DPoints() bool all_ok = true; if( !mMainWindow->getTracker() || mMainWindow->getTracker()->size() < 4 ) { - QMessageBox::critical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Error: At minimum four 3D calibration points needed for 3D calibration.")); + PCritical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Error: At minimum four 3D calibration points needed for 3D calibration.")); all_ok = false; }else { size_t sz_2d = mMainWindow->getTracker()->size(); if( points3D.size()>0 && sz_2d != points3D.size() ){ - QMessageBox::critical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Count of 2D-Points (%1) and 3D-Points (%2) disagree").arg(sz_2d).arg(points3D.size())); + PCritical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Count of 2D-Points (%1) and 3D-Points (%2) disagree").arg(sz_2d).arg(points3D.size())); all_ok = false; } @@ -340,23 +342,25 @@ bool ExtrCalibration::saveExtrCalibPoints() { out << "[" << QString::number(i+1,'i',0) << "]: "<< QString::number(points3D.at(i).x,'f',1) << " " << QString::number(points3D.at(i).y,'f',1) << " " << QString::number(points3D.at(i).z,'f',1) << " " << QString::number(points2D.at(i).x,'f',3) << " " << QString::number(points2D.at(i).y,'f',3) << Qt::endl; } - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Warning); - msgBox.setText("The corresponding calibration points have been changed."); - msgBox.setInformativeText("Do you want to save your changes?"); - msgBox.setDetailedText(out_str); - msgBox.setStandardButtons(QMessageBox::QMessageBox::Save | QMessageBox::Cancel); - msgBox.setDefaultButton(QMessageBox::Save); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + PMessageBox msgBox {nullptr, "PeTrack", + "The corresponding calibration points have been changed.\n" + "Do you want to save your changes?", + QIcon(), + out_str, + PMessageBox::StandardButton::Save | PMessageBox::StandardButton::Cancel, + PMessageBox::StandardButton::Save}; int ret = msgBox.exec(); switch (ret) { - case QMessageBox::Save: + case PMessageBox::StandardButton::Save: { // Save was clicked QFile file(mExtrCalibFile); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QMessageBox::critical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Cannot open %1:\n%2.").arg(mExtrCalibFile).arg(file.errorString())); + PCritical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Cannot open %1:\n%2.").arg(mExtrCalibFile).arg(file.errorString())); return false; } @@ -371,10 +375,10 @@ bool ExtrCalibration::saveExtrCalibPoints() file.close(); break; } - case QMessageBox::Discard: + case PMessageBox::StandardButton::Discard: // Don't Save was clicked break; - case QMessageBox::Cancel: + case PMessageBox::StandardButton::Cancel: // Cancel was clicked break; default: @@ -559,7 +563,7 @@ void ExtrCalibration::calibExtrParams() reprojectionError.clear(); - QMessageBox::critical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Error: Could not calculate extrinsic calibration. Please select other 2D/3D point correspondences for extrinsic calibration!")); + PCritical(mMainWindow, QObject::tr("Petrack"), QObject::tr("Error: Could not calculate extrinsic calibration. Please select other 2D/3D point correspondences for extrinsic calibration!")); isExtCalib = false; diff --git a/src/pMessageBox.cpp b/src/pMessageBox.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33ad8a5b3098f308799c62fcf7f233df588f7d32 --- /dev/null +++ b/src/pMessageBox.cpp @@ -0,0 +1,274 @@ +#include "pMessageBox.h" + +#include <QGridLayout> +#include <QLabel> +#include <QStyle> +#include <QDialogButtonBox> +#include <QPushButton> +#include <QApplication> +#include <QTextDocument> + +#include "helper.h" + +/** + * @brief Constructs a PMessageBox + * + * @param parent pointer to parent widget + * @param title title of the dialog window + * @param msg message to display on the dialog + * @param icon icon to display (e.g. yellow warning triangle) + * @param informativeText longer text (or table via html/rich text) to show + * @param buttons buttons for the user to click default: only Ok) + * @param defaultButton button used when pressing enter + */ +PMessageBox::PMessageBox(QWidget *parent, const QString& title, const QString& msg, const QIcon& icon, const QString& informativeText, StandardButtons buttons, StandardButton defaultButton) : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) +{ + QGridLayout* layout = new QGridLayout(); + setLayout(layout); + + QFont f = QApplication::font("QMessageBox"); + Qt::TextInteractionFlags flags(style()->styleHint(QStyle::SH_MessageBox_TextInteractionFlags, nullptr, this)); + + QLabel *detailedText = new QLabel(this); + if(!informativeText.isEmpty()) + { + detailedText->setWordWrap(true); + detailedText->setTextInteractionFlags(flags); + detailedText->setFont(f); + detailedText->setText(informativeText); + layout->addWidget(detailedText, 1, 1); + } + + QLabel* text = new QLabel(this); + text->setWordWrap(true); + text->setTextInteractionFlags(flags); + text->setFont(f); + text->setText(msg); + layout->addWidget(text, 0,1); + + setWindowTitle(title); + QLabel* infoIcon = new QLabel(this); + int iconSize = style()->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, this); + infoIcon->setPixmap(icon.pixmap(iconSize, iconSize)); + layout->addWidget(infoIcon, 0, 0); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(buttons, this); + layout->addWidget(buttonBox, 2, 1); + if(defaultButton != StandardButton::NoButton){ + QPushButton *def = buttonBox->button(defaultButton); + if(def){ + def->setAutoDefault(false); + def->setDefault(true); + }else{ + debout << "Warning: Given default button does is non-specified button" << std::endl; + } + + } + + // return the clicked button; -1 if none was clicked + connect(buttonBox, &QDialogButtonBox::clicked, this, [=](QAbstractButton *button){ + int ret = buttonBox->standardButton(button); + if(ret == StandardButton::NoButton){ + this->done(-1); + }else{ + this->done(ret); + } + }); + + layout->setSpacing(20); + + setMinimumWidth(text); + setMinimumWidth(detailedText); + + setFixedSize(sizeHint()); +} + +/** + * @brief Opens a dialog with given title, text and buttons and also logs the message. + * + * This Method opens a modal dialog with given text and buttons. The + * dialogue has an information-icon and is logged with info-level. + * + * The pressed button is returned, i.e. PMessageBox::StandardButton::Yes. + * + * @param parent Pointer to parent + * @param title title of dialog window + * @param text message to the user + * @param buttons buttons to use (default: OK) + * @param defaultButton button to press, when pressing enter + * @return clicked button + */ +int PMessageBox::information(const char*file, + const char*func, + int line, QWidget *parent, + const QString &title, + const QString &text, + PMessageBox::StandardButtons buttons, + PMessageBox::StandardButton defaultButton) +{ + std::cout << func << " in " << file_name(file) << " line " << line << ": Info: " << text << std::endl; + + // if no GUI gets displayed and no button except OK is used (no return Value used) + // Then only log it + if(QGuiApplication::platformName() == "offscreen") + { + if(buttons & (~StandardButton::Ok)) + { + throw std::runtime_error( + QString("user-interaction demanded during offscreen mode with message\n%1") + .arg(text).toStdString() + ); + } + + return StandardButton::NoButton; + } + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + PMessageBox msg = PMessageBox(parent, title, text, icon, QString(), buttons, defaultButton); + return msg.exec(); +} + +/** + * @brief Opens a dialog with given title, text and buttons and also logs the message. + * + * This Method opens a modal dialog with given text and buttons. The + * dialogue has an warning-icon and is logged with warning-level. + * + * The pressed button is returned, i.e. PMessageBox::StandardButton::Yes. + * + * @param parent Pointer to parent + * @param title title of dialog window + * @param text message to the user + * @param buttons buttons to use (default: OK) + * @param defaultButton button to press, when pressing enter + * @return clicked button + */ +int PMessageBox::warning(const char* file, + const char* func, + int line, + QWidget *parent, + const QString &title, + const QString &text, + PMessageBox::StandardButtons buttons, + PMessageBox::StandardButton defaultButton) +{ + std::cout << func << " in " << file_name(file) << " line " << line << ": Warning: " << text << std::endl; + + // if no GUI gets displayed and no button except OK is used (no return Value used) + // Then only log it + if(QGuiApplication::platformName() == "offscreen") + { + if(buttons & (~StandardButton::Ok)) + { + throw std::runtime_error( + QString("user-interaction demanded during offscreen mode with message\n%1") + .arg(text).toStdString() + ); + } + + return StandardButton::NoButton; + } + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + PMessageBox msg = PMessageBox(parent, title, text, icon, QString(), buttons, defaultButton); + return msg.exec(); +} + +/** + * @brief Opens a dialog with given title, text and buttons and also logs the message. + * + * This Method opens a modal dialog with given text and buttons. The + * dialogue has an critical-icon and is logged with critical(error?)-level. + * + * The pressed button is returned, i.e. PMessageBox::StandardButton::Yes. + * + * @param parent Pointer to parent + * @param title title of dialog window + * @param text message to the user + * @param buttons buttons to use (default: OK) + * @param defaultButton button to press, when pressing enter + * @return clicked button + */ +int PMessageBox::critical(const char*file, + const char*func, + int line, + QWidget *parent, + const QString &title, + const QString &text, + PMessageBox::StandardButtons buttons, + PMessageBox::StandardButton defaultButton) +{ + std::cout << func << " in " << file_name(file) << " line " << line << ": Critical: " << text << std::endl; + + // if no GUI gets displayed and no button except OK is used (no return Value used) + // Then only log it + if(QGuiApplication::platformName() == "offscreen") + { + if(buttons & (~StandardButton::Ok)) + { + throw std::runtime_error( + QString("user-interaction demanded during offscreen mode with message\n%1") + .arg(text).toStdString() + ); + } + + return StandardButton::NoButton; + } + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical); + PMessageBox msg = PMessageBox(parent, title, text, icon, QString(), buttons, defaultButton); + return msg.exec(); +} + +/** + * @brief Opens a dialog with given title, text and buttons and returns chosen action. + * + * This Method opens a modal dialog with given text and buttons. The + * Dialog defaults to a yes and no button and returns accordingly. + * + * The pressed button is returned, i.e. PMessageBox::StandardButton::Yes. + * + * @param parent Pointer to parent + * @param title title of dialog window + * @param text message to the user + * @param buttons buttons to use (default: OK) + * @param defaultButton button to press, when pressing enter + * @return clicked button + */ +int PMessageBox::question(const char* /*file*/, + const char* /*func*/, + int /*line*/, + QWidget *parent, + const QString &title, + const QString &text, + PMessageBox::StandardButtons buttons, + PMessageBox::StandardButton defaultButton) +{ + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxQuestion); + PMessageBox msg = PMessageBox(parent, title, text, icon, QString(), buttons, defaultButton); + + // no debout, since question **demands** user interaction; also no support for scripting to come + if(QGuiApplication::platformName() == "offscreen") + { + throw std::runtime_error( + QString("user-interaction demanded during offscreen mode with message\n%1") + .arg(text).toStdString() + ); + } + + return msg.exec(); +} + +void PMessageBox::setMinimumWidth(QLabel *textLabel) +{ + QTextDocument doc; + if(Qt::mightBeRichText(textLabel->text())){ + doc.setHtml(textLabel->text()); + }else{ + doc.setPlainText(textLabel->text()); + } + doc.setDefaultFont(textLabel->font()); + doc.setTextWidth(textLabel->fontMetrics().averageCharWidth()*120); + + textLabel->setMinimumWidth(static_cast<int>(doc.idealWidth())); +} diff --git a/src/petrack.cpp b/src/petrack.cpp index 4e3994c89a5497b5e4f15fa1baed77defbe5e404..d877005c7ef8c397ab93918765627f229b323912 100644 --- a/src/petrack.cpp +++ b/src/petrack.cpp @@ -50,6 +50,7 @@ #include "tracker.h" #include "trackerReal.h" #include "cmath" +#include "pMessageBox.h" #ifdef AVI #include "aviFile.h" #else @@ -626,14 +627,14 @@ void Petrack::openProject(QString fileName, bool openSeq) // default fileName="" QFile file(fileName); if (!file.open(QIODevice::ReadOnly)) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(fileName).arg(file.errorString())); + PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(fileName, file.errorString())); return; } resetSettings(); QDomDocument doc("PETRACK"); // eigentlich Pfad zu Beschreibungsdatei fuer Dateiaufbau if (!doc.setContent(&file)) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot read content from %1.").arg(fileName)); + PCritical(this, tr("PeTrack"), tr("Cannot read content from %1.").arg(fileName)); file.close(); return; } @@ -647,7 +648,7 @@ void Petrack::openProject(QString fileName, bool openSeq) // default fileName="" if (root.hasAttribute("VERSION")) if (root.attribute("VERSION") != VERSION) { - QMessageBox::warning(this, tr("PeTrack"), tr("Reading %1:\nDifferent version numbers %2 (application) and %3 (file) may cause problems.").arg(fileName).arg(VERSION).arg(root.attribute("VERSION"))); + PWarning(this, tr("PeTrack"), tr("Reading %1:\nDifferent version numbers %2 (application) and %3 (file) may cause problems.").arg(fileName, VERSION, root.attribute("VERSION"))); //tr("Cannot read content from %1\nbecause of different version numbers\n%2 (application) and %3 (file).").arg(fileName).arg(VERSION).arg(root.attribute("VERSION"))); //return; } @@ -773,7 +774,7 @@ bool Petrack::saveProject(QString fileName) // default fileName="" QFile file(fileName); if (!file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text)) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot save %1:\n%2.").arg(fileName).arg(file.errorString())); + PCritical(this, tr("PeTrack"), tr("Cannot save %1:\n%2.").arg(fileName, file.errorString())); file.close(); return false; } @@ -837,7 +838,7 @@ void Petrack::openCameraLiveStream(int camID /* =-1*/) } if (!mAnimation->openCameraStream(camID)) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot start Camera Livestream.")); + PCritical(this, tr("PeTrack"), tr("Cannot start Camera Livestream.")); return; } mSeqFileName = "camera live stream"; @@ -866,7 +867,7 @@ void Petrack::openSequence(QString fileName) // default fileName = "" { if (!mAnimation->openAnimation(fileName)) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot load %1.").arg(fileName)); + PCritical(this, tr("PeTrack"), tr("Cannot load %1.").arg(fileName)); return; } @@ -1221,7 +1222,7 @@ void Petrack::saveSequence(bool saveVideo, bool saveView, QString dest) // defau if (!writeFrameRet) { progress.setValue(progEnd); - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot save %1 maybe because of wrong file extension or unsupported codec.").arg(dest)); + PCritical(this, tr("PeTrack"), tr("Cannot save %1 maybe because of wrong file extension or unsupported codec.").arg(dest)); break; } } @@ -1264,7 +1265,7 @@ void Petrack::saveSequence(bool saveVideo, bool saveView, QString dest) // defau if (!saveRet) { progress.setValue(progEnd); - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot save %1.").arg(fileName)); + PCritical(this, tr("PeTrack"), tr("Cannot save %1.").arg(fileName)); break; } } @@ -1349,7 +1350,7 @@ void Petrack::saveView(QString dest) //default = "" mScene->render(&painter); painter.end(); if (!img->save(dest)) //, "PNG" - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot save %1 maybe because of wrong file extension.").arg(dest)); + PCritical(this, tr("PeTrack"), tr("Cannot save %1 maybe because of wrong file extension.").arg(dest)); delete img; } lastFile = dest; @@ -1398,7 +1399,7 @@ void Petrack::saveImage(QString dest) //default = "" else { if (!mImage->save(dest)) //, "PNG" - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot save %1 maybe because of wrong file extension.").arg(dest)); + PCritical(this, tr("PeTrack"), tr("Cannot save %1 maybe because of wrong file extension.").arg(dest)); } lastFile = dest; } @@ -1435,7 +1436,7 @@ void Petrack::print() } } else - QMessageBox::critical(this, tr("PeTrack"), tr("Nothing to print!")); + PCritical(this, tr("PeTrack"), tr("Nothing to print!")); } void Petrack::resetSettings() @@ -1463,18 +1464,9 @@ void Petrack::about() void Petrack::commandLineOptions() { - //QTextBrowser(this); - //static QMessageBox* mb = NULL; - //if (mb == NULL) - //{ - QMessageBox* mb = new QMessageBox(this); //QMessageBox mb(this); + PMessageBox *mb = new PMessageBox{this, tr("Command line options"), commandLineOptionsString, QIcon()}; + mb->setModal(false); mb->setAttribute(Qt::WA_DeleteOnClose); - mb->setWindowTitle(tr("Command line options")); - //mb->setWindowModality(Qt::NonModal); - mb->setModal(false); // if you want it non-modal - mb->setText(commandLineOptionsString); - mb->setStandardButtons(QMessageBox::Ok); - //} //"<style>spantab {padding-left: 4em; margin-left:5em}</style><span class=\"tab\"></span>" //"<p>Only to convert a video <kbd>video.avi</kbd> with settings stored in a petrack project file <kbd>project.pet</kbd> to an image sequence to be stored in the directory <kbd>folder</kbd> call:<br>" @@ -1490,11 +1482,7 @@ void Petrack::commandLineOptions() - mb->show(); //mb->exec(); //mb->open(); - - // QMessageBox::about(this, tr("Command line options"), tr( -//"Beside the space bar all bindings only affect inside the image.<p>" -//"Space bar<br>blavbla")); + mb->show(); //Usage: petrack [-help|-?] [[-project] project.pet] [-sequence image_sequence_or_video] [-autoSave|-autosave image_folder_or_video|project.pet|tracker_file] [-autoTrack|-autotrack tracker_file] [-autoPlay|-autoplay tracker_file] @@ -1516,31 +1504,31 @@ void Petrack::commandLineOptions() void Petrack::keyBindings() { - QMessageBox* mb = new QMessageBox(this); + const QString out = tr( + "<p>Beside the space bar all bindings only affect inside the image.</p>" + "<dl><dt><kbd>Space bar</kbd></dt><dd>toggles between pause and last play direction</dd>" + "<dt><kbd>Mouse scroll wheel</kbd></dt><dd>zooms in and out to or from the pixel of the image at the position of the mouse pointer</dd>" + "<dt><kbd>Shift + mouse scroll wheel</kbd></dt><dd>plays forwards or backwards frame by frame</dd>" + "<dt><kbd>Holding left mouse button</kbd></dt><dd>moves image</dd>" + "<dt><kbd>Arrows up/down</kbd></dt><dd>zoom in/out</dd>" + "<dt><kbd>Arrows left/right</kbd></dt><dd>frame back/forward</dd>" + "<dt><kbd>Double-click left mouse button</kbd></dt><dd>opens video or image sequence</dd>" + "<dt><kbd>Ctrl + double-click left mouse button</kbd></dt><dd>inserts new or moves near trackpoint</dd>" + "<dt><kbd>Ctrl + Shift + double-click left mouse button</kbd></dt><dd>splits near trackpoint before actual frame</dd>" + "<dt><kbd>Ctrl + double-click right mouse button</kbd></dt><dd>deletes a trajectory of a near trackpoint</dd>" + "<dt><kbd>Shift + double-click right mouse button</kbd></dt><dd>deletes the past part of a trajectory of a near trackpoint</dd>" + "<dt><kbd>Alt + double-click right mouse button</kbd></dt><dd>deletes the future part of a trajectory of a near trackpoint</dd>" + "<dt><kbd>Ctrl + double-click middle mouse button</kbd></dt><dd>deletes all trajectories</dd>" + "<dt><kbd>Shift + double-click middle mouse button</kbd></dt><dd>deletes the past part of all trajectories</dd>" + "<dt><kbd>Alt + double-click middle mouse button</kbd></dt><dd>deletes the future part of all trajectories</dd>" + "<dt><kbd>Shift + t</kbd></dt><dd>toggles tracking online calculation</dd>" + "<dt><kbd>Shift + double-click left mouse button</kbd></dt><dd>inserts new or moves near trackpoint and enables showing only the modified trajectory</dd></dl>" + "<p>Further key bindings you will find next to the entries of the menus.</p>" + ); + + PMessageBox *mb = new PMessageBox(this, tr("Key Bindings"), out, QIcon()); mb->setAttribute(Qt::WA_DeleteOnClose); - mb->setWindowTitle(tr("Command line options")); - mb->setModal(false); // if you want it non-modal - mb->setText(tr( -"<p>Beside the space bar all bindings only affect inside the image.</p>" -"<dl><dt><kbd>Space bar</kbd></dt><dd>toggles between pause and last play direction</dd>" -"<dt><kbd>Mouse scroll wheel</kbd></dt><dd>zooms in and out to or from the pixel of the image at the position of the mouse pointer</dd>" -"<dt><kbd>Shift + mouse scroll wheel</kbd></dt><dd>plays forwards or backwards frame by frame</dd>" -"<dt><kbd>Holding left mouse button</kbd></dt><dd>moves image</dd>" -"<dt><kbd>Arrows up/down</kbd></dt><dd>zoom in/out</dd>" -"<dt><kbd>Arrows left/right</kbd></dt><dd>frame back/forward</dd>" -"<dt><kbd>Double-click left mouse button</kbd></dt><dd>opens video or image sequence</dd>" -"<dt><kbd>Ctrl + double-click left mouse button</kbd></dt><dd>inserts new or moves near trackpoint</dd>" -"<dt><kbd>Ctrl + Shift + double-click left mouse button</kbd></dt><dd>splits near trackpoint before actual frame</dd>" -"<dt><kbd>Ctrl + double-click right mouse button</kbd></dt><dd>deletes a trajectory of a near trackpoint</dd>" -"<dt><kbd>Shift + double-click right mouse button</kbd></dt><dd>deletes the past part of a trajectory of a near trackpoint</dd>" -"<dt><kbd>Alt + double-click right mouse button</kbd></dt><dd>deletes the future part of a trajectory of a near trackpoint</dd>" -"<dt><kbd>Ctrl + double-click middle mouse button</kbd></dt><dd>deletes all trajectories</dd>" -"<dt><kbd>Shift + double-click middle mouse button</kbd></dt><dd>deletes the past part of all trajectories</dd>" -"<dt><kbd>Alt + double-click middle mouse button</kbd></dt><dd>deletes the future part of all trajectories</dd>" -"<dt><kbd>Shift + t</kbd></dt><dd>toggles tracking online calculation</dd>" -"<dt><kbd>Shift + double-click left mouse button</kbd></dt><dd>inserts new or moves near trackpoint and enables showing only the modified trajectory</dd></dl>" -"<p>Further key bindings you will find next to the entries of the menus.</p>" - )); + mb->setModal(false); //"Beside the space bar all bindings only affect inside the image.<p>" //"Space bar<br>" @@ -1575,16 +1563,14 @@ void Petrack::keyBindings() //" inserts new or moves near trackpoint and enables showing only the modified trajectory<p>" //"Further key bindings you will find next to the entries of the menus." - mb->setStandardButtons(QMessageBox::Ok); mb->show(); - //QMessageBox::about(NULL, tr("Key bindings"), tr( } void Petrack::onlineHelp() { static QUrl url("https://jugit.fz-juelich.de/ped-dyn-emp/petrack/-/wikis/home"); if (!(QDesktopServices::openUrl(url))) - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot open external browser<br>with url ") + url.toString() + "!"); + PCritical(this, tr("PeTrack"), tr("Cannot open external browser<br>with url ") + url.toString() + "!"); } void Petrack::antialias() @@ -2405,23 +2391,24 @@ void Petrack::writeSettings() bool Petrack::maybeSave() { - int ret = QMessageBox::warning(this, tr("PeTrack"), - tr("Do you want to save\n" + int ret = PWarning(this, tr("PeTrack"), + tr("Do you want to save " "the current project?\n" - "Be sure to save trajectories, background\n" + "Be sure to save trajectories, background " "and 3D calibration point separately!"), - QMessageBox::Yes | QMessageBox::Default, - QMessageBox::No, - QMessageBox::Cancel | QMessageBox::Escape); + PMessageBox::StandardButton::Yes | + PMessageBox::StandardButton::No | + PMessageBox::StandardButton::Cancel, + PMessageBox::StandardButton::Yes); - if (ret == QMessageBox::Yes) + if (ret == PMessageBox::StandardButton::Yes) { if (saveSameProject()) return true; else return false; } - else if (ret == QMessageBox::Cancel) + else if (ret == PMessageBox::StandardButton::Cancel) return false; else return true; @@ -2568,7 +2555,7 @@ void Petrack::importTracker(QString dest) //default = "" if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { // errorstring ist je nach Betriebssystem in einer anderen Sprache!!!! - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot open %1:\n%2").arg(dest).arg(file.errorString())); + PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2").arg(dest).arg(file.errorString())); return; } @@ -2643,7 +2630,7 @@ void Petrack::importTracker(QString dest) //default = "" }else if (dest.right(4) == ".txt") // 3D Koordinaten als Tracking-Daten importieren Zeilenformat: Personennr, Framenr, x, y, z { - QMessageBox::warning(this,tr("PeTrack"), tr("Are you sure you want to import 3D data from TXT-File? You have to make sure that the coordinate system now is exactly at the same position and orientation than at export time!")); + PWarning(this,tr("PeTrack"), tr("Are you sure you want to import 3D data from TXT-File? You have to make sure that the coordinate system now is exactly at the same position and orientation than at export time!")); QFile file(dest); // size of person list @@ -2652,7 +2639,7 @@ void Petrack::importTracker(QString dest) //default = "" if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { // errorstring ist je nach Betriebssystem in einer anderen Sprache!!!! - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot open %1:\n%2").arg(dest).arg(file.errorString())); + PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2").arg(dest).arg(file.errorString())); return; } @@ -2702,7 +2689,7 @@ void Petrack::importTracker(QString dest) //default = "" { conversionFactorTo_cm = 100.0; exec_once_flag = true; - QMessageBox::warning(this,tr("PeTrack"), tr("PeTrack will interpret position data as unit [m]. No header with [cm] found.")); + PWarning(this,tr("PeTrack"), tr("PeTrack will interpret position data as unit [m]. No header with [cm] found.")); } QTextStream stream(&line); @@ -2774,7 +2761,7 @@ void Petrack::importTracker(QString dest) //default = "" } else { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot load %1 maybe because of wrong file extension.").arg(dest)); + PCritical(this, tr("PeTrack"), tr("Cannot load %1 maybe because of wrong file extension.").arg(dest)); } lastFile = dest; } @@ -3079,7 +3066,7 @@ void Petrack::exportTracker(QString dest) //default = "" if (!file.open()/*!file.open(QIODevice::WriteOnly | QIODevice::Text)*/) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString())); + PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString())); return; } QProgressDialog progress("Export TRC-File",NULL,0,mTracker->size()+1,this->window()); @@ -3127,10 +3114,9 @@ void Petrack::exportTracker(QString dest) //default = "" QFile::remove(dest); if( !file.copy(dest) ) - QMessageBox::critical(this, tr("PeTrack"), - tr("Could not export tracking data.\n" - "Please try again!"), - QMessageBox::Ok); + PCritical(this, tr("PeTrack"), + tr("Could not export tracking data.\n" + "Please try again!")); else statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000); @@ -3167,7 +3153,7 @@ void Petrack::exportTracker(QString dest) //default = "" if (!file.open()) //!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString())); + PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString())); return; } @@ -3254,10 +3240,9 @@ void Petrack::exportTracker(QString dest) //default = "" QFile::remove(dest); if( !file.copy(dest) ) - QMessageBox::critical(this, tr("PeTrack"), + PCritical(this, tr("PeTrack"), tr("Could not export tracking data.\n" - "Please try again!"), - QMessageBox::Ok); + "Please try again!")); else statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000); @@ -3297,7 +3282,7 @@ void Petrack::exportTracker(QString dest) //default = "" if (!fileDat.open()) //!fileDat.open(QIODevice::WriteOnly | QIODevice::Text)) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(fileDat.errorString())); + PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(fileDat.errorString())); return; } // recalcHeight true, wenn personenhoehe ueber trackpoints neu berechnet werden soll (z.b. um waehrend play mehrfachberuecksichtigung von punkten auszuschliessen, aenderungen in altitude neu in berechnung einfliessen zu lassen) @@ -3323,10 +3308,9 @@ void Petrack::exportTracker(QString dest) //default = "" QFile::remove(dest); if( !fileDat.copy(dest) ) - QMessageBox::critical(this, tr("PeTrack"), + PCritical(this, tr("PeTrack"), tr("Could not export tracking data.\n" - "Please try again!"), - QMessageBox::Ok); + "Please try again!")); else statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000); @@ -3393,7 +3377,7 @@ void Petrack::exportTracker(QString dest) //default = "" QTemporaryFile fileXml; if (!fileXml.open()) //!fileXml.open(QIODevice::WriteOnly | QIODevice::Text)) { - QMessageBox::critical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(fileXml.errorString())); + PCritical(this, tr("PeTrack"), tr("Cannot open %1:\n%2.").arg(dest).arg(fileXml.errorString())); return; } debout << "export tracking data to " << dest << " (" << mTracker->size() << " person(s))..." << std::endl; @@ -3421,10 +3405,9 @@ void Petrack::exportTracker(QString dest) //default = "" QFile::remove(dest); if( !fileXml.copy(dest) ) - QMessageBox::critical(this, tr("PeTrack"), - tr("Could not export tracking data.\n" - "Please try again!"), - QMessageBox::Ok); + PCritical(this, tr("PeTrack"), + tr("Could not export tracking data.\n" + "Please try again!")); else statusBar()->showMessage(tr("Saved tracking data to %1.").arg(dest), 5000); diff --git a/src/player.cpp b/src/player.cpp index 8206b2918e75a4fa586a26e8ae2a391987d24ec6..751fdbb746077da87d8086fc921dfd3ac94dccf1 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -32,6 +32,7 @@ #include "animation.h" #include "petrack.h" #include "control.h" +#include "pMessageBox.h" //#define TIME_MEASUREMENT @@ -416,7 +417,7 @@ void Player::playVideo(){ }else{ if( mLooping && mMainWindow->getControlWidget()->trackOnlineCalc->checkState() == Qt::Checked) { - QMessageBox::warning(this, "Error: No tracking while looping", "Looping and tracking are incompatible. Please disable one first."); + PWarning(this, "Error: No tracking while looping", "Looping and tracking are incompatible. Please disable one first."); mState = PlayerState::PAUSE; break; }else if(mLooping) @@ -524,9 +525,8 @@ void Player::recStream() if (!QFile(videoTmp).copy(dest)) { - QMessageBox::critical(this, tr("PeTrack"), - tr("Error: Could not save video file!"), - QMessageBox::Ok); + PCritical(this, tr("PeTrack"), + tr("Error: Could not save video file!")); }else { mMainWindow->statusBar()->showMessage(tr("Saved video file to %1.").arg(dest), 5000); diff --git a/src/stereoContext.cpp b/src/stereoContext.cpp index d76e642178dfcd1b5a72fd5a1ff41f7b95103f39..9d7604639b945310dc96b24162e102f12c2a81b1 100644 --- a/src/stereoContext.cpp +++ b/src/stereoContext.cpp @@ -1018,7 +1018,7 @@ IplImage *pet::StereoContext::getDisparity(bool *dispNew) QFile file(fn); if (!file.open(QIODevice::ReadOnly)) { - QMessageBox::information(NULL,"show","Failed to read"); + PInformation(NULL,"show","Failed to read"); } QByteArray buffer = file.readAll(); //reinterpret_cast<double *> mDisparity.height*mDisparity.width*8 //debout << "Number of bytes in height field from virtual scene: " << buffer.size() <<endl; @@ -1294,7 +1294,7 @@ CvMat* pet::StereoContext::getPointCloud() QFile file(fn); if (!file.open(QIODevice::ReadOnly)) { - QMessageBox::information(NULL,"show","Failed to read"); + PInformation(NULL,"show","Failed to read"); } QByteArray buffer = file.readAll(); //reinterpret_cast<double *> mDisparity.height*mDisparity.width*8 //debout << "Number of bytes in height field from virtual scene: " << buffer.size() <<endl; @@ -1417,7 +1417,7 @@ bool pet::StereoContext::exportPointCloud(QString dest) //default = "" if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - QMessageBox::critical(mMain, QObject::tr("Petrack"), QObject::tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString())); + PCritical(mMain, QObject::tr("Petrack"), QObject::tr("Cannot open %1:\n%2.").arg(dest).arg(file.errorString())); return false; } @@ -1487,7 +1487,7 @@ bool pet::StereoContext::exportPointCloud(QString dest) //default = "" } else { - QMessageBox::critical(mMain, QObject::tr("Petrack"), QObject::tr("Cannot save %1 maybe because of wrong file extension.").arg(dest)); + PCritical(mMain, QObject::tr("Petrack"), QObject::tr("Cannot save %1 maybe because of wrong file extension.").arg(dest)); return false; } lastFile = dest; @@ -1496,7 +1496,7 @@ bool pet::StereoContext::exportPointCloud(QString dest) //default = "" } else { - QMessageBox::critical(mMain, QObject::tr("Petrack"), QObject::tr("Cannot export point cloud, because disparity has not been generated.")); + PCritical(mMain, QObject::tr("Petrack"), QObject::tr("Cannot export point cloud, because disparity has not been generated.")); return false; } } diff --git a/src/tracker.cpp b/src/tracker.cpp index 704c6738f5386c0747cf0d886a3093196b4c082b..504b07ebfbdb632aa6fd1e080743d87ff7316ea1 100644 --- a/src/tracker.cpp +++ b/src/tracker.cpp @@ -30,6 +30,7 @@ #include "control.h" #include "stereoWidget.h" #include "multiColorMarkerWidget.h" +#include "pMessageBox.h" using namespace::cv; using namespace std; @@ -964,10 +965,10 @@ bool Tracker::editTrackPersonComment(const Vec2F& p, int frame, const QSet<int>& if (ok) { if (comment.isEmpty()) { - int ret = QMessageBox::warning(mMainWindow, QObject::tr("Empty comment"), + int ret = PWarning(mMainWindow, QObject::tr("Empty comment"), QObject::tr("Are you sure you want to save an empty comment?"), - QMessageBox::Save | QMessageBox::Cancel); - if (ret == QMessageBox::Cancel) { + PMessageBox::StandardButton::Save | PMessageBox::StandardButton::Cancel); + if (ret == PMessageBox::StandardButton::Cancel) { return false; } }