First attempt at getting rid of tracker for post capture
[harmattan/cameraplus] / src / postcapturemodel.cpp
index fc639c9..1f71a58 100644 (file)
  */
 
 #include "postcapturemodel.h"
-#include <QSparqlConnection>
-#include <QSparqlQuery>
-#include <QSparqlResult>
-#include <QSparqlError>
-#if defined(QT4)
-#include <QDeclarativeInfo>
-#elif defined(QT5)
-#include <QQmlInfo>
-#endif
+#include "fileinfomodel.h"
+#include <QDir>
 #include <QDateTime>
-#include <QDBusConnection>
-#include <QStringList>
-#include <QDBusMetaType>
-#include <QDBusArgument>
-
-#define DRIVER "QTRACKER_DIRECT"
-#define QUERY "SELECT rdf:type(?urn) AS ?type nie:url(?urn) AS ?url nie:contentCreated(?urn) AS ?created nie:title(?urn) AS ?title nfo:fileName(?urn) AS ?filename nie:mimeType(?urn) AS ?mimetype tracker:available(?urn) AS ?available nfo:fileLastModified(?urn) as ?lastmod tracker:id(?urn) AS ?trackerid (EXISTS { ?urn nao:hasTag nao:predefined-tag-favorite }) AS ?favorite WHERE { ?urn nfo:equipment ?:equipment . {?urn a nfo:Video} UNION {?urn a nfo:Image}} ORDER BY DESC(?created)"
-
-#define UPDATE_QUERY "SELECT rdf:type(?urn) AS ?type nie:url(?urn) AS ?url nie:contentCreated(?urn) AS ?created nie:title(?urn) AS ?title nfo:fileName(?urn) AS ?filename nie:mimeType(?urn) AS ?mimetype tracker:available(?urn) AS ?available nfo:fileLastModified(?urn) as ?lastmod tracker:id(?urn) AS ?trackerid (EXISTS { ?urn nao:hasTag nao:predefined-tag-favorite }) AS ?favorite WHERE {?urn a nfo:Visual . FILTER (tracker:id(?urn) IN (%1)) }"
-
-#define TRACKER_SERVICE "org.freedesktop.Tracker1"
-#define TRACKER_RESOURCE_PATH "/org/freedesktop/Tracker1/Resources"
-#define TRACKER_RESOURCE_INTERFACE "org.freedesktop.Tracker1.Resources"
-#define TRACKER_RESOURCE_SIGNAL "GraphUpdated"
-#define PHOTO_CLASS "http://www.tracker-project.org/temp/nmm#Photo"
-#define VIDEO_CLASS "http://www.tracker-project.org/temp/nmm#Video"
-#define TRACKER_RESOURCE_SIGNAL_SIGNATURE "sa(iiii)a(iiii)"
-
-class Quad {
-public:
-  int graph;
-  int subject;
-  int predicate;
-  int object;
-};
-
-Q_DECLARE_METATYPE(Quad);
-Q_DECLARE_METATYPE(QList<Quad>);
-
-QDBusArgument& operator<<(QDBusArgument& argument, const Quad& t) {
-  argument.beginStructure();
-  argument << t.graph << t.subject << t.predicate << t.object;
-  argument.endStructure();
-  return argument;
-}
+#include <QUrl>
 
-const QDBusArgument& operator>>(const QDBusArgument& argument, Quad& t) {
-  argument.beginStructure();
-  argument >> t.graph >> t.subject >> t.predicate >> t.object;
-  argument.endStructure();
-  return argument;
-}
+static QHash<QString, QString> m_mime;
 
 PostCaptureModel::PostCaptureModel(QObject *parent) :
-  QAbstractListModel(parent),
-  m_connection(0),
-  m_connected(false) {
-
-  qDBusRegisterMetaType<Quad>();
-  qDBusRegisterMetaType<QList<Quad> >();
+  QSortFilterProxyModel(parent),
+  m_model(new FileInfoModel(this)) {
 
   QHash<int, QByteArray> roles;
-  roles.insert(Item, "item");
+  roles.insert(UrlRole, "url");
+  roles.insert(TitleRole, "title");
+  roles.insert(MimeTypeRole, "mimeType");
+  roles.insert(CreatedRole, "created");
+  roles.insert(FileNameRole, "fileName");
+
+  setSourceModel(m_model);
+
+  setDynamicSortFilter(true);
+  setSortRole(CreatedRole);
 
   setRoleNames(roles);
+
+  if (m_mime.isEmpty()) {
+    m_mime.insert("jpg", "image/jpeg");
+    m_mime.insert("mp4", "video/mp4");
+  }
 }
 
 PostCaptureModel::~PostCaptureModel() {
-  qDeleteAll(m_items);
-  m_items.clear();
 
-  delete m_connection; m_connection = 0;
 }
 
-void PostCaptureModel::reload() {
-  delete m_connection; m_connection = 0;
-
-  if (!m_items.isEmpty()) {
-    beginRemoveRows(QModelIndex(), 0, m_items.size() - 1);
-    qDeleteAll(m_items);
-    m_items.clear();
-    endRemoveRows();
-  }
-
-  m_connection = new QSparqlConnection(DRIVER, QSparqlConnectionOptions(), this);
-  if (!m_connection->isValid()) {
-    emit error(tr("Failed to create SPARQL connection"));
-    return;
-  }
+QString PostCaptureModel::imagePath() const {
+  return m_imagePath;
+}
 
-  QString equipment = QString("urn:equipment:%1:%2:").arg(m_manufacturer).arg(m_model);
-
-  QSparqlQuery q(QUERY, QSparqlQuery::SelectStatement);
-  q.bindValue("equipment", equipment);
-  exec(q);
-
-  if (!m_connected) {
-    const char *slot = SLOT(graphUpdated(const QString&,
-                                        const QList<Quad>&,
-                                        const QList<Quad>&));
-    m_connected = QDBusConnection::sessionBus().connect(TRACKER_SERVICE, TRACKER_RESOURCE_PATH,
-                                                       TRACKER_RESOURCE_INTERFACE,
-                                                       TRACKER_RESOURCE_SIGNAL,
-                                                       TRACKER_RESOURCE_SIGNAL_SIGNATURE,
-                                                       this, slot);
+void PostCaptureModel::setImagePath(const QString& path) {
+  if (m_imagePath != path) {
+    m_imagePath = path;
+    emit imagePathChanged();
   }
+}
 
-  if (!m_connected) {
-    qmlInfo(this) << "Failed to connect to tracker " << TRACKER_RESOURCE_SIGNAL;
-  }
+QString PostCaptureModel::videoPath() const {
+  return m_videoPath;
 }
 
-void PostCaptureModel::exec(QSparqlQuery& query) {
-  if (!m_connection) {
-    qWarning() << "No connection to query";
-    return;
+void PostCaptureModel::setVideoPath(const QString& path) {
+  if (m_videoPath != path) {
+    m_videoPath = path;
+    emit videoPathChanged();
   }
+}
 
-  QSparqlResult *result = m_connection->exec(query);
-
-  if (result->hasError()) {
-    QSparqlError error = result->lastError();
-    qmlInfo(this) << "Error executing SPARQL query" << error.message();
-
-    delete result;
+QStringList PostCaptureModel::loadDir(QDir& dir) {
+  QStringList files;
+  QStringList entries(dir.entryList(QDir::Files | QDir::NoDotAndDotDot));
 
-    emit PostCaptureModel::error(tr("Failed to query tracker"));
+  foreach (const QString& entry, entries) {
+    files << dir.absoluteFilePath(entry);
   }
 
-  if (result) {
-    QObject::connect(result, SIGNAL(dataReady(int)), this, SLOT(dataReady(int)));
-    QObject::connect(result, SIGNAL(finished()), result, SLOT(deleteLater()));
-  }
+  return files;
 }
 
-int PostCaptureModel::rowCount(const QModelIndex& parent) const {
-  if (parent.isValid()) {
-    return 0;
-  }
+void PostCaptureModel::reload() {
+  QStringList files;
 
-  return m_items.size();
-}
+  QDir images(m_imagePath);
+  QDir videos(m_videoPath);
 
-QVariant PostCaptureModel::data(const QModelIndex& index, int role) const {
-  if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size()) {
-    return QVariant();
+  if (images.canonicalPath() == videos.canonicalPath()) {
+    files += loadDir(images);
   }
-
-  if (role == Item) {
-    return QVariant::fromValue(dynamic_cast<QObject *>(m_items[index.row()]));
+  else {
+    files += loadDir(images);
+    files += loadDir(videos);
   }
 
-  return QVariant();
-}
+  m_data.clear();
 
-QString PostCaptureModel::manufacturer() const {
-  return m_manufacturer;
-}
+  m_model->setFiles(files);
 
-void PostCaptureModel::setManufacturer(const QString& manufacturer) {
-  if (m_manufacturer != manufacturer) {
-    m_manufacturer = manufacturer;
-    emit manufacturerChanged();
-  }
+  sort(0, Qt::DescendingOrder);
 }
 
-QString PostCaptureModel::model() const {
-  return m_model;
+bool PostCaptureModel::lessThan(const QModelIndex& left, const QModelIndex& right) const {
+  return info(sourceModel()->data(left, Qt::DisplayRole).toString()).created() <
+    info(sourceModel()->data(right, Qt::DisplayRole).toString()).created();
 }
 
-void PostCaptureModel::setModel(const QString& model) {
-  if (m_model != model) {
-    m_model = model;
-    emit modelChanged();
+QVariant PostCaptureModel::data(const QModelIndex& index, int role) const {
+  if (!index.isValid() || index.row() < 0) {
+    return QVariant();
   }
-}
 
-void PostCaptureModel::dataReady(int totalCount) {
-  Q_UNUSED(totalCount);
+  QFileInfo inf = info(QSortFilterProxyModel::data(index, Qt::DisplayRole).toString());
+  switch (role) {
+  case UrlRole:
+    return QUrl::fromLocalFile(inf.absoluteFilePath());
 
-  QSparqlResult *result = dynamic_cast<QSparqlResult *>(sender());
-  if (!result) {
-    return;
-  }
-
-  while (result->next()) {
-    addRow(new PostCaptureModelItem(result->current(), this));
-  }
+  case TitleRole:
+    return inf.baseName();
 
-  result->previous();
-}
-
-void PostCaptureModel::addRow(PostCaptureModelItem *item) {
-  if (m_hash.contains(item->trackerId())) {
-    m_hash[item->trackerId()]->update(item);
-    delete item;
-    return;
-  }
+  case MimeTypeRole:
+    if (m_mime.contains(inf.completeSuffix())) {
+      return m_mime[inf.completeSuffix()];
+    }
 
-  beginInsertRows(QModelIndex(), m_items.size(), m_items.size());
-  m_items << item;
-  m_hash.insert(item->trackerId(), item);
+    return QString();
 
-  endInsertRows();
-}
+  case CreatedRole:
+    return inf.created().toString();
 
-void PostCaptureModel::remove(QObject *item) {
-  PostCaptureModelItem *i = dynamic_cast<PostCaptureModelItem *>(item);
-  if (!i) {
-    qmlInfo(this) << "Invalid item to remove";
-    return;
-  }
+  case FileNameRole:
+    return inf.fileName();
 
-  int index = m_items.indexOf(i);
-  if (index == -1) {
-    qmlInfo(this) << "Item" << i->trackerId() << "not found in model";
-    return;
+  default:
+    break;
   }
 
-  beginRemoveRows(QModelIndex(), index, index);
-  m_items.takeAt(index);
-  m_hash.remove(i->trackerId());
-  endRemoveRows();
-
-  i->deleteLater();
+  return QVariant();
 }
 
-void PostCaptureModel::graphUpdated(const QString& className, const QList<Quad>& deleted,
-                                   const QList<Quad>& inserted) {
-
-  // We will just assume tracker:available has changed and that's it.
-  // We are not really interested in the rest of properties.
-
-  if (!(className == QLatin1String(PHOTO_CLASS) || className == QLatin1String(VIDEO_CLASS))) {
-    return;
+QFileInfo PostCaptureModel::info(const QString& path) const {
+  if (m_data.contains(path)) {
+    return m_data[path];
   }
 
-  QList<int> items;
-
-  for (int x = 0; x < deleted.size(); x++) {
-    Quad q = deleted[x];
-    if (m_hash.contains(q.subject) && items.indexOf(q.subject) == -1) {
-      items << q.subject;
-    }
-  }
+  QFileInfo inf(path);
+  m_data.insert(path, inf);
 
-  for (int x = 0; x < inserted.size(); x++) {
-    Quad q = inserted[x];
-    if (m_hash.contains(q.subject) && items.indexOf(q.subject) == -1) {
-      items << q.subject;
-    }
-  }
+  return inf;
+}
 
-  for (int x = 0; x < items.size(); x++) {
-    QString query = QString(UPDATE_QUERY).arg(items[x]);
-    QSparqlQuery q(query, QSparqlQuery::SelectStatement);
+void PostCaptureModel::remove(const QUrl& file) {
+  QString path(file.toLocalFile());
 
-    exec(q);
-  }
+  m_data.remove(path);
+  m_model->removeFile(path);
 }
 
 #if defined(QT5)
@@ -289,93 +173,3 @@ void PostCaptureModel::setRoleNames(const QHash<int, QByteArray>& roles) {
   m_roles = roles;
 }
 #endif
-
-PostCaptureModelItem::PostCaptureModelItem(const QSparqlResultRow& row, QObject *parent) :
-  QObject(parent) {
-
-  for (int x = 0; x < row.count(); x++) {
-    QSparqlBinding b = row.binding(x);
-    m_data.insert(b.name(), b.value());
-  }
-}
-
-QString PostCaptureModelItem::type() const {
-  return value("type").toString();
-}
-
-QUrl PostCaptureModelItem::url() const {
-  return value("url").toUrl();
-}
-
-QString PostCaptureModelItem::created() const {
-  return formatDateTime(value("created").toDateTime());
-}
-
-QString PostCaptureModelItem::title() const {
-  return value("title").toString();
-}
-
-QString PostCaptureModelItem::fileName() const {
-  return value("filename").toString();
-}
-
-QString PostCaptureModelItem::mimeType() const {
-  return value("mimetype").toString();
-}
-
-bool PostCaptureModelItem::available() const {
-  return value("available", false).toBool();
-}
-
-QString PostCaptureModelItem::lastModified() const {
-  return formatDateTime(value("lastmod").toDateTime());
-}
-
-unsigned PostCaptureModelItem::trackerId() const {
-  return value("trackerid").toUInt();
-}
-
-bool PostCaptureModelItem::favorite() const {
-  return value("favorite", false).toBool();
-}
-
-void PostCaptureModelItem::setFavorite(bool add) {
-  if (favorite() != add) {
-    m_data["favorite"] = add;
-
-    emit favoriteChanged();
-  }
-}
-
-QString PostCaptureModelItem::formatDateTime(const QDateTime& dt) const {
-  return dt.toString();
-}
-
-void PostCaptureModelItem::update(PostCaptureModelItem *other) {
-  // We will only update available, favorite and title:
-#if 0
-  qDebug() << "i" << trackerId() << other->trackerId()  << "\n"
-          << "a" << available() << other->available() << "\n"
-          << "t" << title() << other->title() << "\n"
-          << "f" << favorite() << other->favorite();
-#endif
-
-  if (available() != other->available()) {
-    m_data["available"] = other->available();
-    emit availableChanged();
-  }
-
-  if (title() != other->title()) {
-    m_data["title"] = other->title();
-    emit titleChanged();
-  }
-
-  if (favorite() != other->favorite()) {
-    m_data["favorite"] = other->favorite();
-    emit favoriteChanged();
-  }
-}
-
-QVariant PostCaptureModelItem::value(const QString& id, const QVariant& def) const {
-  return m_data.contains(id) ? m_data[id] : def;
-}