diff --git a/CMakeLists.txt b/CMakeLists.txt index 18a266820cd31d01e725f9959cd9aa8182bea181..93d7c13b79116e4cf138c388462c7b0b0634e30b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -390,6 +390,7 @@ target_sources(petrack_core PRIVATE include/filterBeforeBox.h include/intrinsicBox.h include/intrinsicCameraParams.h + include/logwindow.h include/extrinsicBox.h include/extrinsicParameters.h include/autosaveSettings.h @@ -459,6 +460,7 @@ target_sources(petrack_core PRIVATE src/intrinsicBox.cpp src/filterBeforeBox.cpp src/intrinsicCameraParams.cpp + src/logwindow.cpp src/extrinsicBox.cpp src/autosaveSettings.cpp ui/about.ui @@ -473,6 +475,7 @@ target_sources(petrack_core PRIVATE ui/filterBeforeBox.ui ui/intrinsicBox.ui ui/extrinsicBox.ui + ui/logwindow.ui ui/autosaveSettings.ui ) diff --git a/include/helper.h b/include/helper.h index 3ac5533ab5dcc33ffd199085180bc0cf0c29048d..6517e4f7e8d5215f9d36e86c654ee4978388ca59 100644 --- a/include/helper.h +++ b/include/helper.h @@ -277,7 +277,6 @@ inline clock_t getElapsedTime() } bool newerThanVersion(const QString &q1, const QString &q2); - /** * Computes the median of the values in a given vector. * @tparam T any sortable type diff --git a/include/logger.h b/include/logger.h index 5b7d96fc541cfde59c5952d0cffc94b77711fee4..372e95e02a9541ecdf053e5c561f89208d7ef9be 100644 --- a/include/logger.h +++ b/include/logger.h @@ -23,21 +23,27 @@ #include <QString> #include <spdlog/fmt/bundled/format.h> #include <spdlog/fmt/ostr.h> +#include <spdlog/sinks/ringbuffer_sink.h> #include <spdlog/sinks/stdout_sinks.h> #include <spdlog/spdlog.h> namespace logger { +// Note: when changing this, also adapt messageBoxLogFormat accordingly! +const std::string logFormat = "[%s:%#:%!][%l] %v"; const std::string messageBoxLoggerName = "pMessageBox"; const std::string messageBoxLogFormat = "[{}:{}:{}][{}] {}"; inline void setupLogger() { + // add ringbuffer_sink to default logger to store messages for logwindow + auto ringbufferSink = std::make_shared<spdlog::sinks::ringbuffer_sink_mt>(10); + spdlog::default_logger()->sinks().push_back(ringbufferSink); + // setup global logger, which should be used to display message on the command line only spdlog::set_level(spdlog::level::trace); - // Note: when changing this, also adapt messageBoxLogFormat accordingly! - spdlog::set_pattern("[%s:%#:%!][%l] %v"); + spdlog::set_pattern(logFormat); // setup logger, which is used when also a dialog is displayed to the user auto messageBoxLogger = spdlog::stdout_logger_mt("pMessageBox"); diff --git a/include/logwindow.h b/include/logwindow.h new file mode 100644 index 0000000000000000000000000000000000000000..c08e0038f1c9c2c46cd663dd925b543569c20b24 --- /dev/null +++ b/include/logwindow.h @@ -0,0 +1,56 @@ +/* + * PeTrack - Software for tracking pedestrians movement in videos + * Copyright (C) 2023 Forschungszentrum JĂĽlich GmbH, IAS-7 + * + * This program 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. + * + * This program 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 this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef LOGWINDOW_H +#define LOGWINDOW_H + +#include "spdlog//spdlog.h" +#include "spdlog/logger.h" +#include "spdlog/sinks/dist_sink.h" +#include "spdlog/sinks/qt_sinks.h" + +#include <QWidget> +#include <petrack.h> + +namespace Ui +{ +class LogWindow; +} + +class LogWindow : public QWidget +{ + Q_OBJECT + +public: + void saveLog(); + + explicit LogWindow(QWidget *parent, Ui::LogWindow *mUi); + virtual ~LogWindow(); + LogWindow(const LogWindow &) = delete; + LogWindow &operator=(LogWindow) = delete; + LogWindow(const LogWindow &&) = delete; + LogWindow &operator=(LogWindow &&) = delete; + +private: + Ui::LogWindow *mUi; + Petrack *mMainWindow; + std::shared_ptr<spdlog::sinks::dist_sink<std::mutex>> distSink; + std::shared_ptr<spdlog::sinks::qt_sink<std::mutex>> qtSink; +}; + +#endif // LOGWINDOW_H diff --git a/include/petrack.h b/include/petrack.h index 320dd28a468656d668db6f1868ece39833c12556..d79ee141ab08a1a75ae5ff38ae4b9efee5a39410 100644 --- a/include/petrack.h +++ b/include/petrack.h @@ -38,6 +38,7 @@ #include "calibFilter.h" #include "coordItem.h" #include "extrCalibration.h" +#include "logwindow.h" #include "manualTrackpointMover.h" #include "moCapController.h" #include "moCapPerson.h" @@ -86,6 +87,7 @@ class ColorMarkerWidget; class CodeMarkerWidget; class MultiColorMarkerWidget; class ViewWidget; +class LogWindow; class Player; class TrackerItem; class StereoItem; @@ -126,6 +128,7 @@ private slots: void fitInROI(); void commandLineOptions(); void keyBindings(); + void showLogWindow(); void about(); void onlineHelp(); void setCamera(); @@ -221,6 +224,7 @@ public: inline ColorMarkerWidget *getColorMarkerWidget() { return mColorMarkerWidget; } inline CodeMarkerWidget *getCodeMarkerWidget() { return mCodeMarkerWidget; } inline MultiColorMarkerWidget *getMultiColorMarkerWidget() { return mMultiColorMarkerWidget; } + inline LogWindow *getLogWindow() { return mLogWindow; } inline GraphicsView *getView() { return mView; } inline QGraphicsScene *getScene() { return mScene; } inline QImage *getImage() { return mImage; } @@ -377,6 +381,7 @@ private: ColorMarkerWidget *mColorMarkerWidget; CodeMarkerWidget *mCodeMarkerWidget; MultiColorMarkerWidget *mMultiColorMarkerWidget; + LogWindow *mLogWindow; QAction *mOpenSeqAct; QAction *mOpenCameraAct; @@ -420,6 +425,7 @@ private: QAction *mDelPartRoiAct; QAction *mCommandAct; QAction *mKeyAct; + QAction *mShowLogWindowAct; QAction *mAboutAct; QAction *mOnlineHelpAct; QAction *mAutosaveSettings; diff --git a/src/logwindow.cpp b/src/logwindow.cpp new file mode 100644 index 0000000000000000000000000000000000000000..314880f746da59fd8d47efd4beecfb7a9287e7b8 --- /dev/null +++ b/src/logwindow.cpp @@ -0,0 +1,72 @@ +/* + * PeTrack - Software for tracking pedestrians movement in videos + * Copyright (C) 2023 Forschungszentrum JĂĽlich GmbH, IAS-7 + * + * This program 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. + * + * This program 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 this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include "logwindow.h" + +#include "logger.h" +#include "spdlog/sinks/dist_sink.h" +#include "spdlog/sinks/ringbuffer_sink.h" +#include "ui_logwindow.h" + +LogWindow::LogWindow(QWidget *parent, Ui::LogWindow *ui) : QWidget(parent) +{ + mMainWindow = (class Petrack *) parent; + if(!ui) + { + mUi = new Ui::LogWindow(); + } + else + { + mUi = ui; + } + + mUi->setupUi(this); + mUi->logText->setReadOnly(true); + + // extract messages from the ringbuffer_sink + auto ringbufferSink = static_cast<spdlog::sinks::ringbuffer_sink_mt *>(spdlog::default_logger()->sinks()[1].get()); + std::vector<std::string> logMessages = ringbufferSink->last_formatted(10); + for(std::string s : logMessages) + { + s.erase(std::remove(s.begin(), s.end(), '\n'), s.cend()); + mUi->logText->appendPlainText(QString::fromStdString(s)); + } + + distSink = std::make_shared<spdlog::sinks::dist_sink_mt>(); + qtSink = std::make_shared<spdlog::sinks::qt_sink_mt>(mUi->logText, "appendPlainText"); + distSink->add_sink(qtSink); + spdlog::default_logger()->sinks().push_back(distSink); + spdlog::default_logger()->set_pattern(logger::logFormat); + connect(mUi->saveLogButton, &QPushButton::clicked, this, &LogWindow::saveLog); +} +void LogWindow::saveLog() +{ + QString fileName = + QFileDialog::getSaveFileName(this, tr("Select txt file"), "", tr("txt file (*.txt);;All files (*.*)")); + + QFile logFile(fileName); + logFile.open(QIODevice::Append | QIODevice::Text); + QTextStream outstream(&logFile); + outstream << mUi->logText->toPlainText() << Qt::endl; + logFile.close(); +} +LogWindow::~LogWindow() +{ + delete mUi; + distSink->remove_sink(qtSink); +} diff --git a/src/petrack.cpp b/src/petrack.cpp index 656caacdcf71f433f3fbe1d70f13e3c8007cbeb6..a2fd45613ae94ad37192fd6511fd4eef35228497 100644 --- a/src/petrack.cpp +++ b/src/petrack.cpp @@ -188,6 +188,10 @@ Petrack::Petrack(QString petrackVersion) : connect(mView, &GraphicsView::mouseAltReleased, this, &Petrack::releaseTrackPoint); connect(mView, &GraphicsView::mouseCtrlWheel, this, &Petrack::scrollShowOnly); + mLogWindow = new LogWindow(this, nullptr); + mLogWindow->setWindowFlags(Qt::Window); + mLogWindow->setWindowTitle("Log"); + mPlayerWidget = new Player(mAnimation, this); QVBoxLayout *vLayout = new QVBoxLayout; @@ -1745,6 +1749,10 @@ void Petrack::showHideControlWidget() // show | hide Control mViewWidget->hideControls(mHideControlsAct->isChecked()); } +void Petrack::showLogWindow() +{ + mLogWindow->show(); +} void Petrack::setCamera() { @@ -1869,6 +1877,9 @@ void Petrack::createActions() connect(mHideControlsAct, SIGNAL(triggered()), this, SLOT(showHideControlWidget())); connect(mHideControlsAct, SIGNAL(changed()), this, SLOT(showHideControlWidget())); + mShowLogWindowAct = new QAction(tr("&Show log window"), this); + connect(mShowLogWindowAct, &QAction::triggered, this, &Petrack::showLogWindow); + mCropZoomViewAct = new QAction(tr("&Transform while saving"), this); // Crop and zoom while saving mCropZoomViewAct->setCheckable(true); @@ -2028,6 +2039,8 @@ void Petrack::createMenus() mViewMenu->addAction(mFontAct); mViewMenu->addSeparator(); mViewMenu->addAction(mHideControlsAct); + mViewMenu->addSeparator(); + mViewMenu->addAction(mShowLogWindowAct); mDeleteMenu = new QMenu(tr("&Delete"), this); mDeleteMenu->addAction(mDelPastAct); diff --git a/ui/control.ui b/ui/control.ui index d484430ee106a94811bb047c574a112828e8422c..b51c06a482e04725feab2176d0ceafa0a2f4f66c 100644 --- a/ui/control.ui +++ b/ui/control.ui @@ -2239,6 +2239,7 @@ <widget class="QLabel" name="recoNumberNow"> <property name="font"> <font> + <weight>75</weight> <bold>true</bold> </font> </property> @@ -3586,6 +3587,7 @@ <widget class="QLabel" name="trackNumberNow"> <property name="font"> <font> + <weight>75</weight> <bold>true</bold> </font> </property> @@ -3626,6 +3628,7 @@ <widget class="QLabel" name="trackNumberVisible"> <property name="font"> <font> + <weight>75</weight> <bold>true</bold> </font> </property> @@ -3641,6 +3644,7 @@ <widget class="QLabel" name="trackNumberAll"> <property name="font"> <font> + <weight>75</weight> <bold>true</bold> </font> </property> diff --git a/ui/logwindow.ui b/ui/logwindow.ui new file mode 100644 index 0000000000000000000000000000000000000000..59f1c17f87bc550dc8dfc8ba92fe83aa4bad864c --- /dev/null +++ b/ui/logwindow.ui @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>LogWindow</class> + <widget class="QWidget" name="LogWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>600</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPlainTextEdit" name="logText"/> + </item> + </layout> + </item> + <item> + <widget class="QPushButton" name="saveLogButton"> + <property name="toolTip"> + <string>Save Log from Window to file</string> + </property> + <property name="text"> + <string>Save Log</string> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui>