Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ped-dyn-emp/petrack
1 result
Show changes
Commits on Source (26)
...@@ -376,6 +376,7 @@ target_sources(petrack_core PRIVATE ...@@ -376,6 +376,7 @@ target_sources(petrack_core PRIVATE
include/pMessageBox.h include/pMessageBox.h
include/moCapSelectionWidget.h include/moCapSelectionWidget.h
include/personStorage.h include/personStorage.h
include/autosave.h
) )
target_sources(petrack_core PRIVATE target_sources(petrack_core PRIVATE
...@@ -435,6 +436,7 @@ target_sources(petrack_core PRIVATE ...@@ -435,6 +436,7 @@ target_sources(petrack_core PRIVATE
src/pMessageBox.cpp src/pMessageBox.cpp
src/moCapSelectionWidget.cpp src/moCapSelectionWidget.cpp
src/personStorage.cpp src/personStorage.cpp
src/autosave.cpp
ui/about.ui ui/about.ui
ui/codeMarker.ui ui/codeMarker.ui
ui/colorMarker.ui ui/colorMarker.ui
......
/*
* PeTrack - Software for tracking pedestrians movement in videos
* Copyright (C) 2010-2022 Forschungszentrum Jülich GmbH,
* Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
* Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
*
* 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 AUTOSAVE_H
#define AUTOSAVE_H
#include <QObject>
#include <QStringList>
#include <memory>
class Petrack;
class QTimer;
class QFileInfo;
struct AutosaveFilenames
{
QString running;
QString final;
};
class Autosave : public QObject
{
Q_OBJECT
public:
explicit Autosave(Petrack &petrack);
Autosave() = delete;
Autosave(const Autosave &other) = delete;
Autosave(const Autosave &&other) = delete;
Autosave &operator=(const Autosave &other) = delete;
Autosave &operator=(Autosave &&other) = delete;
~Autosave() override = default;
void trackPersonModified();
void resetTrackPersonCounter();
static bool autosaveExists(const QString &filename);
void deleteAutosave();
void loadAutosave();
bool isAutosave(const QString &file);
private:
static QString buildAutosaveName(const QString &projectFileName, const QString &ending);
static AutosaveFilenames autosaveNamesTrc(const QString &projectFileName);
static AutosaveFilenames autosaveNamesPet(const QString &projectFileName);
void saveTrc();
QStringList getAutosave();
static QStringList getAutosave(const QFileInfo &projectPath);
private slots:
void savePet();
private:
static constexpr int petSaveInterval = 120 * 1000; // in ms -> 120s
static constexpr int changesTillAutosave = 10;
void startTimer();
void stopTimer();
Petrack &mPetrack;
QTimer *mTimer;
int mChangeCounter = 0;
};
#endif // AUTOSAVE_H
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <vector> #include <vector>
class Petrack; class Petrack;
class Autosave;
struct PersonFrame struct PersonFrame
{ {
...@@ -43,7 +44,7 @@ public: ...@@ -43,7 +44,7 @@ public:
Whole Whole
}; };
explicit PersonStorage(Petrack &mainWindow) : mMainWindow(mainWindow) {} explicit PersonStorage(Petrack &mainWindow, Autosave &autosave) : mMainWindow(mainWindow), mAutosave(autosave) {}
void splitPerson(size_t pers, int frame); void splitPerson(size_t pers, int frame);
bool splitPersonAt(const Vec2F &p, int frame, const QSet<int> &onlyVisible); bool splitPersonAt(const Vec2F &p, int frame, const QSet<int> &onlyVisible);
...@@ -120,7 +121,7 @@ public: ...@@ -120,7 +121,7 @@ public:
// rueckgabewert false wenn keine hoeheninformationen in tracker datensatz vorliegt // rueckgabewert false wenn keine hoeheninformationen in tracker datensatz vorliegt
bool printHeightDistribution(); bool printHeightDistribution();
void setMarkerHeights(const std::unordered_map<int, float> &heights); void setMarkerHeights(const std::unordered_map<int, float> &heights);
void setMarkerID(int person, int markerIDs); void setMarkerID(int person, int markerIDs, bool manual = false);
void setMarkerIDs(const std::unordered_map<int, int> &markerIDs); void setMarkerIDs(const std::unordered_map<int, int> &markerIDs);
void purge(int frame); void purge(int frame);
...@@ -129,6 +130,7 @@ public: ...@@ -129,6 +130,7 @@ public:
private: private:
std::vector<TrackPerson> mPersons; std::vector<TrackPerson> mPersons;
Petrack &mMainWindow; Petrack &mMainWindow;
Autosave &mAutosave;
}; };
#endif // PERSONSTORAGE_H #endif // PERSONSTORAGE_H
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "stereoContext.h" #include "stereoContext.h"
#endif #endif
#include "autoCalib.h" #include "autoCalib.h"
#include "autosave.h"
#include "backgroundFilter.h" #include "backgroundFilter.h"
#include "borderFilter.h" #include "borderFilter.h"
#include "brightContrastFilter.h" #include "brightContrastFilter.h"
...@@ -201,14 +202,7 @@ public: ...@@ -201,14 +202,7 @@ public:
inline pet::StereoContext *getStereoContext() { return mStereoContext; } inline pet::StereoContext *getStereoContext() { return mStereoContext; }
inline QString getProFileName() { return mProFileName; } inline QString getProFileName() { return mProFileName; }
private: void setProFileName(const QString &fileName);
inline void setProFileName(const QString &fileName)
{
// NOTE: Use only the global variant in future?
// global one in helper.h because it is needed to use getFileList and shouldn't depend on Petrack
proFileName = fileName;
mProFileName = fileName;
}
public: public:
inline QString getTrackFileName() { return mTrcFileName; } inline QString getTrackFileName() { return mTrcFileName; }
...@@ -464,14 +458,15 @@ private: ...@@ -464,14 +458,15 @@ private:
reco::Recognizer mReco; reco::Recognizer mReco;
PersonStorage mPersonStorage{*this}; QDomDocument mDefaultSettings;
Autosave mAutosave{*this};
PersonStorage mPersonStorage{*this, mAutosave};
Tracker *mTracker; Tracker *mTracker;
TrackerReal *mTrackerReal; TrackerReal *mTrackerReal;
double mHeadSize; double mHeadSize;
double mCmPerPixel; double mCmPerPixel;
QDomDocument mDefaultSettings;
double mShowFPS; double mShowFPS;
bool mAutoBackTrack; bool mAutoBackTrack;
...@@ -481,7 +476,6 @@ private: ...@@ -481,7 +476,6 @@ private:
MoCapStorage mStorage; MoCapStorage mStorage;
MoCapController mMoCapController{mStorage, mExtrCalibration}; MoCapController mMoCapController{mStorage, mExtrCalibration};
QString mPetrackVersion{"Unknown"}; ///< Version of PeTrack used to compile QString mPetrackVersion{"Unknown"}; ///< Version of PeTrack used to compile
QString mGitCommitID{"Unknown"}; ///< Commit hash used to compile QString mGitCommitID{"Unknown"}; ///< Commit hash used to compile
QString mGitCommitDate{"Unknown"}; ///< Commit date used to compile QString mGitCommitDate{"Unknown"}; ///< Commit date used to compile
......
/*
* PeTrack - Software for tracking pedestrians movement in videos
* Copyright (C) 2010-2022 Forschungszentrum Jülich GmbH,
* Maik Boltes, Juliane Adrian, Ricardo Martin Brualla, Arne Graf, Paul Häger, Daniel Hillebrand,
* Deniz Kilic, Paul Lieberenz, Daniel Salden, Tobias Schrödter, Ann Katrin Seemann
*
* 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 "autosave.h"
#include "petrack.h"
#include <QTimer>
Autosave::Autosave(Petrack &petrack) : mPetrack(petrack)
{
mTimer = new QTimer{this};
connect(mTimer, &QTimer::timeout, this, &Autosave::savePet);
startTimer();
}
// Autosave::~Autosave() = default;
//{
// NOTE: Currently this would also delete on Keyboard Interrupt (Ctrl + C)
// Replaced by Method call in closeEvent in Petrack to circumvent this
// if Project-Object from Issue 88 gets implemented,
// Autosave should be a Member of the project, not Petrack
// then the destructor could maybe be used to delete the autosave
// deleteAutosave();
//}
/**
* @brief Occasioanlly triggers autosaving
*
* This method gets called everytime the user modifies a trajectory. After a certain number of modifications, an
* autosave for the .trc file is written to disk
*/
void Autosave::trackPersonModified()
{
mChangeCounter++;
if(mChangeCounter >= changesTillAutosave)
{
mChangeCounter = 0;
saveTrc();
}
}
void Autosave::resetTrackPersonCounter()
{
mChangeCounter = 0;
}
/**
* @brief Checks if autosave for project with given filename exists
* @param filename path to the project file
* @return true if autosave file exists, else false
*/
bool Autosave::autosaveExists(const QString &filename)
{
return !getAutosave(QFileInfo(filename)).empty();
}
/**
* @brief Delete all autosave files for currently loaded project (.pet and .trc)
*/
void Autosave::deleteAutosave()
{
const auto autosaves = getAutosave();
if(!autosaves.empty())
{
for(const auto &save : autosaves)
{
QFile saveFile{save};
saveFile.remove();
}
}
}
/**
* @brief Loads autosave files for currently loaded project
*/
void Autosave::loadAutosave()
{
const auto autosaveFiles = getAutosave();
if(autosaveFiles.empty())
{
return;
}
const auto petIndex = autosaveFiles.indexOf(QRegularExpression(R"(.*\.pet)"));
if(petIndex != -1)
{
const QString petAutosaveName = autosaveFiles[petIndex];
mPetrack.openProject(petAutosaveName);
}
else
{
mPetrack.openProject(mPetrack.getProFileName());
}
const auto trcIndex = autosaveFiles.indexOf(QRegularExpression(R"(.*\.trc)"));
if(trcIndex != -1)
{
const QString trcAutosaveName = autosaveFiles[trcIndex];
const auto trcFile = mPetrack.getTrackFileName();
mPetrack.deleteTrackPointAll(PersonStorage::Direction::Whole);
mPetrack.importTracker(trcAutosaveName);
mPetrack.setTrackFileName(trcFile);
}
}
/**
* @brief Returns whether a given filename would be autosave
*
* NOTE: File does not need to exist to be classified as autosave
*
* @param file file to test
* @return true when name of an autosave, else false;
*/
bool Autosave::isAutosave(const QString &file)
{
const auto &projectName = mPetrack.getProFileName();
const auto [petRunningAutosave, petAutosaveName] = [&projectName]
{
auto names = autosaveNamesPet(projectName);
names.running = QFileInfo(names.running).absoluteFilePath();
names.final = QFileInfo(names.final).absoluteFilePath();
return names;
}();
const auto [trcRunningAutosave, trcAutosaveName] = [&projectName]
{
auto names = autosaveNamesTrc(projectName);
names.running = QFileInfo(names.running).absoluteFilePath();
names.final = QFileInfo(names.final).absoluteFilePath();
return names;
}();
QFileInfo fileInfo{file};
const QString &filePath = fileInfo.absoluteFilePath();
return filePath == petAutosaveName || filePath == trcAutosaveName || filePath == petRunningAutosave ||
filePath == trcRunningAutosave;
}
/**
* @brief Starts timer for time-dependent autosave (pet-file)
*/
void Autosave::startTimer()
{
if(!mTimer->isActive())
{
mTimer->start(petSaveInterval);
}
}
/**
* @brief Stops timer for time-dependent autosave (pet-file)
*/
void Autosave::stopTimer()
{
if(mTimer->isActive())
{
mTimer->stop();
}
}
QString Autosave::buildAutosaveName(const QString &projectFileName, const QString &ending)
{
const QFileInfo projectFile{projectFileName};
return projectFile.dir().filePath("." + projectFile.baseName() + "_autosave" + ending);
}
AutosaveFilenames Autosave::autosaveNamesTrc(const QString &projectFileName)
{
return {buildAutosaveName(projectFileName, "_running.trc"), buildAutosaveName(projectFileName, ".trc")};
}
AutosaveFilenames Autosave::autosaveNamesPet(const QString &projectFileName)
{
return {buildAutosaveName(projectFileName, "_running.pet"), buildAutosaveName(projectFileName, ".pet")};
}
/**
* @brief Saves the .pet-file
*
* This method is called by the timeout signal of mTimer.
* It saves the pet-file to a hidden file with a name derived from
* the name of the currently loaded project
*/
void Autosave::savePet()
{
const auto projectName = mPetrack.getProFileName();
// only save if there is a project name; Means there needs to be an .pet file already for autosave to work. With our
// workflow usually the case
if(projectName.isEmpty() || QFileInfo(projectName).isDir())
{
return;
}
const auto &[autosaveName, finalAutosaveName] = autosaveNamesPet(projectName);
mPetrack.saveProject(autosaveName);
// first save to temp file, so crash during saving doesn't corrupt old autosave
QFile tempAutosave{autosaveName};
QFile autosave{finalAutosaveName};
if(tempAutosave.exists())
{
if(autosave.exists())
{
autosave.remove();
}
if(tempAutosave.copy(finalAutosaveName))
{
// we don't currently use it for loading, so we could remove it even if the copying fails...
tempAutosave.remove();
}
}
}
/**
* @brief Saves the .trc-file
*
* This method is called by trackPersonModified after a set number of modifications.
* It saves the trc-file to a hidden file with a name derived from
* the name of the currently loaded project
*/
void Autosave::saveTrc()
{
const auto projectName = mPetrack.getProFileName();
const auto &[autosaveName, finalAutosaveName] = autosaveNamesTrc(projectName);
const auto trackFileName = mPetrack.getTrackFileName();
const auto lastTrackerExport = mPetrack.getLastTrackerExport();
mPetrack.exportTracker(autosaveName);
mPetrack.setTrackFileName(trackFileName);
mPetrack.setLastTrackerExport(lastTrackerExport);
// first save to temp file, so crash during saving doesn't corrupt old autosave
QFile tempAutosave{autosaveName};
QFile autosave{finalAutosaveName};
if(tempAutosave.exists())
{
if(autosave.exists())
{
autosave.remove();
}
if(tempAutosave.copy(finalAutosaveName))
{
// we don't currently use it for loading, so we could remove it even if the copying fails...
tempAutosave.remove();
}
}
}
/**
* @brief Returns a list of autosave files for the current project
* @return list of autosaves; may be empty
*/
QStringList Autosave::getAutosave()
{
const auto projectPath = QFileInfo(mPetrack.getProFileName());
return Autosave::getAutosave(projectPath);
}
/**
* @brief Returns a list of autosave files for the project at projectPath
* @param projectPath filepath of .pet-file
* @return list of autosaves; may be empty
*/
QStringList Autosave::getAutosave(const QFileInfo &projectPath)
{
if(projectPath.isFile())
{
QStringList list;
const auto autosavePetName = autosaveNamesPet(projectPath.absoluteFilePath()).final;
const QFileInfo autosavePet{autosavePetName};
if(autosavePet.exists())
{
list.append(autosavePetName);
}
const auto autosaveTrcName = autosaveNamesTrc(projectPath.absoluteFilePath()).final;
const QFileInfo autosaveTrc{autosaveTrcName};
if(autosaveTrc.exists())
{
list.append(autosaveTrcName);
}
return list;
}
return QStringList{};
}
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "personStorage.h" #include "personStorage.h"
#include "animation.h" #include "animation.h"
#include "autosave.h"
#include "control.h" #include "control.h"
#include "multiColorMarkerWidget.h" #include "multiColorMarkerWidget.h"
#include "pMessageBox.h" #include "pMessageBox.h"
...@@ -34,6 +35,7 @@ ...@@ -34,6 +35,7 @@
*/ */
void PersonStorage::splitPerson(size_t pers, int frame) void PersonStorage::splitPerson(size_t pers, int frame)
{ {
mAutosave.trackPersonModified();
int j; int j;
if(mPersons.at(pers).firstFrame() < frame) if(mPersons.at(pers).firstFrame() < frame)
...@@ -66,6 +68,7 @@ void PersonStorage::splitPerson(size_t pers, int frame) ...@@ -66,6 +68,7 @@ void PersonStorage::splitPerson(size_t pers, int frame)
*/ */
bool PersonStorage::splitPersonAt(const Vec2F &point, int frame, const QSet<int> &onlyVisible) bool PersonStorage::splitPersonAt(const Vec2F &point, int frame, const QSet<int> &onlyVisible)
{ {
mAutosave.trackPersonModified();
for(size_t i = 0; i < mPersons.size(); ++i) for(size_t i = 0; i < mPersons.size(); ++i)
{ // ueber TrackPerson { // ueber TrackPerson
if(((onlyVisible.empty()) || (onlyVisible.contains(i))) && if(((onlyVisible.empty()) || (onlyVisible.contains(i))) &&
...@@ -90,6 +93,7 @@ bool PersonStorage::splitPersonAt(const Vec2F &point, int frame, const QSet<int> ...@@ -90,6 +93,7 @@ bool PersonStorage::splitPersonAt(const Vec2F &point, int frame, const QSet<int>
*/ */
bool PersonStorage::delPointOf(int pers, int direction, int frame) bool PersonStorage::delPointOf(int pers, int direction, int frame)
{ {
mAutosave.trackPersonModified();
if(direction == -1) if(direction == -1)
{ {
for(int j = 0; j < frame - mPersons.at(pers).firstFrame(); ++j) for(int j = 0; j < frame - mPersons.at(pers).firstFrame(); ++j)
...@@ -125,6 +129,7 @@ bool PersonStorage::delPointOf(int pers, int direction, int frame) ...@@ -125,6 +129,7 @@ bool PersonStorage::delPointOf(int pers, int direction, int frame)
*/ */
bool PersonStorage::delPoint(const Vec2F &point, int direction, int frame, const QSet<int> &onlyVisible) bool PersonStorage::delPoint(const Vec2F &point, int direction, int frame, const QSet<int> &onlyVisible)
{ {
mAutosave.trackPersonModified();
for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) for(int i = 0; i < static_cast<int>(mPersons.size()); ++i)
{ // ueber TrackPerson { // ueber TrackPerson
if(((onlyVisible.empty()) || (onlyVisible.contains(i))) && if(((onlyVisible.empty()) || (onlyVisible.contains(i))) &&
...@@ -146,6 +151,7 @@ bool PersonStorage::delPoint(const Vec2F &point, int direction, int frame, const ...@@ -146,6 +151,7 @@ bool PersonStorage::delPoint(const Vec2F &point, int direction, int frame, const
*/ */
void PersonStorage::delPointAll(Direction direction, int frame) void PersonStorage::delPointAll(Direction direction, int frame)
{ {
mAutosave.trackPersonModified();
for(size_t i = 0; i < mPersons.size(); ++i) // ueber TrackPerson for(size_t i = 0; i < mPersons.size(); ++i) // ueber TrackPerson
{ {
if(mPersons.at(i).trackPointExist(frame)) if(mPersons.at(i).trackPointExist(frame))
...@@ -190,6 +196,7 @@ void PersonStorage::delPointAll(Direction direction, int frame) ...@@ -190,6 +196,7 @@ void PersonStorage::delPointAll(Direction direction, int frame)
*/ */
void PersonStorage::delPointInsideROI() void PersonStorage::delPointInsideROI()
{ {
mAutosave.trackPersonModified();
QRectF rect = mMainWindow.getRecoRoiItem()->rect(); QRectF rect = mMainWindow.getRecoRoiItem()->rect();
bool inside; bool inside;
...@@ -225,6 +232,7 @@ void PersonStorage::delPointInsideROI() ...@@ -225,6 +232,7 @@ void PersonStorage::delPointInsideROI()
*/ */
void PersonStorage::delPointROI() void PersonStorage::delPointROI()
{ {
mAutosave.trackPersonModified();
int anz = 0; int anz = 0;
QRectF rect = mMainWindow.getRecoRoiItem()->rect(); QRectF rect = mMainWindow.getRecoRoiItem()->rect();
...@@ -258,6 +266,7 @@ void PersonStorage::delPointROI() ...@@ -258,6 +266,7 @@ void PersonStorage::delPointROI()
*/ */
bool PersonStorage::editTrackPersonComment(const Vec2F &point, int frame, const QSet<int> &onlyVisible) bool PersonStorage::editTrackPersonComment(const Vec2F &point, int frame, const QSet<int> &onlyVisible)
{ {
mAutosave.trackPersonModified();
for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson
{ {
if(((onlyVisible.empty()) || (onlyVisible.contains(i))) && if(((onlyVisible.empty()) || (onlyVisible.contains(i))) &&
...@@ -312,6 +321,7 @@ bool PersonStorage::editTrackPersonComment(const Vec2F &point, int frame, const ...@@ -312,6 +321,7 @@ bool PersonStorage::editTrackPersonComment(const Vec2F &point, int frame, const
*/ */
bool PersonStorage::setTrackPersonHeight(const Vec2F &point, int frame, const QSet<int> &onlyVisible) bool PersonStorage::setTrackPersonHeight(const Vec2F &point, int frame, const QSet<int> &onlyVisible)
{ {
mAutosave.trackPersonModified();
for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson
{ {
if(((onlyVisible.empty()) || (onlyVisible.contains(i))) && if(((onlyVisible.empty()) || (onlyVisible.contains(i))) &&
...@@ -379,6 +389,7 @@ bool PersonStorage::setTrackPersonHeight(const Vec2F &point, int frame, const QS ...@@ -379,6 +389,7 @@ bool PersonStorage::setTrackPersonHeight(const Vec2F &point, int frame, const QS
*/ */
bool PersonStorage::resetTrackPersonHeight(const Vec2F &point, int frame, QSet<int> onlyVisible) bool PersonStorage::resetTrackPersonHeight(const Vec2F &point, int frame, QSet<int> onlyVisible)
{ {
mAutosave.trackPersonModified();
for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) // ueber TrackPerson
{ {
if(((onlyVisible.empty()) || (onlyVisible.contains(i))) && if(((onlyVisible.empty()) || (onlyVisible.contains(i))) &&
...@@ -472,6 +483,11 @@ bool PersonStorage::addPoint( ...@@ -472,6 +483,11 @@ bool PersonStorage::addPoint(
reco::RecognitionMethod method, reco::RecognitionMethod method,
int *pers) int *pers)
{ {
if(point.qual() > 100)
{
// manually added point
mAutosave.trackPersonModified();
}
bool found = false; bool found = false;
int i, iNearest = 0.; int i, iNearest = 0.;
float scaleHead; float scaleHead;
...@@ -737,6 +753,7 @@ PersonStorage::getProximalPersons(const QPointF &pos, int frame, QSet<int> selec ...@@ -737,6 +753,7 @@ PersonStorage::getProximalPersons(const QPointF &pos, int frame, QSet<int> selec
*/ */
void PersonStorage::recalcHeight(float altitude) void PersonStorage::recalcHeight(float altitude)
{ {
mAutosave.trackPersonModified();
for(auto &person : mPersons) for(auto &person : mPersons)
{ {
person.recalcHeight(altitude); person.recalcHeight(altitude);
...@@ -949,6 +966,7 @@ void PersonStorage::checkPlausibility( ...@@ -949,6 +966,7 @@ void PersonStorage::checkPlausibility(
/// optimize color for all persons /// optimize color for all persons
void PersonStorage::optimizeColor() void PersonStorage::optimizeColor()
{ {
mAutosave.trackPersonModified();
for(auto &person : mPersons) for(auto &person : mPersons)
{ {
if(person.color().isValid()) if(person.color().isValid())
...@@ -961,6 +979,7 @@ void PersonStorage::optimizeColor() ...@@ -961,6 +979,7 @@ void PersonStorage::optimizeColor()
/// reset the height of all persons, but not the pos of the trackpoints /// reset the height of all persons, but not the pos of the trackpoints
void PersonStorage::resetHeight() void PersonStorage::resetHeight()
{ {
mAutosave.trackPersonModified();
for(auto &person : mPersons) for(auto &person : mPersons)
{ {
person.resetHeight(); person.resetHeight();
...@@ -970,6 +989,7 @@ void PersonStorage::resetHeight() ...@@ -970,6 +989,7 @@ void PersonStorage::resetHeight()
/// reset the pos of the tzrackpoints, but not the heights /// reset the pos of the tzrackpoints, but not the heights
void PersonStorage::resetPos() void PersonStorage::resetPos()
{ {
mAutosave.trackPersonModified();
for(auto &person : mPersons) for(auto &person : mPersons)
{ {
for(auto &point : person) for(auto &point : person)
...@@ -1040,6 +1060,7 @@ bool PersonStorage::printHeightDistribution() ...@@ -1040,6 +1060,7 @@ bool PersonStorage::printHeightDistribution()
*/ */
void PersonStorage::setMarkerHeights(const std::unordered_map<int, float> &heights) void PersonStorage::setMarkerHeights(const std::unordered_map<int, float> &heights)
{ {
mAutosave.trackPersonModified();
for(auto &person : mPersons) // over TrackPerson for(auto &person : mPersons) // over TrackPerson
{ {
for(auto &point : person) // over TrackPoints for(auto &point : person) // over TrackPoints
...@@ -1070,8 +1091,12 @@ void PersonStorage::setMarkerHeights(const std::unordered_map<int, float> &heigh ...@@ -1070,8 +1091,12 @@ void PersonStorage::setMarkerHeights(const std::unordered_map<int, float> &heigh
* @param personID internal id of persons (0 based) * @param personID internal id of persons (0 based)
* @param markerIDs new marker ID * @param markerIDs new marker ID
*/ */
void PersonStorage::setMarkerID(int personID, int markerID) void PersonStorage::setMarkerID(int personID, int markerID, bool manual)
{ {
if(manual)
{
mAutosave.trackPersonModified();
}
auto &person = mPersons.at(personID); auto &person = mPersons.at(personID);
person.setMarkerID(markerID); person.setMarkerID(markerID);
for(auto &trackPoint : person) // over TrackPoints for(auto &trackPoint : person) // over TrackPoints
...@@ -1086,6 +1111,7 @@ void PersonStorage::setMarkerID(int personID, int markerID) ...@@ -1086,6 +1111,7 @@ void PersonStorage::setMarkerID(int personID, int markerID)
*/ */
void PersonStorage::setMarkerIDs(const std::unordered_map<int, int> &markerIDs) void PersonStorage::setMarkerIDs(const std::unordered_map<int, int> &markerIDs)
{ {
mAutosave.trackPersonModified();
for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) // over TrackPerson for(int i = 0; i < static_cast<int>(mPersons.size()); ++i) // over TrackPerson
{ {
// personID of current person // personID of current person
...@@ -1115,6 +1141,7 @@ void PersonStorage::setMarkerIDs(const std::unordered_map<int, int> &markerIDs) ...@@ -1115,6 +1141,7 @@ void PersonStorage::setMarkerIDs(const std::unordered_map<int, int> &markerIDs)
*/ */
void PersonStorage::purge(int frame) void PersonStorage::purge(int frame)
{ {
mAutosave.trackPersonModified();
int i, j; int i, j;
float count; ///< number of trackpoints without recognition float count; ///< number of trackpoints without recognition
...@@ -1242,6 +1269,7 @@ void PersonStorage::insertFeaturePoint( ...@@ -1242,6 +1269,7 @@ void PersonStorage::insertFeaturePoint(
*/ */
int PersonStorage::merge(int pers1, int pers2) int PersonStorage::merge(int pers1, int pers2)
{ {
mAutosave.trackPersonModified();
auto &person = mPersons.at(pers1); auto &person = mPersons.at(pers1);
auto &other = mPersons.at(pers2); auto &other = mPersons.at(pers2);
const bool extrapolate = mMainWindow.getControlWidget()->trackExtrapolation->checkState() == Qt::Checked; const bool extrapolate = mMainWindow.getControlWidget()->trackExtrapolation->checkState() == Qt::Checked;
......
...@@ -605,6 +605,17 @@ void Petrack::openProject(QString fileName, bool openSeq) // default fileName="" ...@@ -605,6 +605,17 @@ void Petrack::openProject(QString fileName, bool openSeq) // default fileName=""
tr("PeTrack project file (*.pet);;All files (*.*)")); tr("PeTrack project file (*.pet);;All files (*.*)"));
} }
if(Autosave::autosaveExists(fileName) && fileName != mProFileName)
{
auto ret = PQuestion(this, "Autosave detected", "An autosave was detected.\nDo you want to load the Autosave?");
if(ret == PMessageBox::StandardButton::Yes)
{
setProFileName(fileName);
mAutosave.loadAutosave();
return;
}
}
if(!fileName.isEmpty()) if(!fileName.isEmpty())
{ {
QFile file(fileName); QFile file(fileName);
...@@ -2529,6 +2540,7 @@ void Petrack::closeEvent(QCloseEvent *event) ...@@ -2529,6 +2540,7 @@ void Petrack::closeEvent(QCloseEvent *event)
if(maybeSave()) if(maybeSave())
{ {
writeSettings(); writeSettings();
mAutosave.deleteAutosave();
event->accept(); event->accept();
} }
else else
...@@ -3045,6 +3057,7 @@ void Petrack::exportTracker(QString dest) // default = "" ...@@ -3045,6 +3057,7 @@ void Petrack::exportTracker(QString dest) // default = ""
progress.setValue(mPersonStorage.nbPersons() + 1); progress.setValue(mPersonStorage.nbPersons() + 1);
std::cout << " finished " << std::endl; std::cout << " finished " << std::endl;
mAutosave.resetTrackPersonCounter();
#ifdef TIME_MEASUREMENT #ifdef TIME_MEASUREMENT
time1 += clock() - tstart; time1 += clock() - tstart;
...@@ -3974,6 +3987,23 @@ double Petrack::getHeadSize(QPointF *pos, int pers, int frame) ...@@ -3974,6 +3987,23 @@ double Petrack::getHeadSize(QPointF *pos, int pers, int frame)
} }
} }
void Petrack::setProFileName(const QString &fileName)
{
// don't change project Name to an autosave
if(mAutosave.isAutosave(fileName) || fileName == mProFileName)
{
return;
}
// Change project => delete old autosave
mAutosave.deleteAutosave();
// NOTE: Use only the global variant in future?
// global one in helper.h because it is needed to use getFileList and shouldn't depend on Petrack
proFileName = fileName;
mProFileName = fileName;
updateWindowTitle();
}
/** /**
* @brief Return the user's selection of pedestrians/trajectories * @brief Return the user's selection of pedestrians/trajectories
* *
......
...@@ -210,7 +210,7 @@ void TrackerItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) ...@@ -210,7 +210,7 @@ void TrackerItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
if(changeID) if(changeID)
{ {
int markerID = QInputDialog::getInt(mMainWindow, "Enter Marker ID", "Marker ID:"); int markerID = QInputDialog::getInt(mMainWindow, "Enter Marker ID", "Marker ID:");
mPersonStorage.setMarkerID(i, markerID); mPersonStorage.setMarkerID(i, markerID, true);
} }
} }
else if(selectedAction == infoTrj) else if(selectedAction == infoTrj)
......
...@@ -60,7 +60,8 @@ SCENARIO("I want to get the render data with one person loaded", "[ui]") ...@@ -60,7 +60,8 @@ SCENARIO("I want to get the render data with one person loaded", "[ui]")
// default time offset 0 // default time offset 0
Petrack pet; Petrack pet;
PersonStorage st{pet}; Autosave save{pet};
PersonStorage st{pet, save};
ExtrCalibMock extrCalib{st}; ExtrCalibMock extrCalib{st};
/* /*
......