-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
241 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
|
||
#include <core/function_wrappers.hpp> | ||
#include <core/iexif_reader.hpp> | ||
#include <core/ilogger_factory.hpp> | ||
#include <core/itask_executor.hpp> | ||
#include <core/task_executor_utils.hpp> | ||
#include <database/database_tools/implementation/series_detector.hpp> | ||
#include <QElapsedTimer> | ||
#include <QPromise> | ||
|
||
#include "gui/desktop/utils/groups_manager.hpp" | ||
#include "series_model.hpp" | ||
|
||
|
||
using namespace std::placeholders; | ||
|
||
|
||
SeriesModel::SeriesModel(Project& project, ICoreFactoryAccessor& core) | ||
: m_logger(core.getLoggerFactory().get("SeriesModel")) | ||
, m_project(project) | ||
, m_core(core) | ||
, m_initialized(false) | ||
, m_loaded(false) | ||
{ | ||
|
||
} | ||
|
||
|
||
SeriesModel::~SeriesModel() | ||
{ | ||
m_candidatesFuture.cancel(); | ||
m_candidatesFuture.waitForFinished(); | ||
} | ||
|
||
|
||
bool SeriesModel::isLoaded() const | ||
{ | ||
return m_loaded; | ||
} | ||
|
||
|
||
void SeriesModel::groupBut(const QSet<int>& excludedRows) | ||
{ | ||
std::vector<GroupCandidate> toStore; | ||
|
||
for(int i = 0; i < m_candidates.size(); i++) | ||
{ | ||
if (excludedRows.contains(i)) | ||
continue; | ||
|
||
const auto& candidate = m_candidates[i]; | ||
toStore.push_back(candidate); | ||
} | ||
|
||
auto& executor = m_core.getTaskExecutor(); | ||
|
||
for (const auto& group: toStore) | ||
{ | ||
runOn(executor, [group, &project = m_project, &exifFactor = m_core.getExifReaderFactory()]() mutable | ||
{ | ||
//GroupsManager::groupIntoCollage(project.getDatabase(), exifFactor, project, group.members); | ||
}, | ||
"colage group generation"); | ||
} | ||
} | ||
|
||
|
||
QVariant SeriesModel::data(const QModelIndex& index, int role) const | ||
{ | ||
if (index.isValid() && index.column() == 0 && index.row() < m_candidates.size()) | ||
{ | ||
const auto& candidate = m_candidates[index.row()]; | ||
|
||
if (role == PhotoDataRole) | ||
return QVariant::fromValue(candidate.members.front()); | ||
else if (role == DetailsRole) | ||
return QVariant::fromValue(candidate); | ||
else if (role == GroupTypeRole) | ||
{ | ||
QString type; | ||
switch (candidate.type) | ||
{ | ||
case Group::Type::Invalid: break; | ||
case Group::Type::Animation: type = tr("Photo series"); break; | ||
case Group::Type::HDR: type = tr("HDR"); break; | ||
case Group::Type::Generic: type = tr("Photos taken at similar time"); break; | ||
} | ||
|
||
return type; | ||
} | ||
else if (role == MembersRole) | ||
return QVariant::fromValue(candidate.members); | ||
} | ||
|
||
return {}; | ||
} | ||
|
||
|
||
int SeriesModel::rowCount(const QModelIndex& parent) const | ||
{ | ||
return m_candidates.size(); | ||
} | ||
|
||
|
||
bool SeriesModel::canFetchMore(const QModelIndex& parent) const | ||
{ | ||
return parent.isValid() == false && m_initialized == false; | ||
} | ||
|
||
void SeriesModel::fetchMore(const QModelIndex& parent) | ||
{ | ||
if (parent.isValid() == false) | ||
{ | ||
m_initialized = true; | ||
|
||
fetchGroups(); | ||
} | ||
} | ||
|
||
|
||
QHash<int, QByteArray> SeriesModel::roleNames() const | ||
{ | ||
auto roles = QAbstractListModel::roleNames(); | ||
|
||
roles.insert( | ||
{ | ||
{ DetailsRole, "details" }, | ||
{ PhotoDataRole, "photoData" }, | ||
{ GroupTypeRole, "groupType" }, | ||
{ MembersRole, "members" } | ||
}); | ||
|
||
return roles; | ||
} | ||
|
||
|
||
void SeriesModel::fetchGroups() | ||
{ | ||
auto& executor = m_core.getTaskExecutor(); | ||
|
||
m_candidatesFuture = runOn<std::vector<GroupCandidate>> | ||
( | ||
executor, | ||
[this](QPromise<std::vector<GroupCandidate>>& promise) | ||
{ | ||
IExifReaderFactory& exif = m_core.getExifReaderFactory(); | ||
|
||
QElapsedTimer timer; | ||
|
||
SeriesDetector detector(*m_project.getDatabase(), exif.get(), &promise); | ||
|
||
timer.start(); | ||
promise.addResult(detector.listCandidates()); | ||
m_logger->debug(QString("Photos analysis took %1s").arg(timer.elapsed()/1000.0)); | ||
}, | ||
"SeriesDetector" | ||
); | ||
|
||
m_candidatesFuture.then(std::bind(&SeriesModel::updateModel, this, _1)); | ||
} | ||
|
||
|
||
void SeriesModel::updateModel(const std::vector<GroupCandidate>& canditates) | ||
{ | ||
beginInsertRows({}, 0, canditates.size() - 1); | ||
m_candidates = canditates; | ||
endInsertRows(); | ||
|
||
m_loaded = true; | ||
emit loadedChanged(m_loaded); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
|
||
#ifndef SERIESMODEL_HPP | ||
#define SERIESMODEL_HPP | ||
|
||
#include <QAbstractItemModel> | ||
#include <QFuture> | ||
|
||
#include <core/icore_factory_accessor.hpp> | ||
#include <database/idatabase.hpp> | ||
#include <database/database_tools/series_candidate.hpp> | ||
#include <project_utils/project.hpp> | ||
|
||
class SeriesDetector; | ||
|
||
class SeriesModel: public QAbstractListModel | ||
{ | ||
Q_OBJECT | ||
Q_PROPERTY(bool loaded READ isLoaded NOTIFY loadedChanged) | ||
|
||
public: | ||
enum Roles | ||
{ | ||
DetailsRole = Qt::UserRole + 1, | ||
PhotoDataRole, | ||
GroupTypeRole, | ||
MembersRole, | ||
}; | ||
|
||
SeriesModel(Project &, ICoreFactoryAccessor &); | ||
~SeriesModel(); | ||
|
||
bool isLoaded() const; | ||
Q_INVOKABLE void groupBut(const QSet<int> &); | ||
|
||
QVariant data(const QModelIndex& index, int role) const override; | ||
int rowCount(const QModelIndex& parent) const override; | ||
bool canFetchMore(const QModelIndex& parent) const override; | ||
void fetchMore(const QModelIndex& parent) override; | ||
QHash<int, QByteArray> roleNames() const override; | ||
|
||
signals: | ||
void loadedChanged(bool) const; | ||
|
||
private: | ||
std::unique_ptr<ILogger> m_logger; | ||
std::vector<GroupCandidate> m_candidates; | ||
Project& m_project; | ||
ICoreFactoryAccessor& m_core; | ||
QFuture<std::vector<GroupCandidate>> m_candidatesFuture; | ||
bool m_initialized; | ||
bool m_loaded; | ||
|
||
void fetchGroups(); | ||
void updateModel(const std::vector<GroupCandidate> &); | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters