[meego-commits] 7307: Changes to Trunk:Handset/meego-handset-photos
longbu
no_reply at build.meego.com
Fri Sep 3 10:23:12 UTC 2010
Hi,
I have made the following changes to meego-handset-photos in project Trunk:Handset. Please review and accept ASAP.
Thank You,
longbu
[This message was auto-generated]
---
Request #7307:
submit: devel:ux:handset/meego-handset-photos(r13) -> Trunk:Handset/meego-handset-photos
Message:
0.0.22
State: new 2010-09-03T03:23:11 longbu
Comment: None
changes files:
--------------
--- meego-handset-photos.changes
+++ meego-handset-photos.changes
@@ -0,0 +1,5 @@
+* Fri Sep 3 2010 Long Bu<long.bu at intel.com> -0.0.22
+ - Fixes: BMC6197, BMC6177
+ - lots of optimization on album related functions
+ - Add album automatically split rules
+
old:
----
meego-handset-photos-0.0.21.tar.bz2
new:
----
meego-handset-photos-0.0.22.tar.bz2
spec files:
-----------
--- meego-handset-photos.spec
+++ meego-handset-photos.spec
@@ -7,7 +7,7 @@
Name: meego-handset-photos
Summary: A Photo Viewer
-Version: 0.0.21
+Version: 0.0.22
Release: 1
Group: System/Libraries
License: Apache License, Version 2.0
other changes:
--------------
++++++ meego-handset-photos-0.0.21.tar.bz2 -> meego-handset-photos-0.0.22.tar.bz2
--- liballphoto
+++ liballphoto
+(directory)
--- liballphoto/abstracttasklet.cpp
+++ liballphoto/abstracttasklet.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include <QTimer>
+#include "abstracttasklet.h"
+
+AbstractTasklet::AbstractTasklet(QObject *parent) :
+ QObject(parent)
+{
+ Q_UNUSED(parent);
+}
+
+AbstractTasklet::~AbstractTasklet()
+{
+ jobs.clear();
+}
+
+
+void AbstractTasklet::stopJobQueue()
+{
+ jobs.clear();
+}
+
+void AbstractTasklet::processJobQueue()
+{
+ if (jobs.isEmpty())
+ return;
+
+ Job job = jobs.takeFirst();
+// job.dump();
+ processSingleJob(job);
+
+/* if(jobs.count() > 0)
+ QTimer::singleShot(0, this, SLOT(processJobQueue())); */
+}
+
+void Job::dump()
+{
+ qDebug() << "entering dump";
+ MPListItem *entry = static_cast<MPListItem *>(userData.value<void *>());
+ qDebug() << "entry is " << entry;
+ qDebug() << "xxxx: " << entry->thumbnailURI;
+ qDebug() << "Job at row " << row.row() << ":" << entry->thumbnailURI;
+ qDebug() << "leaving dump";
+}
+
--- liballphoto/abstracttasklet.h
+++ liballphoto/abstracttasklet.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#ifndef ABSTRACT_TASKLET_H
+#define ABSTRACT_TASKLET_H
+
+#include <QObject>
+#include <QModelIndex>
+
+#include <QDebug>
+
+#include "mplistmodel.h"
+
+struct MPListItem;
+struct Job {
+ QModelIndex row;
+ QVariant userData;
+
+ void dump();
+};
+
+class AbstractTasklet : public QObject
+{
+ Q_OBJECT
+public:
+ explicit AbstractTasklet(QObject *parent = 0);
+ virtual ~AbstractTasklet();
+
+ virtual void processSingleJob(Job& j) = 0;
+
+ void addJob(Job& j) {jobs << j;}
+signals:
+
+public slots:
+ void stopJobQueue();
+ void processJobQueue();
+
+private:
+ QList<Job> jobs;
+};
+
+#endif // TASKLET_H
--- liballphoto/dynamicmlist.cpp
+++ liballphoto/dynamicmlist.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include "dynamicmlist.h"
+#include "mcontentitemcreator.h"
+
+
+DynamicMList::DynamicMList(MWidget *parent, MContentItem::ContentItemStyle itemStyle, int id) :
+ MList(parent), tasklet(NULL)
+{
+ MContentItemCreator *thumbnailItemCreator = new MContentItemCreator(itemStyle, id);
+ setCellCreator(thumbnailItemCreator);
+}
+
+DynamicMList::~DynamicMList()
+{
+ if (tasklet)
+ disconnect(this, SIGNAL(panningStarted()), tasklet, SLOT(stopJobQueue()));
+
+ if (tasklet)
+ delete tasklet;
+
+}
+
+void DynamicMList::setTasklet (AbstractTasklet *newTasklet)
+{
+ if (!newTasklet)
+ return;
+
+ if (tasklet) {
+ disconnect(this, SIGNAL(panningStarted()), tasklet, SLOT(stopJobQueue()));
+ delete tasklet;
+ }
+
+ tasklet = newTasklet;
+ connect(this, SIGNAL(panningStarted()), tasklet, SLOT(stopJobQueue()));
+}
--- liballphoto/dynamicmlist.h
+++ liballphoto/dynamicmlist.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#ifndef DYNAMICMLIST_H
+#define DYNAMICMLIST_H
+
+#include <QObject>
+#include <MAbstractCellCreator>
+#include <QAbstractItemModel>
+#include <MList>
+#include <MContentItem>
+
+#include "abstracttasklet.h"
+
+class AbstractTasklet;
+
+class DynamicMList : public MList
+{
+Q_OBJECT
+public:
+ explicit DynamicMList(MWidget *parent = 0, MContentItem::ContentItemStyle style = MContentItem::SingleIcon, int id = 0);
+ virtual ~DynamicMList();
+
+ void setCellCreator(MCellCreator * itemCreator)
+ {
+ creator = itemCreator;
+ MList::setCellCreator(itemCreator);
+ }
+
+ MCellCreator *cellCreator() const {return creator;}
+ void setTasklet (AbstractTasklet *newTasklet);
+ AbstractTasklet *getTasklet() const {return tasklet;}
+public slots:
+ virtual void doTasklet() = 0;
+
+private:
+ MCellCreator *creator;
+ AbstractTasklet *tasklet;
+};
+
+#endif // DYNAMICMLIST_H
--- liballphoto/dynamicphotolist.cpp
+++ liballphoto/dynamicphotolist.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include <QDebug>
+#include <QTimer>
+#include <QPixmapCache>
+#include <MWidgetView>
+#include "dynamicphotolist.h"
+#include "dynamicmlist.h"
+#include "mcontentitemcreator.h"
+#include "mcontentitemex.h"
+
+
+
+DynamicPhotoList::DynamicPhotoList(MWidget *parent, M::Orientation orientation) : DynamicMList(parent)
+{
+ connect(this, SIGNAL(panningStopped()), this, SLOT(doTasklet()));
+ //connect(AppWindow::instance(), SIGNAL(orientationChanged(M::Orientation)), this, SLOT(onOrientationChanged(M::Orientation)));
+ photosListModel = new MPListModel(this);
+ photosTasklet = new PhotosTasklet(this);
+ setItemModel(photosListModel);
+ setTasklet(photosTasklet);
+ MContentItemCreator *photothumbnailCreator = dynamic_cast<MContentItemCreator *>(cellCreator());
+ onOrientationChanged(orientation);
+ setObjectName("thumbnailList");
+ enableItemClick();
+ QPixmapCache::setCacheLimit (4096);
+
+ QTimer::singleShot(1500, this, SLOT(doTasklet()));
+}
+
+DynamicPhotoList::~DynamicPhotoList()
+{
+ //The base class's destructor takes care of the model and the tasklet
+ disconnect(this, SIGNAL(panningStopped()), this, SLOT(doTasklet()));
+}
+
+void DynamicPhotoList::enableItemClick()
+{
+ connect(this, SIGNAL(itemClicked(const QModelIndex&)), this, SLOT(onClick(const QModelIndex&)));
+}
+
+void DynamicPhotoList::disableItemClick()
+{
+ disconnect(this, SIGNAL(itemClicked(const QModelIndex&)), this, SLOT(onClick(const QModelIndex&)));
+}
+
+void DynamicPhotoList::onOrientationChanged(M::Orientation orientation)
+{
+ MContentItemCreator *photothumbnailCreator = dynamic_cast<MContentItemCreator *>(cellCreator());
+ if (orientation == M::Portrait)
+ photothumbnailCreator->setCellObjectName("photoThumbnail_Portrait");
+ else
+ photothumbnailCreator->setCellObjectName("photoThumbnail_Landscape");
+
+ setColumns(orientation == M::Portrait ? 5 : 8);
+}
+
+void DynamicPhotoList::onClick(const QModelIndex &index)
+{
+ QVariant data = index.data(Qt::DisplayRole);
+ MPListItem *item = static_cast<MPListItem *>(data.value<void *>());
+
+ QString thumbnailPath = item->thumbnailURI;
+ if (thumbnailPath.isEmpty())
+ thumbnailPath = PhotosTasklet::getThumbnailPath(item->photoURI);
+ emit clicked(item->photoURI, thumbnailPath);
+}
+
+const int DynamicPhotoList::numItemsBeforeFirstVisibleOne = 4*8;
+const int DynamicPhotoList::numItemsAfterLastVisibleOne = 4*8;
+
+#define Q_JOB() do { \
+ QModelIndex index(firstVisibleIndex.sibling(i, 0)); \
+ if (!index.isValid())\
+ continue;\
+ QVariant data = index.data(Qt::DisplayRole);\
+ MPListItem *entry = static_cast<MPListItem *>(data.value<void *>());\
+ if (entry == NULL || entry->isLoaded) \
+ continue; \
+ \
+\
+ Job job; \
+ job.userData = data; \
+ job.row = index; \
+ getTasklet()->addJob(job); \
+} while (0)
+
+void DynamicPhotoList::doTasklet()
+{
+ QModelIndex firstVisibleIndex = firstVisibleItem();
+ QModelIndex lastVisibleIndex = lastVisibleItem();
+
+ int firstVFlatRow = firstVisibleIndex.row();
+ int lastVFlatRow = lastVisibleIndex.row();
+ if (lastVFlatRow - firstVFlatRow < 23) {
+ //when the doTasklet gets called in the timeout handler,
+ //the lastVisbieItem() has not been calculated yet by MListFastView
+ lastVFlatRow = firstVFlatRow + 23; //FixMe: Arbitrary number.
+ }
+ MPListModel *model = dynamic_cast<MPListModel *>(itemModel());
+
+ // remove rows before firstVFlatRow - numItemsBeforeFirstVisibleOne
+ int firstRow = firstVFlatRow - numItemsBeforeFirstVisibleOne;
+ if (firstRow < 0)
+ firstRow = 0;
+
+ int lastRow = lastVFlatRow + numItemsAfterLastVisibleOne;
+ if (lastRow >= model->rowCount())
+ lastRow = model->rowCount() - 1;
+
+
+ //Q tasklets
+ for (int i = firstVFlatRow; i <= lastRow; i++) {
+ QModelIndex index(firstVisibleIndex.sibling(i, 0));
+ if (!index.isValid())
+ continue;
+ QVariant data = index.data(Qt::DisplayRole);
+ MPListItem *entry = static_cast<MPListItem *>(data.value<void *>());
+ if (entry == NULL || entry->isLoaded)
+ continue;
+ model->setSpinner(index, true);
+ break;
+ }
+ for (int i = firstVFlatRow; i <= lastVFlatRow; i++)
+ Q_JOB();
+ for (int i = lastVFlatRow + 1; i <= lastRow; i++)
+ Q_JOB();
+ for (int i = firstRow; i < firstVFlatRow; i++)
+ Q_JOB();
+
+ for (int i = 0; i < firstRow; i++) {
+ if (i >= model->rowCount())
+ break;
+
+ //I guess when assign a new content to pixmap, it should release the orignal buffer
+ // and share the new content
+ model->setDefaultThumbnail(i);
+ }
+
+
+ // remove rows after lastVFlatRow + numItemsAfterLastvisibleOne
+ for (int i = lastRow + 1; i < model->rowCount(); i++)
+ model->setDefaultThumbnail(i);
+
+ int i = lastRow + 1;
+ if (i < model->rowCount()) {
+ QModelIndex index(firstVisibleIndex.sibling(i, 0));
+ if (index.isValid()) {
+ QVariant data = index.data(Qt::DisplayRole);
+ MPListItem *entry = static_cast<MPListItem *>(data.value<void *>());
+ if (entry && !entry->isLoaded)
+ model->setSpinner(index, true);
+ }
+ }
+
+ getTasklet()->processJobQueue();
+}
+
+
+void genCSSFile(const char *filename, int edge) {
+const char *l1 = "@const THUMBNAIL_CELL_SIZE:";
+const char *l2 = "#photoThumbnail2 { \n \
+ minimum-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE; \n\
+ preferred-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE; \n\
+ maximum-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE; \n \
+ image-object-name: \"PhotoThumbnailImage2\"; \n\
+}\n \
+#photoThumbnail2:pressed { \n\
+ image-object-name: \"PhotoThumbnailImage2\"; \n\
+} \n\
+#PhotoThumbnailImage2 { \n\
+ minimum-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE; \n\
+ preferred-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE; \n\
+ maximum-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE;\n\
+}";
+
+ QFile f(filename);
+ if (f.open(QFile::WriteOnly | QFile::Truncate)) {
+ QTextStream out(&f);
+ out << l1 << " " << edge << "px;" << "\n";
+ out << l2 << "\n";
+ }
+ f.close();
+}
+
--- liballphoto/dynamicphotolist.h
+++ liballphoto/dynamicphotolist.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#ifndef DYNAMICPHOTOLIST_H
+#define DYNAMICPHOTOLIST_H
+
+#include <QObject>
+#include "dynamicmlist.h"
+#include "mplistmodel.h"
+#include "photostasklet.h"
+
+class PhotosTasklet;
+class DynamicPhotoList : public DynamicMList
+{
+ Q_OBJECT
+public:
+ DynamicPhotoList(MWidget *parent = 0, M::Orientation orientation = M::Landscape);
+
+ virtual ~DynamicPhotoList();
+
+ static const int numItemsBeforeFirstVisibleOne;
+ static const int numItemsAfterLastVisibleOne;
+
+ void setAlbumUrn(QString albumUrn);
+ void enableItemClick();
+ void disableItemClick();
+
+public slots:
+ virtual void doTasklet();
+ void onClick(const QModelIndex &index);
+ void onOrientationChanged(M::Orientation orientation);
+
+Q_SIGNALS:
+ void clicked(const QString &photoURI, const QString &thumbnailPath);
+
+private:
+ MPListModel *photosListModel;
+ PhotosTasklet *photosTasklet;
+};
+
+#endif // DYNAMICPHOTOLIST_H
--- liballphoto/liballphotos.pro
+++ liballphoto/liballphotos.pro
+include (../common.pri)
+TARGET = allphotos
+TEMPLATE = lib
+target.path = /usr/lib
+
+MOC_DIR = .moc
+OBJECTS_DIR = .obj
+
+QT += opengl network dbus
+
+QMAKE_CXXFLAGS += -Wno-reorder
+
+CONFIG += link_pkgconfig \
+ qt \
+ meegotouch \
+ qdbus
+
+LIBS += -lqttracker
+
+SOURCES += *.cpp
+
+HEADERS += *.h
+
+headers.files = $$HEADERS
+headers.path = /usr/include
+
+INSTALLS += target headers
--- liballphoto/mcontentitemcreator.cpp
+++ liballphoto/mcontentitemcreator.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include <QDebug>
+#include <MLabel>
+#include "mcontentitemcreator.h"
+#include "mcontentitemex.h"
+
+void MContentItemCreator::updateCell(const QModelIndex &index, MWidget *cell) const
+{
+ MContentItemEx *contentItem = dynamic_cast<MContentItemEx *>(cell);
+ if (contentItem == NULL) // TODO This is shouldn't happen, list must know what it doing, but with multiple columns it happens sometimes
+ return;
+
+ QVariant data = index.data(Qt::DisplayRole);
+ MPListItem *item = static_cast<MPListItem *>(data.value<void *>());
+ //contentItem->setItemMode(ContentItemMode);
+ //qDebug() << "updateCell row:" << index.row() << "thumbnail" << item->thumbnailURI;
+ //qDebug() << "cellSize" << cell->size().width() << "," << cell->size().height();
+ contentItem->setPixmap(*(item->thumbnail));
+ if (item->showSpinner) {
+ contentItem->showSpinner();
+ } else {
+ contentItem->hideSpinner();
+ }
+
+ //if (contentItem->itemStyle() == MContentItem::TwoIconsTwoWidgets) {
+ // with implicit data sharing
+ //all contentItem should share one copy of defaultThumbnail's data'
+ contentItem->boundingRect();
+
+ //updateContentItemMode(index, contentItem);
+}
+
--- liballphoto/mcontentitemcreator.h
+++ liballphoto/mcontentitemcreator.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#ifndef PHOTOSCONTENTITEMCREATOR_H
+#define PHOTOSCONTENTITEMCREATOR_H
+
+#include <QModelIndex>
+#include <MContentItem>
+#include <MAbstractCellCreator>
+#include <MWidget>
+#include <MAction>
+#include <QSizeF>
+
+#include "mplistmodel.h"
+#include "mcontentitemex.h"
+
+
+class MContentItemCreator : public MAbstractCellCreator<MContentItemEx>
+{
+public:
+ MContentItemCreator(MContentItemEx::ContentItemStyle style, int _id = 0) : itemStyle(MContentItemEx::TwoIconsTwoWidgets),
+ id(_id)
+ {
+ itemStyle = style;
+ size = MAbstractCellCreator<MContentItemEx>::cellSize();
+
+ }
+
+ virtual ~MContentItemCreator()
+ {
+ }
+
+ //override
+ void setCellViewType(const QString &viewType) {
+ cellViewType = viewType;
+ MAbstractCellCreator<MContentItemEx>::setCellViewType(viewType);
+ updateSize();
+ }
+
+ void setCellObjectName(const QString &objectName) {
+ cellObjectName = objectName;
+ MAbstractCellCreator<MContentItemEx>::setCellObjectName(objectName);
+ updateSize();
+ }
+/*
+ void setOddCellObjectName(const QString &objectName) {
+ oddCellObjectName = objectName;
+ //MAbstractCellCreator<MContentItemEx>::setCellObjectName(objectName);
+ updateSize();
+ }
+
+ void setEvenCellObjectName(const QString &objectName) {
+ evenCellObjectName = objectName;
+ //MAbstractCellCreator<MContentItemEx>::setCellObjectName(objectName);
+ updateSize();
+ }
+*/
+
+ //override this for specifying Style to SingleIcon
+ virtual MWidget *createCell(const QModelIndex &index, MWidgetRecycler &recycler) const {
+ recycler.setMaxItemsPerClass(0);
+ MContentItemEx *cell = dynamic_cast<MContentItemEx *>(recycler.take(MContentItem::staticMetaObject.className()));
+ if (cell == NULL) {
+ cell = new MContentItemEx(itemStyle, NULL, id);
+
+ cell->index = index;
+ if (!cellViewType.isEmpty())
+ cell->setViewType(cellViewType);
+ if (!cellObjectName.isEmpty())
+ cell->setObjectName(cellObjectName);
+
+
+ }
+
+ updateCell(index, cell);
+ return cell;
+ }
+
+ void updateCell(const QModelIndex &index, MWidget *cell) const;
+
+ // void setColumns(int columns) {
+ // Q_ASSERT(columns > 0);
+ // amountOfColumns = columns;
+ // }
+
+ virtual QSizeF cellSize() const {
+ return size;
+ }
+
+private:
+ void updateSize() {
+ MContentItemEx *cell = new MContentItemEx(itemStyle, NULL, id);
+ if (!cellViewType.isEmpty())
+ cell->setViewType(cellViewType);
+ if (!cellObjectName.isEmpty())
+ cell->setObjectName(cellObjectName);
+ size = cell->effectiveSizeHint(Qt::PreferredSize);
+ delete cell;
+ qDebug() << "update cell Size to" << size;
+ }
+
+ QSizeF size;
+ QString cellViewType;
+ QString cellObjectName;
+ MContentItemEx::ContentItemStyle itemStyle;
+
+ int id; //identify the cell is for photo or album
+};
+
+
+
+#endif // PHOTOSCONTENTITEMCREATOR_H
+
--- liballphoto/mcontentitemex.cpp
+++ liballphoto/mcontentitemex.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include "mcontentitemex.h"
+
+void MContentItemEx::setPixmap(const QPixmap &pixmap)
+{
+ MContentItem::setPixmap(pixmap);
+}
+
+void MContentItemEx::showSpinner()
+{
+ MProgressIndicator *org = dynamic_cast<MProgressIndicator *>(additionalItem());
+ if (!org) {
+ MProgressIndicator *spinner = new MProgressIndicator(this, MProgressIndicator::spinnerType);
+ spinner->setUnknownDuration(true);
+ spinner->setObjectName("loadingSpinner");
+ setAdditionalItem(spinner);
+ delete org;
+ }
+}
+
+void MContentItemEx::hideSpinner()
+{
+ MProgressIndicator *org = dynamic_cast<MProgressIndicator *>(additionalItem());
+ setAdditionalItem(NULL);
+ if (org)
+ delete org;
+}
+
--- liballphoto/mcontentitemex.h
+++ liballphoto/mcontentitemex.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef MCONTENTITEMEX_H
+#define MCONTENTITEMEX_H
+
+#include <MContentItem>
+#include <QModelIndex>
+
+class MContentItemEx : public MContentItem
+{
+public:
+
+ MContentItemEx(MContentItem::ContentItemStyle itemStyle = MContentItem::TwoIconsTwoWidgets, QGraphicsItem *parent = 0, int _id = 0)
+ : MContentItem(itemStyle, parent), id(_id)
+ {
+ }
+
+ virtual ~MContentItemEx(){};
+
+
+ QModelIndex index; // the index of this item in some model
+ int id;
+
+ void showSpinner();
+ void hideSpinner();
+
+public slots:
+ void setPixmap(const QPixmap &pixmap);
+
+};
+
+#endif // MCONTENTITEMEX_H
--- liballphoto/mplistmodel.cpp
+++ liballphoto/mplistmodel.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include <QDir>
+#include <QDebug>
+#include <QtDBus/QtDBus>
+#include <MTheme>
+#include "mplistmodel.h"
+#include "searchengine.h"
+#include "thumbnailer.h"
+#include "photostasklet.h"
+
+QHash<QString, QString> MPListModel::urnToPathHashMap;
+
+QString MPListModel::homePath = QDir::toNativeSeparators(QDir::homePath());
+QString MPListModel::thumbnail_folder = QDir::separator() + QString(".thumbnails") + QDir::separator() + QString("normal");
+QString MPListModel::thumbnail_suffix = ".png";
+
+MPListModel::MPListModel(DynamicMList *controller) : list(controller)
+{
+ //Create Thumbnailer
+ Thumbnailer::instance();
+ QObject::connect(Thumbnailer::instance(), SIGNAL(ready(uint,QStringList)), this, SLOT(handleReady(uint,QStringList)), Qt::QueuedConnection);
+ QObject::connect(Thumbnailer::instance(), SIGNAL(error(uint, QStringList, const int &, const QString &)), this, SLOT(handleError(uint,QStringList, const int &, const QString &)), Qt::QueuedConnection);
+ //QObject::connect(TrackerListener::instance(), SIGNAL(SubjectsAdded(const QStringList &subjects)), this, SLOT(handlePhotoAdded(const QStringList &urns)));
+ int indexValue = 0;
+
+ //Build photoItemVector
+
+ //defaultThumbnail.load(QString(MPListModel::testThumbnailDir).append("/defaultThumbnail.png"));
+ pDefaultThumbnail = new QPixmap; //(QPixmap *)MTheme::pixmap("defaultThumbnail");
+ //pDefaultThumbnail = new QPixmap(*defaultPixmap);
+ //MTheme::releasePixmap(defaultPixmap);
+
+#if 0
+ // for debug only, pull all thumbnails int ~/.thumbnail into this model
+ QDir thumbnailDir(MPListModel::testThumbnailDir);
+ qDebug() << "dir is " << MPListModel::testThumbnailDir;
+ bool yyy = thumbnailDir.exists();
+ thumbnailDir.setNameFilters(QStringList() << "*.png");
+
+ QFileInfoList fileInfoList = thumbnailDir.entryInfoList();
+ QStringList xxx = thumbnailDir.entryList(QDir::Files);
+
+ for (int i = 0; i < fileInfoList.size(); i++) {
+ listItemsVector << new MPListItem("", fileInfoList.at(i).absoluteFilePath(), defaultThumbnail);
+ }
+#endif
+ thumbnailDir = new QDir(homePath + thumbnail_folder);
+
+ //get all photo urls from tracker
+ QVector<QStringList> *photos = NULL; //hold all photo urls got from tracker
+ bool deletePhotos = false;
+ //get all photo urls from tracker
+ photos = new QVector<QStringList>();
+ deletePhotos = true;
+ SearchEngine::getAllPhoto(*photos);
+
+ for (QVector<QStringList>::iterator i = photos->begin(); i != photos->end(); i++) {
+ QFile f;
+ QUrl url = QUrl::fromEncoded((*i)[0].toAscii());
+
+ f.setFileName(url.toLocalFile());
+ if (f.exists()) // only create photoItem for files that exist; Tracker may has bug
+ {
+ MPListItem *item = new MPListItem( (*i)[0] , "", pDefaultThumbnail, (*i)[1]);
+ item->urn = (*i)[2];
+ listItemsVector << item;
+
+ pathToIndexHashMap.insert(url.toLocalFile(), indexValue);
+ urnToPathHashMap.insert(item->urn, url.toLocalFile());
+ indexValue++;
+ }
+ }
+
+ if (deletePhotos)
+ delete photos;
+}
+
+void MPListModel::addOutstandingThumbnailRequest(QString requestPath)
+{
+ outstandingThumbnailRequest.insert(requestPath);
+}
+
+void MPListModel::removeOutstandingThumbnailRequest(QString requestPath)
+{
+ outstandingThumbnailRequest.remove(requestPath);
+}
+
+
+
+void MPListModel::handleReady(const unsigned int &handler, const QStringList &urls)
+{
+ for (QStringList::const_iterator i = urls.begin(); i != urls.end(); i++) {
+ QString localPath = *i;
+ QString key = localPath.remove(QRegExp("^file:\/\/"));
+ if (!outstandingThumbnailRequest.contains(key)) {
+ outstandingThumbnailRequest.remove(key);
+ continue;
+ }
+ int indexValue = pathToIndexHashMap.value(key, -1);
+ if (indexValue == -1)
+ continue;
+ MPListItem *entry = listItemsVector[indexValue];
+ if (entry->thumbnailURI.isEmpty())
+ continue;
+ entry->thumbnail = new QPixmap(PhotosTasklet::squareQPixmapFromPath(entry->thumbnailURI, list->cellCreator()->cellSize().toSize().width()));
+ entry->isLoaded = true;
+ entry->showSpinner = false;
+ QModelIndex modelIndex = index(indexValue, 0);
+ QModelIndex next = modelIndex.sibling(modelIndex.row() + 1, 0);
+ if (next.isValid()) {
+ QVariant data = next.data(Qt::DisplayRole);
+ MPListItem *next_entry = static_cast<MPListItem *>(data.value<void *>());
+ if (!next_entry->isLoaded)
+ next_entry->showSpinner = true;
+ thumbnailWasLoaded(next); //emit date changed signal;
+ }
+
+ thumbnailWasLoaded(modelIndex);
+ QTimer::singleShot(0, list->getTasklet(), SLOT(processJobQueue()));
+ }
+}
+
+void MPListModel::handleError(const unsigned int &handler, const QStringList &urls, const int &errorCode, const QString &message)
+{
+ if (errorCode == 0)
+ return;
+ for (QStringList::const_iterator i = urls.begin(); i != urls.end(); i++) {
+ QString localPath = *i;
+ QString key = localPath.remove(QRegExp("^file:\/\/"));
+ if (!outstandingThumbnailRequest.contains(key)) {
+ outstandingThumbnailRequest.remove(key);
+ continue;
+ }
+ int indexValue = pathToIndexHashMap.value(key, -1);
+ if (indexValue == -1)
+ continue;
+ MPListItem *entry = listItemsVector[indexValue];
+ entry->thumbnail = new QPixmap(PhotosTasklet::squareQPixmapFromPath(entry->thumbnailURI, list->cellCreator()->cellSize().toSize().width()));
+ entry->isLoaded = true;
+ entry->showSpinner = false;
+ QModelIndex modelIndex = index(indexValue, 0);
+ QModelIndex next = modelIndex.sibling(modelIndex.row() + 1, 0);
+ if (next.isValid()) {
+ QVariant data = next.data(Qt::DisplayRole);
+ MPListItem *next_entry = static_cast<MPListItem *>(data.value<void *>());
+ if (!next_entry->isLoaded) {
+ next_entry->showSpinner = true;
+ }
+ thumbnailWasLoaded(next); //emit date changed signal;
+ }
+
+ thumbnailWasLoaded(modelIndex);
+ QTimer::singleShot(0, list->getTasklet(), SLOT(processJobQueue()));
+ }
+}
+
+MPListModel::~MPListModel()
+{
+ QObject::disconnect(Thumbnailer::instance(), SIGNAL(ready(uint,QStringList)), this, SLOT(handleReady(uint,QStringList)));
+ QObject::disconnect(Thumbnailer::instance(), SIGNAL(error(uint, QStringList, const int &, const QString &)), this, SLOT(handleError(uint,QStringList, const int &, const QString &)));
+ for (int i = 0; i < listItemsVector.count(); i++) {
+ delete listItemsVector[i];
+ }
+
+ listItemsVector.resize(0);
+ delete thumbnailDir;
+ //MTheme::releasePixmap(pDefaultThumbnail);
+ delete pDefaultThumbnail;
+}
+
+QString MPListModel::testThumbnailDir = "themes/.thumbnails/normal";
+
+QVariant MPListModel::data(const QModelIndex &index, int role) const
+{
+ // This function will be called many times during fast panning, lets
+ // check boundaries and validnes only in debug mode
+ Q_ASSERT(index.isValid());
+ Q_ASSERT(index.row() < listItemsVector.size());
+
+ if (role == Qt::DisplayRole) {
+ // Let's store a pointer into QVariant, otherwise QT will make a copy but we are lazy
+ // and don't want to copy stuff around
+ return QVariant::fromValue(static_cast<void *>(listItemsVector[index.row()]));
+ }
+
+ return QVariant();
+}
+
+int MPListModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return listItemsVector.size();
+}
+
+int MPListModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return 1;
+}
+
+/*
+bool MPListModel::insertRows(int row, int count, const QModelIndex &parent)
+{
+ if (count <= 0)
+ return true;
+
+ emit layoutAboutToBeChanged();
+ beginInsertRows(parent, row, row + count - 1);
+ for (int i=0; i < count; i++) {
+ MPListItem *item = listItemsVector[row + i];
+ QString fileString = item->photoURI.remove(QRegExp("^file:\/\/"));
+ QStringList list = fileString.split("/");
+ QString filename = list.last();
+
+ QString targetName = "copy_of_" + filename;
+ list[list.count()-1] = targetName;
+ QString targetString = list.join("/");
+ int n = 2;
+ while (QFile::exists(targetString)) {
+ targetName = "copy_" + QString::number(n) + "_of_" + filename;
+ list[list.count()-1] = targetName;
+ targetString = list.join("/");
+ n++;
+ }
+ QFile::copy(fileString, targetString);
+ }
+ endInsertRows();
+ emit layoutChanged();
+ return true;
+}
+*/
+
+
+/*
+bool MPListModel::removeRows(int row, int count, const QModelIndex &parent)
+{
+ if (count <= 0)
+ return true; //Successfully removed 0 rows.
+
+ emit layoutAboutToBeChanged();
+ beginRemoveRows(parent, row, row + count - 1);
+ //Todo: Huan review this for possible tracker-related clean-up
+ for (int i=0; i < count; i++) {
+ MPListItem *itemToBeDeleted = listItemsVector[row + i];
+ QFile::remove(itemToBeDeleted->photoURI.remove(QRegExp("^file:\/\/")));
+ delete itemToBeDeleted;
+ QUrl url = QUrl::fromEncoded(listItemsVector[row]->photoURI.toAscii());
+ pathToIndexHashMap.remove(url.toLocalFile());
+ listItemsVector.remove(row);
+
+ }
+ endRemoveRows();
+ emit layoutChanged();
+ return true;
+}
+*/
+
+
+void MPListModel::thumbnailWasLoaded(const QModelIndex &index)
+{
+ emit dataChanged(index, index);
+}
+
+void MPListModel::setSparql(QString qlString)
+{
+ //rebuild the model with the new qlString
+}
+
+void MPListModel::setDefaultThumbnail(int index)
+{
+ if (listItemsVector[index]->isLoaded) {
+ delete listItemsVector[index]->thumbnail;
+ listItemsVector[index]->thumbnail = pDefaultThumbnail;
+ listItemsVector[index]->isLoaded = false;
+ }
+}
+
+void MPListModel::setSpinner(const QModelIndex &index, bool showSpinner)
+{
+ int i = index.row();
+ if (listItemsVector[i]->isLoaded && !showSpinner)
+ listItemsVector[i]->showSpinner = false;
+ else if (!listItemsVector[i]->isLoaded)
+ listItemsVector[i]->showSpinner = showSpinner;
+
+ thumbnailWasLoaded(index);
+}
+
+#if 0
+void MPListModel::updateAlbumModel()
+{
+ qDebug() << "MPListModel::updateAlbumModel()";
+ if (getDataType() == MPAbstractListModelOps::Album) {
+ // create a album model
+ QVector<QStringList> *result = new QVector<QStringList>();
+ SearchEngine::getAllPhotoAlbums(*result);
+ qDebug() << "MPListModel::updateAlbumModel() getallphotoalbums:" << t.elapsed();
+ emit layoutAboutToBeChanged();
+ beginRemoveRows(QModelIndex(), 0, listItemsVector.count() - 1);
+ qDebug() << "albums:" << result->size();
+ for (int i = 0; i < listItemsVector.count(); i++) {
+ delete listItemsVector[i];
+ }
+ listItemsVector.clear();
+ pathToIndexHashMap.clear();
+ endRemoveRows();
+
+ int indexValue = 0;
+ MPSettings settings;
+ for(QVector<QStringList>::iterator i = result->begin();i != result->end(); i++) {
+ MPListItem *t = new MPListItem((*i)[1], ((*i)[2]).toInt(), (*i)[0]);
+ t->thumbnail = pDefaultThumbnail;
+ t->urn = (*i)[0];
+ qDebug() << "paul debug urn in updateAlbum:" << t->urn;
+ t->photoURI = settings.getAlbumCover(t->urn);
+ qDebug() << "12345 paul debug cover uri:" << t->photoURI;
+ listItemsVector << t;
+ qDebug() << "paul debug in update album " << t->urn << "num photos" << (*i)[2];
+
+ pathToIndexHashMap.insert(QUrl::fromEncoded(t->photoURI.toAscii()).toLocalFile(), indexValue++);
+ }
+ emit layoutChanged();
+ emit dataChanged(index(0, 0), index(result->size() -1, 0));
+ reset();
+ list->getTasklet()->stopJobQueue();
+ list->doTasklet();
+ }
+ qDebug() << "MPListModel::updateAlbumModel() end";
+}
+#else
+
+#endif
+
+void MPListModel::relayout()
+{
+ emit layoutChanged();
+}
+
--- liballphoto/mplistmodel.h
+++ liballphoto/mplistmodel.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#ifndef MPLISTMODEL_H
+#define MPLISTMODEL_H
+
+#include <QAbstractTableModel>
+#include <QPixmap>
+#include "thumbnailer.h"
+#include "dynamicmlist.h"
+
+// Structure which contain data for each item
+// This structure is used for both photo and album
+struct MPListItem {
+public:
+ MPListItem(QString newphotoURI, QString newThumbnailURI, QPixmap *t, QString newmimetype) :
+ thumbnail(NULL), showSpinner(false), photoURI(newphotoURI), thumbnailURI(newThumbnailURI), isLoaded(false), mimetype(newmimetype), numPhotos(0)
+ {
+ thumbnail = t; //implicit data sharing
+ }
+
+ MPListItem(QString _albumName, int _numPhotos) :
+ thumbnail(NULL), showSpinner(false), isLoaded(false), numPhotos(_numPhotos) {};
+
+ MPListItem(QString _albumName, int _numPhotos, QString _albumID) :
+ thumbnail(NULL), showSpinner(false), isLoaded(false), albumID(_albumID), numPhotos(_numPhotos) {};
+
+
+ QString urn;
+
+
+ QPixmap *thumbnail; // will be filled with empty image, after real image will be loaded it will replace old one
+ bool showSpinner; //whether to show Spinner
+ QString photoURI;
+ QString thumbnailURI;
+ bool isLoaded;
+ QString mimetype;
+
+// QString albumName; //album Name. for album item only
+ QString albumID; // used for backend to idenity album
+ int numPhotos; // number of photos in this album. for album item only
+
+private:
+ // explicit MPListItem(); //disable default constructor
+};
+
+class DynamicMList;
+//Data model for photo listing and album listing
+class MPListModel: public QAbstractTableModel
+{
+ Q_OBJECT
+
+public:
+ // Defining roles here which will be used for sorting and filtering in PhoneBookSortedModel
+ //enum PhoneBookRoles {
+ // PhoneBookSortRole = Qt::UserRole + 1,
+ // PhoneBookFilterRole
+ //};
+ MPListModel(DynamicMList *controller);
+ virtual ~MPListModel();
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ void setSparql(QString qlString);
+ void removeAlbum(const QModelIndex &index);
+
+/* bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+*/
+ virtual void thumbnailWasLoaded(const QModelIndex &index);
+ virtual void setDefaultThumbnail(int index);
+ virtual void setSpinner(const QModelIndex &index, bool showSpinner);
+
+ virtual void addOutstandingThumbnailRequest(QString ruquestPath);
+ virtual void removeOutstandingThumbnailRequest(QString ruquestPath);
+
+ virtual void relayout();
+
+ static QString testThumbnailDir;
+ static QString homePath;
+ static QString thumbnail_folder;
+ static QString thumbnail_suffix;
+ Thumbnailer *thumbnailer;
+ QDir *thumbnailDir;
+
+private:
+ QVector<MPListItem *> listItemsVector;
+ QPixmap *pDefaultThumbnail;
+ QHash<QString, int> pathToIndexHashMap;
+ static QHash<QString, QString> urnToPathHashMap;
+ QSet<QString> outstandingThumbnailRequest;
+ DynamicMList *list;
+
+ friend class DynamicPhotoList;
+ friend class DynamicAlbumList;
+private slots:
+ void handleReady(const unsigned int &handler, const QStringList &urls);
+ void handleError(const unsigned int &handler, const QStringList &urls, const int &errorcode, const QString &message);
+};
+
+
+
+#endif // MPLISTMODEL_H
--- liballphoto/photostasklet.cpp
+++ liballphoto/photostasklet.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include <QCryptographicHash>
+#include <QDir>
+#include <QDebug>
+#include "photostasklet.h"
+#include "mplistmodel.h"
+
+PhotosTasklet::PhotosTasklet(DynamicPhotoList *list) : outstandingChecking(false)
+{
+ this->list = list;
+}
+
+PhotosTasklet::~PhotosTasklet()
+{
+
+}
+
+QPixmap PhotosTasklet::squareQPixmapFromPath(QString path, qreal edgeR)
+{
+ QImage a = QImage(path);
+ int edge = (int)edgeR;
+/* int w = a.width();
+ int h = a.height();
+ int edge = w;
+ if (edge > h)
+ edge = h; */
+ QImage b = a.scaled(edge, edge, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
+ QImage c = b.copy(0, 0, edge, edge);
+ return QPixmap::fromImage(c);
+}
+
+#if 0
+void PhotosTasklet::checkThumbnailsGenerated()
+{
+ outstandingChecking = false;
+ if (thumbnailsToBeGenerated.isEmpty())
+ return;
+
+ int cnt = thumbnailsToBeGenerated.count();
+ QTime now;
+ now.start();
+ qDebug() << "PhotosTasklet::checkThumbnailsGenerated() time" << now << ":" << now.msec();
+ while (cnt-- > 0) {
+ ThumbnailCheckJob j = thumbnailsToBeGenerated.takeFirst();
+ qDebug() << "PhotosTasklet::checkThumbnailsGenerated() duetime" << j.dueTime << "cnt:" << cnt;
+ now.start();
+ if (j.dueTime < now)
+ continue;
+
+ MPListItem *entry = static_cast<MPListItem *>(j.userData.value<void *>());
+ QModelIndex index = j.row;
+ MPListModel *photoModel = dynamic_cast<MPListModel *>(const_cast<QAbstractItemModel *>(index.model()));
+ QFile f;
+ f.setFileName(entry->thumbnailURI);
+ if (f.exists()) {
+ entry->thumbnail = new QPixmap(squareQPixmapFromPath(entry->thumbnailURI, AppWindow::instance()->photoList->cellCreator()->cellSize().toSize().width()));
+ //entry->thumbnail = new QPixmap(squareQPixmapFromPath(entry->thumbnailURI, 112));
+ entry->isLoaded = true;
+ photoModel->thumbnailWasLoaded(index);
+ } else {
+ thumbnailsToBeGenerated << j;
+ }
+ }
+
+ /*if(thumbnailsToBeGenerated.count() > 0)
+ QTimer::singleShot(CHECK_THUMBNAIL_FILE_INTERVAL, this, SLOT(checkThumbnailsGenerated()));*/
+}
+#endif
+
+QString PhotosTasklet::getThumbnailPath(const QString &uri)
+{
+ //use its Utf8 to perform md5
+ QByteArray md5Result = QCryptographicHash::hash(uri.toUtf8(), QCryptographicHash::Md5);
+ QString thumbnailPath = MPListModel::homePath + MPListModel::thumbnail_folder + QDir::separator() + md5Result.toHex() + MPListModel::thumbnail_suffix;
+ return thumbnailPath;
+}
+
+void PhotosTasklet::processSingleJob(Job& j)
+{
+ QModelIndex index = j.row;
+ MPListItem *entry = static_cast<MPListItem *>(j.userData.value<void *>());
+ QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model());
+ MPListModel *photoModel = dynamic_cast<MPListModel *>(model);
+ QByteArray md5Result;
+#if 0
+ if (!entry->isLoaded) {
+ qDebug() << "processSingleJob: row " << index.row() << "thumbnail:" << QUrl::fromEncoded(entry->photoURI.toAscii()).path() << "entry@" << (void *)entry;
+ entry->thumbnail = new QPixmap(squareQPixmapFromPath(QUrl::fromEncoded(entry->photoURI.toAscii()).path()));
+ entry->isLoaded = true;
+ photoModel->thumbnailWasLoaded(index);
+ }
+#else
+ //generate thumbnailURI if it does not exist here
+ if (entry->thumbnailURI.isEmpty()) {
+#if 0
+ QUrl url = QUrl::fromEncoded(entry->photoURI.toAscii());
+ QString path = QString("file://") + url.path();
+ //use its Utf8 to perform md5
+ md5Result = QCryptographicHash::hash(path.toUtf8(), QCryptographicHash::Md5);
+ entry->thumbnailURI = photoModel->homePath + photoModel->thumbnail_folder + QDir::separator() + md5Result.toHex() + photoModel->thumbnail_suffix;
+ qDebug() << "entry " << entry << " " << path << " " << "thumbnailURI generated is " << entry->thumbnailURI;
+#else
+ entry->thumbnailURI = getThumbnailPath(entry->photoURI);
+#endif
+ }
+
+ //Some thumbnails may have not been created yet
+ QFile f;
+ f.setFileName(entry->thumbnailURI);
+ if (f.exists()) {
+ entry->thumbnail = new QPixmap(squareQPixmapFromPath(entry->thumbnailURI, list->cellCreator()->cellSize().toSize().width()));
+ //entry->thumbnail = new QPixmap(squareQPixmapFromPath(entry->thumbnailURI, 112));
+ entry->isLoaded = true;
+ entry->showSpinner = false;
+ QModelIndex next = index.sibling(index.row() + 1, 0);
+ if (next.isValid()) {
+ QVariant data = next.data(Qt::DisplayRole);
+ MPListItem *next_entry = static_cast<MPListItem *>(data.value<void *>());
+ if (!next_entry->isLoaded)
+ next_entry->showSpinner = true;
+ photoModel->thumbnailWasLoaded(next);
+ }
+ photoModel->thumbnailWasLoaded(index);
+ QTimer::singleShot(0, this, SLOT(processJobQueue()));
+ } else {
+ QUrl url = QUrl::fromEncoded(entry->photoURI.toAscii());
+ photoModel->addOutstandingThumbnailRequest(url.path());
+ Thumbnailer::instance()->requestThumbnail(QString(("file://" + url.path())), entry->mimetype);
+ }
+
+#endif
+}
--- liballphoto/photostasklet.h
+++ liballphoto/photostasklet.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef PHOTOSTASKLET_H
+#define PHOTOSTASKLET_H
+
+#include "abstracttasklet.h"
+#include "dynamicphotolist.h"
+
+class DynamicPhotoList;
+struct ThumbnailCheckJob : public Job
+{
+ ThumbnailCheckJob(Job &j, int dueSec = 3) : Job(j) { dueTime = QTime::currentTime().addSecs(dueSec);};
+
+ QTime dueTime; //check the thumbnail file before this time
+};
+
+class PhotosTasklet : public AbstractTasklet
+{
+public:
+ explicit PhotosTasklet(DynamicPhotoList *parent = 0);
+ virtual ~PhotosTasklet();
+
+ virtual void processSingleJob(Job& j);
+ static const int CHECK_THUMBNAIL_FILE_INTERVAL = 100;
+ static QPixmap squareQPixmapFromPath(QString path, qreal edgeR);
+ static QString getThumbnailPath(const QString &uri);
+
+private:
+ DynamicPhotoList *list;
+ QList<ThumbnailCheckJob> thumbnailsToBeGenerated;
+ bool outstandingChecking;
+};
+
+#endif // PHOTOSTASKLET_H
--- liballphoto/searchengine.cpp
+++ liballphoto/searchengine.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include "searchengine.h"
+#include <QtTracker/Tracker>
+static const QString SqlGetAllPhoto = "SELECT nie:url(nie:isStoredAs(?photo)) nie:mimeType(?photo) ?photo nfo:fileLastModified(?photo) nie:contentCreated(?photo) WHERE{?photo a nmm:Photo}";
+
+static const QString SqlGetAllPhotoAlbums = "SELECT nie:identifier(?imagelist) nie:title(?imagelist) nfo:entryCounter(?imagelist) ?imagelist " \
+ " nao:identifier(?tag) nao:prefLabel(?tag) ?tag " \
+ " WHERE {?imagelist a nmm:ImageList . OPTIONAL {?imagelist nao:hasTag ?tag . ?tag nao:identifier 'AlbumCover' . }}";
+
+static const QString SqlGetAlbumPhotos = "SELECT nie:url(nie:isStoredAs(?image)) nie:contentCreated(?image) ?image nie:identifier(?imagelist) nie:title(?imagelist) nfo:entryCounter(?imagelist) "\
+ " WHERE { ?imagelist nfo:hasMediaFileListEntry ?entry . ?entry nfo:entryContent ?image "\
+ " { SELECT ?imagelist WHERE {?imagelist a nmm:ImageList ; nie:identifier '%1'} } }";
+
+static const QString SqlRemoveAlbum = " DELETE { ?photoalbum a nmm:ImageList } WHERE { ?photoalbum nie:identifier '%1' }";
+
+static const QString SqlCreateAlbumBegin = "INSERT { _:a a nmm:ImageList ; nie:identifier '%1' ; nie:title '%2' ; nfo:entryCounter %3 ";
+static const QString SqlInsertItem = " nfo:hasMediaFileListEntry [ a nfo:MediaFileListEntry; nfo:entryContent <%1>; nfo:listPosition %2 ] ";
+static const QString SqlCreateAlbumEnd = " }";
+
+static const QString SqlQueryAlbumCoverTag = "SELECT ?tag nao:prefLabel(?tag) " \
+ " WHERE {?imagelist a nmm:ImageList; nao:hasTag ?tag . ?tag nao:identifier 'AlbumCover' . FILTER (str(?imagelist) = '%1')}";
+static const QString SqlDeleteAlbumCoverTag = "DELETE {?tag a rdfs:Resource } WHERE {?imagelist nao:hasTag ?tag . ?tag nao:identifier 'AlbumCover' . " \
+ "{ SELECT ?imagelist WHERE {?imagelist a nmm:ImageList . FILTER (str(?imagelist) = '%1') } } }";
+static const QString SqlInsertAlbumCoverTag = "INSERT { _:tag a nao:Tag ; nao:prefLabel '%1' ; nao:identifier 'AlbumCover' . ?imagelist nao:hasTag _:tag } " \
+ " WHERE { ?imagelist a nmm:ImageList . FILTER (str(?imagelist) = '%2') }";
+static const QString SqlGetAlbumURN = "SELECT ?imagelist WHERE {?imagelist a nmm:ImageList ; nie:identifier '%1' }";
+
+static const QString SqlQueryObjectTag = "SELECT nao:prefLabel(?tag) nao:identifier(?tag) ?tag " \
+ " WHERE {?object a nie:InformationElement; nao:hasTag ?tag . ?tag nao:identifier '%1' . " \
+ " FILTER (str(?object) = '%2')}";
+static const QString SqlInsertObjectTag = "INSERT { _:tag a nao:Tag ; nao:prefLabel '%1' ; nao:identifier '%2' . ?object nao:hasTag _:tag } " \
+ " WHERE { ?object a nie:InformationElement . FILTER (str(?object) = '%3') }";
+static const QString SqlDeleteObjectTag = "DELETE {?tag a rdfs:Resource } WHERE {?object nao:hasTag ?tag . ?tag nao:identifier '%1' . " \
+ " { SELECT ?object WHERE {?object a nie:InformationElement . FILTER (str(?object) = '%2') } } }";
+
+static const QString SqlGetUrlFromURN = "SELECT ?url {<%1> nie:url ?url}";
+static const QString SqlGetMimeTypeFromURN = "SELECT ?mimetype {<%1> nie:mimeType ?mimetype}";
+
+bool SearchEngine::getAllPhoto(QVector<QStringList> &result)
+{
+ result = ::tracker()->rawSparqlQuery(SqlGetAllPhoto);
+ return TRUE;
+}
+
+bool SearchEngine::getAllPhotoAlbums(QVector<QStringList> &result)
+{
+ result = ::tracker()->rawSparqlQuery(SqlGetAllPhotoAlbums);
+ return TRUE;
+}
+
+bool SearchEngine::getAlbumPhotos(const QString &albumIdentifier, QVector<QStringList> &result)
+{
+ QString sql = QString(SqlGetAlbumPhotos).arg(albumIdentifier);
+ result = ::tracker()->rawSparqlQuery(sql);
+ return TRUE;
+}
+
+bool SearchEngine::createAlbum(const QString &albumIdentifier, const QString &albumTitle, const QStringList &photoFiles)
+{
+ if (photoFiles.size() < 1)
+ return TRUE;
+
+ QString sql = QString(SqlCreateAlbumBegin).arg(albumIdentifier).arg(albumTitle).arg(photoFiles.size());
+
+ int j = 0;
+ for (QStringList::const_iterator i = photoFiles.begin(); i != photoFiles.end(); i++) {
+ QString sqlItem = QString(SqlInsertItem).arg(*i).arg(j++);
+ sql += QString(";") + sqlItem;
+ }
+ sql += SqlCreateAlbumEnd;
+
+ ::tracker()->rawSparqlUpdateQuery(sql);
+ return TRUE;
+}
+
+bool SearchEngine::deleteAlbum(const QString &albumIdentifier)
+{
+ QString sql = QString(SqlRemoveAlbum).arg(albumIdentifier);
+ ::tracker()->rawSparqlUpdateQuery(sql);
+ return TRUE;
+}
+
+bool SearchEngine::setAlbumCover(const QString &albumURN, const QString &coverPath)
+{
+ QString sql = QString(SqlQueryAlbumCoverTag).arg(albumURN);
+ bool needDelete = FALSE;
+
+ QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+
+ for (QVector<QStringList>::iterator i = result.begin(); i != result.end(); i++) {
+ if (!(*i)[1].isEmpty()) {
+ needDelete = TRUE;
+ break;
+ }
+ }
+
+ if (needDelete) {
+ sql = QString(SqlDeleteAlbumCoverTag).arg(albumURN);
+ ::tracker()->rawSparqlUpdateQuery(sql);
+ }
+
+ sql = QString(SqlInsertAlbumCoverTag).arg(coverPath).arg(albumURN);
+ ::tracker()->rawSparqlUpdateQuery(sql);
+
+ return TRUE;
+}
+
+bool SearchEngine::getAlbumCover(const QString &albumURN, QString &coverPath)
+{
+ QString sql = QString(SqlQueryAlbumCoverTag).arg(albumURN);
+
+ QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+
+ coverPath = QString("");
+
+ for (QVector<QStringList>::iterator i = result.begin(); i != result.end(); i++) {
+ if (!(*i)[1].isEmpty()) {
+ coverPath = (*i)[1];
+ break;
+ }
+ }
+
+ return TRUE;
+}
+/*
+bool SearchEngine::getAlbumURN(const QString &albumIdentifier, QString &albumURN)
+{
+ QString sql = QString(SqlGetAlbumURN).arg(albumIdentifier);
+
+ qDebug() << "SearchEngine::getAlbumURN " << sql;
+
+ QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+ if (result.count() > 0)
+ albumURN = result[0][0];
+
+ return TRUE;
+}
+*/
+bool SearchEngine::setObjectTag(const QString &objectURN, const QString &tagIdentifier, const QString &tagInfo)
+{
+ QString sql = QString(SqlInsertObjectTag).arg(tagInfo).arg(tagIdentifier).arg(objectURN);
+
+
+ ::tracker()->rawSparqlUpdateQuery(sql);
+
+ return TRUE;
+}
+
+bool SearchEngine::getObjectTag(const QString &objectURN, const QString &tagIdentifier, QString &tagInfo)
+{
+ QString sql = QString(SqlQueryObjectTag).arg(tagIdentifier).arg(objectURN);
+
+
+ QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+
+ tagInfo = "";
+
+ for (QVector<QStringList>::iterator i = result.begin(); i != result.end(); i++) {
+ if (!(*i)[0].isEmpty()) {
+ tagInfo = (*i)[0];
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+bool SearchEngine::deleteObjectTag(const QString &objectURN, const QString &tagIdentifier)
+{
+ QString sql = QString(SqlDeleteObjectTag).arg(tagIdentifier).arg(objectURN);
+
+
+ ::tracker()->rawSparqlUpdateQuery(sql);
+
+ return TRUE;
+}
+
+QString SearchEngine::getUrl(const QString &objectURN)
+{
+ QString sql = QString(SqlGetUrlFromURN).arg(objectURN);
+ QString url;
+
+
+ QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+ if (result.count() != 0)
+ url = result[0][0];
+ return url;
+}
+
+QString SearchEngine::getMimeType(const QString &objectURN)
+{
+ QString sql = QString(SqlGetMimeTypeFromURN).arg(objectURN);
+ QString mimeType;
+
+
+ QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+ mimeType = result[0][0];
+ return mimeType;
+}
--- liballphoto/searchengine.h
+++ liballphoto/searchengine.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#ifndef SEARCHENGINE_H
+#define SEARCHENGINE_H
+#include <QtCore>
+
+class SearchEngine
+{
+public:
+ static bool getAllPhoto(QVector<QStringList> &result);
+
+ /// @brief get all photo albums from tracker, including nie:title; nie:identifier; nfo:entryCounter
+ static bool getAllPhotoAlbums(QVector<QStringList> &result);
+
+ /// @brief get all photos from specific album, including photo urls, nie:contentCreated
+ static bool getAlbumPhotos(const QString &albumIdentifier, QVector<QStringList> &result);
+
+ /// @brief create an album, photoFiles must contain urn:uuid:xxxxxx
+ static bool createAlbum(const QString &albumIdentifier, const QString &albumTitle, const QStringList &photoFiles);
+
+ /// @brief delete an album
+ static bool deleteAlbum(const QString &albumIdentifier);
+
+ /// @brief set cover for an album
+ static bool setAlbumCover(const QString &albumURN, const QString &coverPath);
+
+ /// @brief get cover for an album
+ static bool getAlbumCover(const QString &albumURN, QString &coverPath);
+
+ /// @brief get album URN from identifier
+// static bool getAlbumURN(const QString &albumIdentifier, QString &albumURN);
+
+ /// @brief set Tag for an object
+ static bool setObjectTag(const QString &objectURN, const QString &tagIdentifier, const QString &tagInfo);
+
+ /// @brief get Tag for an object
+ static bool getObjectTag(const QString &objectURN, const QString &tagIdentifier, QString &tagInfo);
+
+ /// @brief delete Tag for an object
+ static bool deleteObjectTag(const QString &objectURN, const QString &tagIdentifier);
+
+ /// @brief get url from urn
+ static QString getUrl(const QString &objectURN);
+
+ static QString getMimeType(const QString &objectURN);
+
+ static int getAllPhotoUrlIndex;
+// static int getAllPhoto
+};
+#endif
--- liballphoto/test
+++ liballphoto/test
+(directory)
--- liballphoto/test/clickedslot.cpp
+++ liballphoto/test/clickedslot.cpp
+#include <QDebug>
+#include "clickedslot.h"
+
+void Foo::onClicked(const QString &photoURI, const QString &thumbnailPath)
+{
+ qDebug() << "Foo photoURI : " << photoURI << "ThumbnailPath: " << thumbnailPath;
+}
--- liballphoto/test/clickedslot.h
+++ liballphoto/test/clickedslot.h
+#ifndef _CLICKED_SLOTS_H_
+#define _CLICKED_SLOTS_H_
+#include <QObject>
+
+class Foo : public QObject
+{
+ Q_OBJECT
+public slots:
+ void onClicked(const QString &photoURI, const QString &thumbnailURI);
+};
+
+#endif
--- liballphoto/test/main.cpp
+++ liballphoto/test/main.cpp
+/***************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (directui at nokia.com)
+**
+** This file is part of libmeegotouch.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at directui at nokia.com.
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation
+** and appearing in the file LICENSE.LGPL included in the packaging
+** of this file.
+**
+****************************************************************************/
+
+/*
+ * An example of a minimalistic DirectUI application
+ */
+
+#include <MApplication>
+#include <MApplicationWindow>
+#include <MApplicationPage>
+#include <MButton>
+#include <MLayout>
+#include <MLabel>
+#include <MGridLayoutPolicy>
+#include <MTextEdit>
+#include <dynamicphotolist.h>
+#include "clickedslot.h"
+
+
+int main(int argc, char **argv)
+{
+ /* The base class of all DirectUI applications */
+ MApplication app(argc, argv);
+
+ /* The application window is a top-level window that contains
+ the Home and Back/Close framework controls, Navigation bar,
+ View menu and Toolbar components */
+ MApplicationWindow w;
+ w.show();
+
+ /* Pages represent one "view" of an application, into which you
+ can add your application's contents. An application can have
+ any number of pages with transitions between them */
+ MApplicationPage p;
+
+ MButton button("xxx");
+ DynamicPhotoList *photoList = new DynamicPhotoList(NULL, M::Landscape);
+ Foo foo;
+ QObject::connect(photoList, SIGNAL(clicked(const QString &, const QString &)), &foo, SLOT(onClicked(const QString &, const QString &)));
+ p.setCentralWidget(photoList);
+ p.appear();
+
+ /* Let's add a simple push button to our page */
+ /*
+ QGraphicsWidget *container = p.centralWidget();
+ MLayout *layout = new MLayout(p.centralWidget());
+ container->setLayout(layout);
+ MGridLayoutPolicy *policy = new MGridLayoutPolicy(layout);
+ policy->setContentsMargins(0, 0, 0, 0);
+
+ MLabel *label = new MLabel("xxx");
+ label->setMinimumWidth(225);
+ label->setMaximumWidth(225);
+
+ policy->addItem(label, 0, 0);
+
+ MTextEdit *edit = new MTextEdit();
+ edit->setObjectName("xxx");
+ policy->addItem(edit, 0, 1);
+*/
+ return app.exec();
+}
--- liballphoto/test/testallphoto.pro
+++ liballphoto/test/testallphoto.pro
+TEMPLATE = app
+TARGET = testallphoto
+CONFIG += meegotouch
+LIBS += -lallphotos
+
+# Input
+SOURCES += main.cpp clickedslot.cpp
+
+HEADERS += clickedslot.h
+
+theme.files = themes/*
+theme.path = /usr/share/themes/base/meegotouch/$$TARGET
+theme.CONFIG += no_check_exist
+
+INSTALLS += theme
--- liballphoto/test/themes
+++ liballphoto/test/themes
+(directory)
--- liballphoto/test/themes/style
+++ liballphoto/test/themes/style
+(directory)
--- liballphoto/test/themes/style/testallphoto.css
+++ liballphoto/test/themes/style/testallphoto.css
+
+#thumbnailList {
+ minimum-size: 100% 100%;
+ maximum-size: 100% 100%;
+ preferred-size: 100% 100%; /*seems not working here */
+ background-color: #dadcd9;
+
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+
+ padding-left: 0;
+ padding-top: 0;
+ padding-right: 0;
+ padding-bottom: 0;
+}
+
+ at const THUMBNAIL_CELL_SIZE: 108px;
+ at const THUMBNAIL_CELL_SIZE_H: 108px;
+
+ at const THUMBNAIL_SELECTED_CELL_SIZE: 88px;
+ at const THUMBNAIL_SELECTED_CELL_SIZE_H: 88px;
+
+ at const THUMBNAIL_CELL_SIZE_PORT: 96px;
+ at const THUMBNAIL_CELL_SIZE_H_PORT: 96px;
+#photoThumbnail_Landscape {
+ background-image:;
+
+ background-image-center :;
+
+/* background-image-single : "photo_thumb_frame_Large"; */
+ background-opacity: 1.0;
+
+ minimum-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE_H;
+ preferred-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE_H;
+ maximum-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE_H;
+
+ image-object-name: "PhotoThumbnailImage";
+ padding-left: 0;
+ padding-top: 0;
+ padding-right: 0;
+ padding-bottom: 0px;
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+
+
+
+}
+
+#photoThumbnail_Landscape:selected {
+ background-image:;
+
+ background-image-center :;
+
+/* background-image-single : "photo_thumb_frame_Large"; */
+ background-opacity: 1.0;
+
+ minimum-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE_H;
+ preferred-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE_H;
+ maximum-size: $THUMBNAIL_CELL_SIZE $THUMBNAIL_CELL_SIZE_H;
+
+ image-object-name: "PhotoThumbnailImageSelected";
+ padding-left: 10px;
+ padding-top: 10px;
+ padding-right: 10px;
+ padding-bottom: 10px;
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+
+#photoThumbnail_Portrait {
+ background-image:;
+
+ background-image-center :;
+
+/* background-image-single : "photo_thumb_frame_Large"; */
+ background-opacity: 1.0;
+
+ minimum-size: $THUMBNAIL_CELL_SIZE_PORT $THUMBNAIL_CELL_SIZE_H_PORT;
+ preferred-size: $THUMBNAIL_CELL_SIZE_PORT $THUMBNAIL_CELL_SIZE_H_PORT;
+ maximum-size: $THUMBNAIL_CELL_SIZE_PORT $THUMBNAIL_CELL_SIZE_H_PORT;
+
+ image-object-name: "PhotoThumbnailImage";
+ padding-left: 0;
+ padding-top: 0;
+ padding-right: 0;
+ padding-bottom: 0px;
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+
+
+
+}
+
+#photoThumbnail_Portrait:selected {
+ background-image:;
+
+ background-image-center :;
+
+/* background-image-single : "photo_thumb_frame_Large"; */
+ background-opacity: 1.0;
+
+ minimum-size: $THUMBNAIL_CELL_SIZE_PORT $THUMBNAIL_CELL_SIZE_H_PORT;
+ preferred-size: $THUMBNAIL_CELL_SIZE_PORT $THUMBNAIL_CELL_SIZE_H_PORT;
+ maximum-size: $THUMBNAIL_CELL_SIZE_PORT $THUMBNAIL_CELL_SIZE_H_PORT;
+
+ image-object-name: "PhotoThumbnailImageSelected";
+ padding-left: 0;
+ padding-top: 0;
+ padding-right: 0;
+ padding-bottom: 0px;
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+
+
+
+}
+
+/*
+#photoThumbnail:pressed {
+ background-image : "duilist-singlecolumn-center-background-pressed" 8px 8px 8px 8px;
+
+ background-image-top-left : "duilist-topleft-background-pressed" 8px 8px 8px 8px;
+ background-image-top : "duilist-top-background-pressed" 8px 8px 8px 8px;
+ background-image-top-right : "duilist-topright-background-pressed" 8px 8px 8px 8px;
+ background-image-left : "duilist-left-background-pressed" 8px 8px 8px 8px;
+ background-image-center : "duilist-center-background-pressed" 8px 8px 8px 8px;
+ background-image-right : "duilist-right-background-pressed" 8px 8px 8px 8px;
+ background-image-bottom-left : "duilist-bottomleft-background-pressed" 8px 8px 8px 8px;
+ background-image-bottom : "duilist-bottom-background-pressed" 8px 8px 8px 8px;
+ background-image-bottom-right : "duilist-bottomright-background-pressed" 8px 8px 8px 8px;
+
+ background-image-single : "duilist-single-background-pressed" 8px 8px 8px 8px;
+
+ background-image-singlerow-left : "duilist-singlerow-left-background-pressed" 8px 8px 8px 8px;
+ background-image-singlerow-center : "duilist-singlerow-center-background-pressed" 8px 8px 8px 8px;
+ background-image-singlerow-right : "duilist-singlerow-right-background-pressed" 8px 8px 8px 8px;
+
+ background-image-singlecolumn-top : "duilist-singlecolumn-top-background-pressed" 8px 8px 8px 8px;
+ background-image-singlecolumn-center : "duilist-singlecolumn-center-background-pressed" 8px 8px 8px 8px;
+ background-image-singlecolumn-bottom : "duilist-singlecolumn-bottom-background-pressed" 8px 8px 8px 8px;
+
+ background-color: #212121;
+ background-opacity: 1.0;
+ image-object-name: "PhotoThumbnailImage";
+}
+ */
+
+ at const THUMBNAIL_SIZE: 108px;
+ at const THUMBNAIL_SELECTED_SIZE: 88px;
+ at const THUMBNAIL_SIZE_PORT: 96px;
+ at const THUMBNAIL_SELECTED_SIZE_PORT: 76px;
+#PhotoThumbnailImage.Landscape {
+ /* inherited from DuiWidgetStyle */
+ minimum-size: $THUMBNAIL_SIZE $THUMBNAIL_SIZE;
+ preferred-size: $THUMBNAIL_SIZE $THUMBNAIL_SIZE;
+ maximum-size: $THUMBNAIL_SIZE $THUMBNAIL_SIZE;
+
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-left: 0px;
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-bottom: 0;
+
+
+
+}
+
+#PhotoThumbnailImageSelected.Landscape {
+ /* inherited from DuiWidgetStyle */
+ minimum-size: $THUMBNAIL_SELECTED_SIZE $THUMBNAIL_SELECTED_SIZE;
+ preferred-size: $THUMBNAIL_SELECTED_SIZE $THUMBNAIL_SELECTED_SIZE;
+ maximum-size: $THUMBNAIL_SELECTED_SIZE $THUMBNAIL_SELECTED_SIZE;
+
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-left: 10px;
+ padding-top: 10px;
+ padding-right: 10px;
+ padding-bottom: 10px;
+}
+
+#PhotoThumbnailImage.Portrait {
+ /* inherited from DuiWidgetStyle */
+ minimum-size: $THUMBNAIL_SIZE_PORT $THUMBNAIL_SIZE_PORT;
+ preferred-size: $THUMBNAIL_SIZE_PORT $THUMBNAIL_SIZE_PORT;
+ maximum-size: $THUMBNAIL_SIZE_PORT $THUMBNAIL_SIZE_PORT;
+ padding-left: 0px;
+ padding-top: 0px;
+ padding-right: 0px;
+ padding-bottom: 0;
+
+
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+#PhotoThumbnailImageSelected.Portrait {
+ /* inherited from DuiWidgetStyle */
+ minimum-size: $THUMBNAIL_SELECTED_SIZE_PORT $THUMBNAIL_SELECTED_SIZE_PORT;
+ preferred-size: $THUMBNAIL_SELECTED_SIZE_PORT $THUMBNAIL_SELECTED_SIZE_PORT;
+ maximum-size: $THUMBNAIL_SELECTED_SIZE_PORT $THUMBNAIL_SELECTED_SIZE_PORT;
+ padding-left: 10px;
+ padding-top: 10px;
+ padding-right: 10px;
+ padding-bottom: 10px;
+
+
+ margin-left: 0;
+ margin-right: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+#loadingSpinner {
+ minimum-size: 60px 60px;
+ preferred-size: 60px 60px;
+ maximum-size: 60px 60px;
+
+ margin-left: 24px;
+ margin-top: 24px;
+ speed: 10;
+ active-element-count: 1;
+ element-size: 10px;
+ element-distance: 0.3;
+
+}
--- liballphoto/thumbnailer.cpp
+++ liballphoto/thumbnailer.cpp
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+
+#include "thumbnailer.h"
+
+const QString Thumbnailer::service = "org.freedesktop.thumbnails.Thumbnailer1";
+const QString Thumbnailer::path = "/org/freedesktop/thumbnails/Thumbnailer1";
+const char *Thumbnailer::interface = "org.freedesktop.thumbnails.Thumbnailer1";
+
+const QString Thumbnailer::default_flavor = "normal";
+const QString Thumbnailer::default_schedular = "foreground";
+
+Thumbnailer *Thumbnailer::thumbnailerInstance = NULL;
+
+Thumbnailer *Thumbnailer::instance()
+{
+ if (thumbnailerInstance)
+ return thumbnailerInstance;
+ else {
+ thumbnailerInstance = new Thumbnailer(QDBusConnection::sessionBus(), NULL);
+ return thumbnailerInstance;
+ }
+}
+
+void Thumbnailer::emitReadySignal(const unsigned int &handle, const QStringList &urls)
+{
+ emit ready(handle, urls);
+}
+
+void Thumbnailer::emitErrorSignal(const unsigned int &handle, const QStringList &urls, const int &errorCode, const QString &message)
+{
+ qDebug() << "ERROR SIGNAL " << handle << urls << errorCode << message;
+ emit error(handle, urls, errorCode, message);
+}
+
+Thumbnailer::Thumbnailer(const QDBusConnection &connection, QObject *parent) :
+ QDBusAbstractInterface(service, path, interface, connection, parent)
+{
+ QDBusConnection::sessionBus().connect(service, path, interface,
+ "Ready", this, SLOT(emitReadySignal(const unsigned int, const QStringList)));
+ QDBusConnection::sessionBus().connect(service, path, interface,
+ "Error", this, SLOT(emitErrorSignal(const unsigned int, const QStringList, \
+ const int, const QString )));
+}
+
+Thumbnailer::~Thumbnailer()
+{
+}
--- liballphoto/thumbnailer.h
+++ liballphoto/thumbnailer.h
+/*
+ * Meego-handset-photos is a photo viewer.
+ * Copyright (C) 2010, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef THUMBNAILER_H
+#define THUMBNAILER_H
+
+#include <QtCore/QtCore>
+#include <QtCore/QObject>
+#include <QtDBus/QtDBus>
+
+/// @class Thumbnailer
+/// @brief Generates thumbnail images.
+///
+/// The Thumbnailer class:
+/// - generates thumbnail images by using tumbler service.
+///
+/// The class is a singleton. There should only ever be one instance
+/// running per application.
+///
+/// Thumbnails are generated asynchronously. A signal ready will be emitted
+/// after thumbnail is stored on disk.
+///
+/// The thumbnail size is controlled by tumbler service.
+
+
+class Thumbnailer: public QDBusAbstractInterface
+{
+ Q_OBJECT
+public:
+ /// @brief Return the instance of the thumbnailer singleton.
+ /// @return Thumbnailer Returns the single instance.
+ static Thumbnailer *instance();
+
+ /// @brief Destructor
+ ~Thumbnailer();
+
+private:
+ // Constructor is private because this is a singleton.
+ // Construct it using the instance() method.
+ Thumbnailer(const QDBusConnection &connection, QObject *parent = 0);
+
+ /// @brief Tumbler DBUS service name
+ const static QString service;
+
+ /// @brief Tumbler DBUS service path
+ const static QString path;
+
+ /// @brief Tumbler DBUS service interface
+ const static char* interface;
+
+ /// @brief Tumbler default flavor
+ const static QString default_flavor;
+
+ /// @brief Tumbler default schedular
+ const static QString default_schedular;
+
+ static Thumbnailer *thumbnailerInstance;
+
+public Q_SLOTS:
+ /// @brief Request thumbnail using default flavor and schedular
+ /// @param filePath const QString& The path of the video file
+ /// @param mimetype const QString& The mime type of the video file
+ /// @return QDBusPendingCall
+ inline QDBusPendingCall requestThumbnail(const QString &filePath, const QString &mimetype) {
+ QStringList paths;
+ QStringList mimetypes;
+ quint32 handle = 0;
+ paths << filePath;
+ mimetypes << mimetype;
+
+ return asyncCall(QLatin1String("Queue"), paths, mimetypes,
+ default_flavor, default_schedular,
+ handle);
+ }
+
+ /// @brief Request thumbnail using specified flavor and schedular
+ /// @param filePath const QString& The path of the video file
+ /// @param mimetype const QString& The mime type of the video file
+ /// @param flavor const QString& Specified flavor
+ /// @param scheduler const QString& Specified scheduler
+ /// @param handle quint32 Handler to dequeue from tumbler service
+ /// @return QDBusPendingCall
+ inline QDBusPendingCall requestThumbnail(const QString &filePath, const QString &mimetype,
+ const QString &flavor, const QString &scheduler,
+ quint32 handle) {
+ QStringList paths;
+ QStringList mimetypes;
+ paths << filePath;
+ mimetypes << mimetype;
+
+ return asyncCall(QLatin1String("Queue"), paths, mimetypes,
+ flavor, scheduler,
+ handle);
+ }
+
+ /// @brief Request thumbnails for a bunch of video files using specified flavor and schedular
+ /// @param filePath const QStringList& The paths of the video files
+ /// @param mimetype const QStringList& The mime types of the video files
+ /// @param flavor const QString& Specified flavor
+ /// @param scheduler const QString& Specified scheduler
+ /// @param handle quint32 Handler to dequeue from tumbler service
+ /// @return QDBusPendingCall
+ inline QDBusPendingCall requestThumbnail(const QStringList &paths, const QStringList &mimetypes,
+ const QString &flavor, const QString &scheduler,
+ quint32 handle) {
+ return asyncCall(QLatin1String("Queue"), paths, mimetypes,
+ flavor, scheduler,
+ handle);
+ }
+
+ /// @brief Emit ready signals when DBUS signal Ready is received
+ /// @param handle const unsigned int Handler that is ready
+ /// @param urls const QStringList& Urls of video files that thumbnail is ready
+ void emitReadySignal(const unsigned int &handle, const QStringList &urls);
+
+ void emitErrorSignal(const unsigned int &handle, const QStringList &urls, const int &errorCode, const QString &message);
+
+signals:
+ /// @brief ready signals when thumbnails are ready
+ /// @param handle const unsigned int Handler that is ready
+ /// @param urls const QStringList& Urls of video files that thumbnail is ready
+ void ready(const unsigned int &handle, const QStringList &urls);
+
+ void error(const unsigned int &handle, const QStringList &urls, const int &errorCode, const QString &message);
+};
+#endif
--- makedist
+++ makedist
@@ -34,7 +34,7 @@
# Generate the base package release tar ball
# NOTE: Becuase I used a git attribute that ignores the meego theme dir
# this archive will not include it... that's intentional!
-git archive --prefix=${BASE_PREFIX} ${TAG} | bzip2 -c -- > ${BASE_ARCHIVE} && {
+git archive --prefix=${BASE_PREFIX} ${TAG} base/ themes.pro | bzip2 -c -- > ${BASE_ARCHIVE} && {
echo "Created: ${BASE_ARCHIVE}"
} || {
echo "Creation of release archive ${BASE_ARCHIVE} failed. Reason unknown."
--- src/album-generator/albumsmerger.cpp
+++ src/album-generator/albumsmerger.cpp
@@ -47,27 +47,30 @@
return;
QString albumID = createDateAlbumID(dateRange, subid);
- SearchEngine::createAlbum(albumID, albumID, photos);
+ //SearchEngine::createAlbum(albumID, albumID, photos);
+ trackerTasks << TrackerTask(albumID, TrackerTask::CreateAlbum, photos);
QString albumUrn = albumID;
- MPSettings settings;
// settings.setAlbumName(albumUrn, albumName);
for(int i = 0; i < photos.size(); i++) {
- settings.setPhotoAlbumUrn(photos.at(i), albumUrn);
+ AppWindow::instance()->settings.setPhotoAlbumUrn(photos.at(i), albumUrn);
}
- QString urlString = settings.getPhotoUri(photos[0]);
- settings.setAlbumCover(albumUrn, urlString);
- settings.setAlbumDate(albumUrn, dateRange.getStartDate().toString(), dateRange.getEndDate().toString());
- settings.setAlbumID(albumUrn, albumID);
+ QStringList photoInfo = GetAllPhotosWorker::instance()->getPhotoInfo(photos[0]);
+ QString urlString = SearchEngine::getPhotoUri(photoInfo);
+ AppWindow::instance()->settings.setAlbumCover(albumUrn, urlString);
+ AppWindow::instance()->settings.setAlbumPhotoNum(albumUrn, photos.count());
+ AppWindow::instance()->settings.setAlbumDate(albumUrn, dateRange.getStartDate().toString(), dateRange.getEndDate().toString());
+ AppWindow::instance()->settings.setAlbumID(albumUrn, albumID);
}
void AlbumsMerger::deleteOneAlbum(const QString &id)
{
- MPSettings settings;
QString albumID = id;
QString albumUrn = albumID;
- SearchEngine::deleteAlbum(albumID);
- settings.remove(albumUrn);
+ //SearchEngine::deleteAlbum(albumID);
+ trackerTasks << TrackerTask(albumID, TrackerTask::DeleteAlbum);
+ AppWindow::instance()->settings.remove(albumUrn);
+ AppWindow::instance()->settings.removeAlbum(albumUrn);
}
void AlbumsMerger::deleteAllAlbums()
@@ -110,11 +113,14 @@
dateOnlyMerge(&dateOnlyPhotos);
locationOnlyMerge(&locationPhotos);
emit albumsChanged();
+ QTimer::singleShot(0, this, SLOT(doTrackerTasks()));
return true;
}
bool AlbumsMerger::merge(QVector<QStringList> *photos)
{
+ QTime t;
+ t.start();
deleteAllAlbums();
return mergeOnly(photos);
}
@@ -124,14 +130,14 @@
if (photos->count() <= 0)
return false;
- MPSettings settings;
- qDebug() << "12345 dateOnlyMerge photos count:" << photos->count();
-
for (QVector<QStringList>::iterator i = photos->begin(); i != photos->end(); i++) {
QString urn = (*i)[2];
+ QTime t;
+ t.start();
DateRange &dateRange = getDateRange(urn);
if (!dateAlbumsHash[dateRange].contains(urn)) {
+ t.start();
dateAlbumsHash[dateRange] << urn;
QStringList &photoInAlbums = dateAlbumsHash[dateRange];
@@ -191,21 +197,24 @@
for (int j = 0; j < numSplitAlbums; j++) {
QString albumID = createLocationAlbumID(locationVec[j]);
deleteOneAlbum(albumID);
- SearchEngine::createAlbum(albumID, albumID, photosVec[j]);
+ //SearchEngine::createAlbum(albumID, albumID, photosVec[j]);
+ trackerTasks << TrackerTask(albumID, TrackerTask::CreateAlbum, photosVec[j]);
QString albumUrn = albumID;
- MPSettings settings;
for(int i = 0; i < photosVec[j].size(); i++) {
- settings.setPhotoAlbumUrn(photosVec[j].at(i), albumUrn);
+ AppWindow::instance()->settings.setPhotoAlbumUrn(photosVec[j].at(i), albumUrn);
}
- QString urlString = settings.getPhotoUri(photosVec[j][0]);
+ QStringList photoInfo = GetAllPhotosWorker::instance()->getPhotoInfo(photosVec[j][0]);
+ QString urlString = SearchEngine::getPhotoUri(photoInfo);
+
// QUrl coverUrl(urlString);
- settings.setAlbumCover(albumUrn, urlString);
- settings.setAlbumDate(albumUrn, GetAllPhotosWorker::getPhotoDate(photosVec[j][0]).toString(),
+ AppWindow::instance()->settings.setAlbumCover(albumUrn, urlString);
+ AppWindow::instance()->settings.setAlbumDate(albumUrn, GetAllPhotosWorker::getPhotoDate(photosVec[j][0]).toString(),
GetAllPhotosWorker::getPhotoDate(photosVec[j].last()).toString());
- settings.setAlbumID(albumUrn, albumID);
- settings.setAlbumLocation(albumUrn, locationVec[j]);
+ AppWindow::instance()->settings.setAlbumID(albumUrn, albumID);
+ AppWindow::instance()->settings.setAlbumPhotoNum(albumUrn, photosVec[j].count());
+ AppWindow::instance()->settings.setAlbumLocation(albumUrn, locationVec[j]);
}
emit albumsChanged();
}
@@ -213,16 +222,19 @@
bool AlbumsMerger::locationOnlyMerge(QVector<QStringList> *photos)
{
- MPSettings settings;
-
for (QVector<QStringList>::iterator i = photos->begin(); i != photos->end(); i++) {
- QString urn = (*i)[2];
- QString location = settings.getPhotoLocation(urn);
+ QString urn = SearchEngine::getPhotoUrn(*i);
+ QTime t;
+ t.start();
+ QString location = AppWindow::instance()->settings.getPhotoLocation(urn);
if (!location.isEmpty()) {
+ QTime t;
+ t.start();
addOneLocationPhotoIntoAlbum(urn, location);
} else {
- QString uri = settings.getPhotoUri(urn);
+ QStringList photoInfo = GetAllPhotosWorker::instance()->getPhotoInfo(urn);
+ QString uri = SearchEngine::getPhotoUri(photoInfo);
QString localPath = QUrl(uri).toLocalFile();
ExifUtils exif(localPath);
float lat, lon;
@@ -237,11 +249,11 @@
bool AlbumsMerger::isLocationPhoto(const QString &photoUrn)
{
- MPSettings settings;
- QString location = settings.getPhotoLocation(photoUrn);
+ QString location = AppWindow::instance()->settings.getPhotoLocation(photoUrn);
bool res = false;
if (location.isEmpty()) {
- QString uri = settings.getPhotoUri(photoUrn);
+ QStringList photoInfo = GetAllPhotosWorker::instance()->getPhotoInfo(photoUrn);
+ QString uri = SearchEngine::getPhotoUri(photoInfo);
QString localPath = QUrl(uri).toLocalFile();
ExifUtils exif(localPath);
float dummy;
@@ -267,32 +279,31 @@
void AlbumsMerger::onTranslated(const QVariant &userdata, const QString &location)
{
- MPSettings settings;
QString urn = userdata.toString();
- settings.setPhotoLocation(urn, location);
+ AppWindow::instance()->settings.setPhotoLocation(urn, location);
addOneLocationPhotoIntoAlbum(urn,location);
+ QTimer::singleShot(0, this, SLOT(doTrackerTasks()));
}
void AlbumsMerger::handlePhotoAdded(const QStringList &urns)
{
QVector<QStringList> x(urns.count());
- MPSettings settings;
+/* MPSettings settings;
for (int i = 0; i < urns.count(); i++) {
x[i] << "" << "" << urns[i];
settings.setPhotoUri(urns[i], SearchEngine::getUrl(urns[i]));
- }
+ } */
mergeOnly(&x);
}
void AlbumsMerger::handlePhotoRemoved(const QStringList &urns)
{
- MPSettings settings;
QString location;
bool shouldUpdate = false;
for (int i = 0; i < urns.count(); i++) {
if (!AppWindow::instance()->photoRemoveBlacklist.contains(urns[i])) {
- location = settings.getPhotoLocation(urns[i]);
+ location = AppWindow::instance()->settings.getPhotoLocation(urns[i]);
if (!location.isEmpty()) {
locationAlbumsHash[location].removeAll(urns[i]);
if (locationAlbumsHash[location].count() == 0) {
@@ -302,7 +313,7 @@
}
} else {
// the photo belongs to a date only location
- QDate date = QDate::fromString(settings.getPhotoDate(urns[i]));
+ QDate date = GetAllPhotosWorker::instance()->getPhotoDate(urns[i]);
DateRange range(date, date);
if (dateRanges.contains(range)) {
dateAlbumsHash[range].removeAll(urns[i]);
@@ -321,8 +332,34 @@
shouldUpdate = true;
} else {
}
- settings.remove(urns[i]);
+ AppWindow::instance()->settings.remove(urns[i]);
}
if (shouldUpdate)
emit albumsChanged();
+ QTimer::singleShot(0, this, SLOT(doTrackerTasks()));
+}
+
+void AlbumsMerger::doTrackerTasks()
+{
+ while (!trackerTasks.isEmpty()) {
+ TrackerTask task = trackerTasks.takeFirst();
+ task.run();
+ }
+}
+
+
+TrackerTask::TrackerTask(const QString &albumID, TrackerTask::Command cmd, const QStringList &photos) : albumID(albumID), command(cmd), photos(photos)
+{
+}
+
+void TrackerTask::run()
+{
+ switch (command) {
+ case TrackerTask::DeleteAlbum:
+ SearchEngine::deleteAlbum(albumID);
+ break;
+ case TrackerTask::CreateAlbum:
+ SearchEngine::createAlbum(albumID, albumID, photos);
+ break;
+ }
}
--- src/album-generator/albumsmerger.h
+++ src/album-generator/albumsmerger.h
@@ -15,6 +15,7 @@
#include <QDate>
#include <QHash>
#include <QVector>
+#include <QStringList>
#include "reversegeocoder.h"
#define MaxAlbums 20
@@ -56,6 +57,22 @@
QDate end;
};
+class TrackerTask
+{
+public:
+ enum Command {
+ DeleteAlbum,
+ CreateAlbum
+ };
+ TrackerTask(const QString &albumID, TrackerTask::Command cmd, const QStringList &photos = QStringList());
+
+ void run();
+private:
+ Command command;
+ QString albumID;
+ QStringList photos;
+};
+
class AlbumsMerger : public QObject, public ReverseGeocoderAction
{
Q_OBJECT
@@ -98,10 +115,13 @@
ReverseGeocoder *geocoder;
+ QList<TrackerTask> trackerTasks;
+
private slots:
void handlePhotoAdded(const QStringList &);
void handlePhotoRemoved(const QStringList &);
+ void doTrackerTasks();
};
--- src/album-generator/albumsmergethread.cpp
+++ src/album-generator/albumsmergethread.cpp
@@ -20,7 +20,6 @@
void AlbumsMergeThread::run()
{
- qDebug() << "12345 AlbumsMergeThread starts\n";
QEventLoop loop;
QVector<QStringList> *photos = NULL;
GetAllPhotosWorker *worker = GetAllPhotosWorker::instance();
@@ -32,7 +31,10 @@
AlbumsMerger merger;
if (photos) {
QObject::connect(&merger, SIGNAL(albumsChanged()), this, SLOT(onAlbumsChanged()));
+ QTime t;
+ t.start();
merger.merge(photos);
+ qDebug() << "12345 merge elaped:" << t.elapsed();
}
loop.exec();
}
--- src/appwindow.cpp
+++ src/appwindow.cpp
@@ -568,7 +568,6 @@
topToolbarLayout->insertItem(1, albumInfoFreestyleContainer);
albumInfoFreestyleContainer->show();
- MPSettings settings;
currentAlbumName = settings.getPhotoAlbumName(currentPhotoUrn);
currentAlbumUrn = settings.getPhotoAlbumUrn(currentPhotoUrn);
@@ -735,7 +734,6 @@
void AppWindow::showAlbum(QString &urn)
{
- MPSettings settings;
QString displayString = settings.getAlbumName(urn);
albumInfoButtonInInfoContainer->setText(displayString);
photoInfoButtonInInfoContainer->hide();
@@ -783,7 +781,8 @@
//viewport->setObjectName("viewportAlbum");
currentPhotoList = photosInOneAlbumList;
- currentPage()->disappear();
+ if (currentPage())
+ currentPage()->disappear();
allPhotosPage->appear();
allPhotosPage->setEscapeMode(MApplicationPageModel::EscapeManualBack);
autoHideTimer.stop();
@@ -1025,10 +1024,12 @@
MPListModel *orgModel = dynamic_cast<MPListModel *>(photoList->itemModel());
searchPhotoProxyModel = new MPProxyListModel(MPAbstractListModelOps::Photo);
searchPhotoProxyModel->setSourceModel(orgModel);
+ searchPhotoProxyModel->setDynamicSortFilter(true);
MPListModel *orgAlbumModel = dynamic_cast<MPListModel *>(albumList->itemModel());
searchAlbumProxyModel = new MPProxyListModel(MPAbstractListModelOps::Album);
searchAlbumProxyModel->setSourceModel(orgAlbumModel);
+ searchAlbumProxyModel->setDynamicSortFilter(true);
SearchResults *searchResults = new SearchResults(searchPhotoProxyModel, searchAlbumProxyModel);
searchResultsPage->setCentralWidget(searchResults);
--- src/appwindow.h
+++ src/appwindow.h
@@ -73,6 +73,7 @@
DynamicPhotoList *photosInOneAlbumList;
DynamicMList* currentPhotoList;
QStringList photoRemoveBlacklist; //don't handle if a urn is removed in this list
+ MPSettings settings;
void showOverlay(void);
--- src/dynamicalbumlist.cpp
+++ src/dynamicalbumlist.cpp
@@ -84,8 +84,7 @@
MContentItemEx *itemEx = dynamic_cast<MContentItemEx *>(sender()->parent());
QVariant data = (itemEx->index).data(Qt::DisplayRole);
MPListItem *item = static_cast<MPListItem *>(data.value<void *>());
- MPSettings settings;
- QString albumID = settings.getAlbumID(item->urn);
+ QString albumID = AppWindow::instance()->settings.getAlbumID(item->urn);
QVector<QStringList> result;
SearchEngine::getAlbumPhotos(albumID, result);
--- src/getallphotosworker.cpp
+++ src/getallphotosworker.cpp
@@ -15,59 +15,108 @@
#include "exifutils.h"
GetAllPhotosWorker *GetAllPhotosWorker::worker_instance = NULL;
+QVector<QStringList> GetAllPhotosWorker::allPhotos;
+QHash<QString, QStringList> GetAllPhotosWorker::allPhotosMetaHash;
void GetAllPhotosWorker::storePhotoMetaInfo(QVector<QStringList> &allPhotos)
{
for (int i = 0; i < allPhotos.count(); i++) {
- QString photoUrn = allPhotos[i][2];
- QString photoUri = allPhotos[i][0];
- MPSettings settings;
- settings.setPhotoUri(photoUrn, photoUri);
- QString photoLastModifiedDate = allPhotos[i][3];
- QString dateOnly = QDate::fromString(((photoLastModifiedDate.split("T"))[0]), "yyyy-MM-dd").toString();
- settings.setPhotoLastModifiedDate(photoUrn, dateOnly);
+ QString photoUrn = SearchEngine::getPhotoUrn(allPhotos[i]);
+ allPhotosMetaHash.insert(photoUrn, allPhotos[i]);
}
}
+void GetAllPhotosWorker::addOnePhoto(const QStringList &photo)
+{
+ mutexForAllPhotos.lock();
+ allPhotos << photo;
+ allPhotosMetaHash.insert(SearchEngine::getPhotoUrn(photo), photo);
+ sortByDate(allPhotos);
+ mutexForAllPhotos.unlock();
+}
+
+QStringList GetAllPhotosWorker::getPhotoInfo(const QString &photoUrn)
+{
+ mutexForAllPhotos.lock();
+ QStringList ret = allPhotosMetaHash.value(photoUrn);
+ mutexForAllPhotos.unlock();
+ return ret;
+}
+
+void GetAllPhotosWorker::removeOnePhoto(const QString photoUrn)
+{
+ mutexForAllPhotos.lock();
+ QStringList photoInfo = allPhotosMetaHash.value(photoUrn);
+ if (photoInfo.count() > 0) {
+ allPhotos.remove(allPhotos.indexOf(photoInfo));
+ allPhotosMetaHash.remove(photoUrn);
+ }
+ mutexForAllPhotos.unlock();
+}
+
void GetAllPhotosWorker::run()
{
+ QTime t2;
+ t2.start();
SearchEngine::getAllPhoto(allPhotos);
+ qDebug() << "12345: getAllPhotos elapsed:" << t2.elapsed();
+ QTime t;
+ t.start();
storePhotoMetaInfo(allPhotos);
+ qDebug() << "12345: storePhotoMetaInfo elapsed:" << t.elapsed();
+ t.start();
sortByDate(allPhotos);
+ qDebug() << "12345: sortByDate all photos t:" << t.elapsed();
mutex.lock();
isDone = true;
mutex.unlock();
cond.wakeAll();
- qDebug() << "12345 GetAllPhotosWorker thread done";
}
QDate GetAllPhotosWorker::getPhotoDate(const QString &photoUrn)
{
- MPSettings settings;
- QString dateString = settings.getPhotoDate(photoUrn);
- if (dateString.isEmpty()) {
- QString uri = settings.getPhotoUri(photoUrn);
- QString path = QUrl(uri).toLocalFile();
- QDate date;
- bool result = ExifUtils(path).getDate(date);
- if (!result) {
- date = QFileInfo(path).lastModified().date();
- }
- dateString = date.toString();
+ QStringList photoMeta = allPhotosMetaHash.value(photoUrn);
+ return getPhotoDate(photoMeta);
+}
+
+QDate GetAllPhotosWorker::extractLastModifiedDate(const QStringList &a)
+{
+ return QDate::fromString(((a[3].split("T"))[0]), "yyyy-MM-dd");
+}
- settings.setPhotoDate(photoUrn, dateString);
+QDate GetAllPhotosWorker::getPhotoDate(const QStringList &a)
+{
+ QString dateString = SearchEngine::getPhotoContentCreated(a);
+ if (dateString.isEmpty())
+ dateString = SearchEngine::getPhotoLastModified(a);
+
+ return QDate::fromString(((dateString.split("T"))[0]), "yyyy-MM-dd");
+ /*(
+ QDate date;
+ QString uri = a[0];
+ QString path = QUrl(uri).toLocalFile();
+ bool result = ExifUtils(path).getDate(date);
+ if (!result) {
+ date = extractLastModifiedDate(a);
}
- return QDate::fromString(dateString);
+ return date;
+ */
}
bool GetAllPhotosWorker::compare(const QStringList &a, const QStringList &b)
{
- return compare2(a[2], b[2]);
+ QDate dateOnlyA = getPhotoDate(a);
+ QDate dateOnlyB = getPhotoDate(b);
+ return dateOnlyA > dateOnlyB;
}
bool GetAllPhotosWorker::compare2(const QString &a, const QString &b)
{
+ QTime t;
+ static int i = 0;
+ t.start();
bool res = getPhotoDate(a) > getPhotoDate(b);
+ qDebug() << "12345 compare2 no: " << i++ << " time; " << t.elapsed();
return res;
}
--- src/getallphotosworker.h
+++ src/getallphotosworker.h
@@ -16,7 +16,8 @@
class GetAllPhotosWorker : public QThread {
public:
- QVector<QStringList> allPhotos;
+ static QVector<QStringList> allPhotos;
+ static QHash<QString, QStringList> allPhotosMetaHash;
inline void waitTillDone() {
mutex.lock();
while (!isDone) {
@@ -34,19 +35,25 @@
// static QString photoUrnToPath(const QString &photoUrn);
static QDate getPhotoDate(const QString &photoUrn);
+ static QDate getPhotoDate(const QStringList &a);
static GetAllPhotosWorker *instance();
+ void addOnePhoto(const QStringList &photo);
+ void removeOnePhoto(const QString photoUrn);
+ QStringList getPhotoInfo(const QString &photoUrn);
private:
static bool compare(const QStringList &a, const QStringList &b);
static bool compare2(const QString &a, const QString &b);
static GetAllPhotosWorker *worker_instance;
+ static QDate extractLastModifiedDate(const QStringList &a);
void storePhotoMetaInfo(QVector<QStringList> &allPhotos);
bool isDone;
QWaitCondition cond;
QMutex mutex;
+ QMutex mutexForAllPhotos;
};
#endif // UTILS_H
--- src/mplistmodel.cpp
+++ src/mplistmodel.cpp
@@ -21,6 +21,7 @@
#include "trackerlistener.h"
#include "mpsettings.h"
#include "getallphotosworker.h"
+#include "appwindow.h"
QHash<QString, QString> MPListModel::urnToPathHashMap;
@@ -65,7 +66,6 @@
if (getDataType() == MPAbstractListModelOps::Album) {
// create a album model
- MPSettings settings;
if (albumUrn == "") {
QVector<QStringList> *result = new QVector<QStringList>();
SearchEngine::getAllPhotoAlbums(*result);
@@ -74,7 +74,7 @@
MPListItem *t = new MPListItem((*i)[1], ((*i)[2]).toInt(), (*i)[0]);
t->thumbnail = pDefaultThumbnail;
t->urn = (*i)[0]; //intended, use ID as urn. albumID == albumURN
- t->photoURI = settings.getAlbumCover(t->urn);
+ t->photoURI = AppWindow::instance()->settings.getAlbumCover(t->urn);
listItemsVector << t;
pathToIndexHashMap.insert(QUrl::fromEncoded(t->photoURI.toAscii()).toLocalFile(), indexValue++);
@@ -101,8 +101,7 @@
}
} else {
- MPSettings settings;
- QString albumID = settings.getAlbumID(albumUrn);
+ QString albumID = AppWindow::instance()->settings.getAlbumID(albumUrn);
photos = new QVector<QStringList>();
deletePhotos = true;
SearchEngine::getAlbumPhotos(albumID, *photos);
@@ -226,6 +225,7 @@
//We don't remove this urn from the hashmap since it may be used later by
//other model
QString urn = urns[i];
+ GetAllPhotosWorker::instance()->removeOnePhoto(urn);
QString path = urnToPathHashMap.value(urn, QString());
if (!path.isEmpty()) {
int index = pathToIndexHashMap.value(path, -1);
@@ -251,17 +251,18 @@
emit layoutAboutToBeChanged();
int cnt = listItemsVector.count();
beginInsertRows(QModelIndex(), cnt - 1, cnt - 1);
- MPSettings settings;
for (int i = 0; i < urns.count(); i++) {
QString urn = urns[i];
- QString path = SearchEngine::getUrl(urn);
- settings.setPhotoUri(urn, path);
+ QStringList photoResult = SearchEngine::getOnePhoto(urn);
+ GetAllPhotosWorker::instance()->addOnePhoto(photoResult);
+
+ QString path = SearchEngine::getPhotoUri(photoResult);
QString key = path.remove(QRegExp("^file:\/\/"));
int indexValue = pathToIndexHashMap.value(key, -1);
if (indexValue != -1)
continue; /* we already have it */
- QString mime = SearchEngine::getMimeType(urn);
+ QString mime = SearchEngine::getPhotoMimeType(photoResult);
MPListItem *item = new MPListItem(path, "", pDefaultThumbnail, mime);
item->urn = urn;
listItemsVector << item;
@@ -300,6 +301,8 @@
// This function will be called many times during fast panning, lets
// check boundaries and validnes only in debug mode
Q_ASSERT(index.isValid());
+ if (index.row() >= listItemsVector.size())
+ qDebug() << "12345 data index:" << index.row() << "size:" << listItemsVector.size();
Q_ASSERT(index.row() < listItemsVector.size());
if (role == Qt::DisplayRole) {
@@ -476,13 +479,17 @@
qDebug() << "MPListModel::updateAlbumModel() end";
}
#else
+
void MPListModel::updateAlbumModel()
{
- qDebug() << "MPListModel::updateAlbumModel()";
+ QTime t;
+ t.start();
if (getDataType() == MPAbstractListModelOps::Album) {
// create a album model
QVector<QStringList> *result = new QVector<QStringList>();
- SearchEngine::getAllPhotoAlbums(*result);
+ qDebug() << "12345: ready";
+ AppWindow::instance()->settings.getAllAlbums(*result);
+ qDebug() << "12345: done: result cnt:" << result->count() << "listitemsvector " << listItemsVector.count();
bool isRemove = false;
int delta = 0;
if (result->count() < listItemsVector.count()) {
@@ -490,8 +497,9 @@
delta = listItemsVector.count() - result->count();
qDebug() << "12345: delta is " << delta;
emit layoutAboutToBeChanged();
- beginRemoveRows(QModelIndex(), listItemsVector.count() - delta, listItemsVector.count() - 1);
- for (int i = listItemsVector.count() - delta; i < listItemsVector.count() - 1; i++) {
+ int cnt = listItemsVector.count();
+ beginRemoveRows(QModelIndex(), cnt - delta, cnt - 1);
+ for (int i = cnt - delta; i < cnt - 1; i++) {
delete listItemsVector[i];
}
listItemsVector.remove(listItemsVector.count() - delta, delta);
@@ -499,7 +507,6 @@
endRemoveRows();
emit layoutChanged();
} else if (result->count() > listItemsVector.count()) {
- MPSettings settings;
delta = result->count() - listItemsVector.count();
qDebug() << "12345: delta for add is " << delta << "result is " << result->count();
emit layoutAboutToBeChanged();
@@ -509,7 +516,7 @@
MPListItem *t = new MPListItem((result->at(i))[1], ((result->at(i))[2]).toInt(), (result->at(i))[0]);
t->thumbnail = pDefaultThumbnail;
t->urn = result->at(i)[0];
- t->photoURI = settings.getAlbumCover(t->urn);
+ t->photoURI = AppWindow::instance()->settings.getAlbumCover(t->urn);
listItemsVector << t;
}
@@ -521,7 +528,6 @@
}
int indexValue = 0;
- MPSettings settings;
QVector<MPListItem *> itemsNeedUpdated;
QVector<MPListItem *> itemsNewAdded;
@@ -530,7 +536,7 @@
MPListItem *t = new MPListItem((result->at(i))[1], ((result->at(i))[2]).toInt(), (result->at(i))[0]);
t->thumbnail = pDefaultThumbnail;
t->urn = result->at(i)[0];
- t->photoURI = settings.getAlbumCover(t->urn);
+ t->photoURI = AppWindow::instance()->settings.getAlbumCover(t->urn);
if (i < listItemsVector.count()) {
if (t->photoURI == listItemsVector[i]->photoURI) {
@@ -551,6 +557,7 @@
}
list->getTasklet()->stopJobQueue();
list->doTasklet();
+ qDebug() << "12345 updatealbum : " << t.elapsed();
}
}
@@ -562,19 +569,7 @@
}
QString MPListItem::albumName() {
- QString start, end;
- QString location;
- QString name;
- MPSettings settings;
- location = settings.getAlbumLocation(urn);
- if (!location.isEmpty()) {
- name = location + " ";
- }
- settings.getAlbumDate(urn, start, end);
- qDebug() << "paul debug albumName: urn:" << urn << "date" << start;
- name.append(start);
- settings.setAlbumName(urn, name);
- return name;
+ return AppWindow::instance()->settings.getAlbumName(urn);
}
--- src/mpproxylistmodel.cpp
+++ src/mpproxylistmodel.cpp
@@ -14,6 +14,8 @@
#include "mpabstractlistmodelops.h"
#include "mpsettings.h"
#include "searchengine.h"
+#include "getallphotosworker.h"
+#include "appwindow.h"
void MPProxyListModel::parseDate(QString in, int &year, int &month, int &day, int &dayOfAWeek) const
{
@@ -107,6 +109,7 @@
qDebug() << "photoDate: " << dateString1;
qDebug() << "user input Date year:" << year << "month:" << month << "day:" << day << "dayOfAWeek:" << dayOfAWeek;
+
if (day != -1) {
if (photoDate.day() == day)
result = true;
@@ -144,15 +147,14 @@
bool MPProxyListModel::matchPhoto(const QString &photoUrn, const QString &userInput) const
{
- MPSettings settings;
- QString dateString = settings.getPhotoDate(photoUrn);
+ QString dateString = GetAllPhotosWorker::instance()->getPhotoDate(photoUrn).toString();
if (compareDate(dateString, userInput)) {
qDebug() << "MPProxyListModel::filterAcceptsRow compare date returns ture";
return true;
}
//Now location
- QString location = settings.getPhotoLocation(photoUrn);
+ QString location = AppWindow::instance()->settings.getPhotoLocation(photoUrn);
if (compareLocation(location, userInput)) {
qDebug() << "MPProxyListModel::filterAcceptsRow compare location returns ture";
return true;
@@ -174,11 +176,10 @@
MPAbstractListModelOps::DataType dataType;
dataType = getDataType();
- MPSettings settings;
if (dataType == MPAbstractListModelOps::Album) {
QString albumUrn = item->urn;
- QString albumID = settings.getAlbumID(albumUrn);
+ QString albumID = AppWindow::instance()->settings.getAlbumID(albumUrn);
QVector<QStringList> photosInTheAlbum;
SearchEngine::getAlbumPhotos(albumID, photosInTheAlbum);
bool isMatched = false;
@@ -201,7 +202,7 @@
void MPProxyListModel::setSearchString(QString _searchString)
{
searchString = _searchString;
- reset();
+ invalidateFilter();
}
void MPProxyListModel::setSpinner(const QModelIndex &index, bool showSpinner)
--- src/mpsettings.cpp
+++ src/mpsettings.cpp
@@ -9,6 +9,8 @@
*/
#include <QString>
+#include <QStringList>
+#include <QDate>
#include <QDebug>
#include "mpsettings.h"
@@ -27,6 +29,7 @@
const QString MPSettings::ALBUM_NAME_KEY = "MP_ALBUM_NAME_KEY";
const QString MPSettings::ALBUM_ID_KEY = "MP_ALBUM_ID_KEY";
const QString MPSettings::ALBUM_COVER_KEY = "MP_ALBUM_COVER_KEY";
+const QString MPSettings::ALBUM_PHOTONUM_KEY = "MP_ALBUM_PHOTONUM_KEY";
MPSettings::MPSettings(const QString & organization, const QString & application, QObject * parent) :
@@ -49,7 +52,6 @@
photoMeta.insert(key, value);
settings.setValue(photoUrn, photoMeta);
-// settings.sync();
}
QVariant MPSettings::value(const QString &photoUrn, const QString &key) const
@@ -76,7 +78,8 @@
{
return value(photoUrn, PHOTO_LOCATION_KEY).toString();
}
-
+
+#if 0
void MPSettings::setPhotoUri(const QString &photoUrn, const QString &uri)
{
setValue(photoUrn, PHOTO_URI_KEY, uri);
@@ -86,6 +89,7 @@
{
return value(photoUrn, PHOTO_URI_KEY).toString();
}
+#endif
void MPSettings::setPhotoAlbumUrn(const QString &photoUrn, const QString &albumUrn)
{
@@ -121,6 +125,7 @@
return getAlbumName(albumUrn);
}
+#if 0
void MPSettings::setPhotoDate(const QString &photoUrn, const QString &dateString)
{
setValue(photoUrn, PHOTO_DATE_KEY, dateString);
@@ -140,10 +145,15 @@
{
return value(photoUrn, PHOTO_LAST_MODIFIED_DATE_KEY).toString();
}
+#endif
void MPSettings::setAlbumDate(const QString &albumUrn, const QString &fromDateString, const QString &toDateString)
{
- qDebug() << "paul debug album date set album " << albumUrn << "date " << fromDateString;
+ MetaData &albumInfo = albumMeta[albumUrn];
+
+ albumInfo.insert(ALBUM_FROM_DATE_KEY, fromDateString);
+ albumInfo.insert(ALBUM_TO_DATE_KEY, toDateString);
+
setValue(albumUrn, ALBUM_FROM_DATE_KEY, fromDateString);
setValue(albumUrn, ALBUM_TO_DATE_KEY, toDateString);
}
@@ -162,17 +172,43 @@
void MPSettings::setAlbumLocation(const QString &albumUrn, const QString &location)
{
+ MetaData &albumInfo = albumMeta[albumUrn];
+
+ albumInfo.insert(ALBUM_LOCATION_KEY, location);
+
setValue(albumUrn, ALBUM_LOCATION_KEY, location);
}
void MPSettings::setAlbumName(const QString &albumUrn, const QString &name)
-{
- setValue(albumUrn, ALBUM_NAME_KEY, name);
+{/*
+ MetaData &albumInfo = albumMeta[albumUrn];
+
+ albumInfo.insert(ALBUM_NAME_KEY, name);
+ setValue(albumUrn, ALBUM_NAME_KEY, name); */
}
QString MPSettings::getAlbumName(const QString &albumUrn)
{
- return value(albumUrn, ALBUM_NAME_KEY).toString();
+ QString start, end;
+ QString location;
+ QString name;
+ location = getAlbumLocation(albumUrn);
+ if (!location.isEmpty()) {
+ name = location + " ";
+ }
+ getAlbumDate(albumUrn, start, end);
+ QDate startDate = QDate::fromString(start);
+ QDate today = QDate::currentDate();
+ int delta = startDate.daysTo(today);
+ if (delta == 0)
+ start = "Today";
+ else if (delta == 1)
+ start = "Yesterday";
+ else if (delta == -1)
+ start = "Tommorrow"; //possible????
+
+ name.append(start);
+ return name;
}
void MPSettings::setAlbumID(const QString &albumUrn, const QString &name)
@@ -186,6 +222,9 @@
void MPSettings::setAlbumCover(const QString &albumUrn, const QString &coverPhotoURI)
{
+ MetaData &albumInfo = albumMeta[albumUrn];
+
+ albumInfo.insert(ALBUM_COVER_KEY, coverPhotoURI);
setValue(albumUrn, ALBUM_COVER_KEY, coverPhotoURI);
}
@@ -194,3 +233,36 @@
return value(albumUrn, ALBUM_COVER_KEY).toString();
}
+void MPSettings::getAllAlbums(QVector<QStringList> &result)
+{
+ QList<QString> keys = albumMeta.keys();
+ result.resize(keys.count());
+ for (int i = 0; i < keys.count(); i++) {
+ QStringList t;
+ t << keys[i]; //t[0] is urn
+ t << ""; //t[1] is albumName which is not used anymore
+ MetaData &albumInfo = albumMeta[keys[i]];
+ t << QString("%1").arg(albumInfo[ALBUM_PHOTONUM_KEY].toInt());
+ result[i] = t;
+ }
+}
+
+void MPSettings::setAlbumPhotoNum(const QString &albumID, const int num)
+{
+ MetaData &albumInfo = albumMeta[albumID];
+
+ albumInfo.insert(ALBUM_PHOTONUM_KEY, num);
+}
+
+int MPSettings::getAlbumPhotoNum(const QString &albumID)
+{
+ MetaData &albumInfo = albumMeta[albumID];
+
+ return albumInfo[ALBUM_PHOTONUM_KEY].toInt();
+}
+
+void MPSettings::removeAlbum(const QString &albumID)
+{
+ albumMeta.remove(albumID);
+}
+
--- src/mpsettings.h
+++ src/mpsettings.h
@@ -24,23 +24,25 @@
void setPhotoLocation(const QString &photoUrn, const QString &location);
QString getPhotoLocation(const QString &photoUrn);
-
+
+#if 0
void setPhotoUri(const QString &photoUrn, const QString &uri);
QString getPhotoUri(const QString &photoUrn);
+#endif
void setPhotoAlbumUrn(const QString &photoUrn, const QString &albumUrn);
QString getPhotoAlbumUrn(const QString &photoUrn);
QString getPhotoAlbumName(const QString &photoUrn);
-
+#if 0
void setPhotoDate(const QString &photoUrn, const QString &dateString);
QString getPhotoDate(const QString &photoUrn);
-
//void setPhotoLocalPath(const QString &photoUrn, const QString &localPath);
//QString getPhotoLocalPath(const QString &photoUrn);
void setPhotoLastModifiedDate(const QString &photoUrn, const QString &dateString);
QString getPhotoLastModifiedDate(const QString &photoUrn);
+#endif
void setAlbumDate(const QString &albumUrn, const QString &fromDateString, const QString &toDateString);
void getAlbumDate(const QString &albumUrn, QString &fromDateString, QString &toDateString);
@@ -57,6 +59,12 @@
void setAlbumCover(const QString &albumID, const QString &photoURI);
QString getAlbumCover(const QString &albumID);
+ void setAlbumPhotoNum(const QString &albumID, const int num);
+ int getAlbumPhotoNum(const QString &albumID);
+
+ void getAllAlbums(QVector<QStringList> &result);
+ void removeAlbum(const QString &albumID);
+
protected:
static const QString PHOTO_ALBUM_URN_KEY; /* ID of the album that the photo belongs to */
static const QString PHOTO_LOCATION_KEY;
@@ -71,6 +79,7 @@
static const QString ALBUM_NAME_KEY; /* name of the album that the photo */
static const QString ALBUM_ID_KEY;
static const QString ALBUM_COVER_KEY;
+ static const QString ALBUM_PHOTONUM_KEY;
void setValue(const QString &photoUrn, const QString &key, const QVariant &value);
QVariant value(const QString &photoUrn, const QString &key) const;
@@ -78,6 +87,7 @@
private:
QSettings settings;
typedef QHash<QString, QVariant> MetaData;
+ QHash<QString, MetaData> albumMeta;
};
#endif
--- src/photostasklet.cpp
+++ src/photostasklet.cpp
@@ -90,7 +90,7 @@
QModelIndex index = j.row;
MPListItem *entry = static_cast<MPListItem *>(j.userData.value<void *>());
QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model());
- MPListModel *photoModel = dynamic_cast<MPListModel *>(model);
+ MPAbstractListModelOps *photoModel = const_cast<MPAbstractListModelOps *>(dynamic_cast<const MPAbstractListModelOps *>(index.model()));
QByteArray md5Result;
#if 0
if (!entry->isLoaded) {
--- src/searchengine.cpp
+++ src/searchengine.cpp
@@ -11,14 +11,13 @@
#include "searchengine.h"
#include <QtTracker/Tracker>
-
-static const QString SqlGetAllPhoto = "SELECT nie:url(nie:isStoredAs(?photo)) nie:mimeType(?photo) ?photo nfo:fileLastModified(?photo) WHERE{?photo a nmm:Photo}";
+static const QString SqlGetAllPhoto = "SELECT nie:url(nie:isStoredAs(?photo)) nie:mimeType(?photo) ?photo nfo:fileLastModified(?photo) nie:contentCreated(?photo) WHERE{?photo a nmm:Photo}";
static const QString SqlGetAllPhotoAlbums = "SELECT nie:identifier(?imagelist) nie:title(?imagelist) nfo:entryCounter(?imagelist) ?imagelist " \
" nao:identifier(?tag) nao:prefLabel(?tag) ?tag " \
" WHERE {?imagelist a nmm:ImageList . OPTIONAL {?imagelist nao:hasTag ?tag . ?tag nao:identifier 'AlbumCover' . }}";
-static const QString SqlGetAlbumPhotos = "SELECT nie:url(nie:isStoredAs(?image)) nie:contentCreated(?image) ?image nie:identifier(?imagelist) nie:title(?imagelist) nfo:entryCounter(?imagelist) "\
+static const QString SqlGetAlbumPhotos = "SELECT nie:url(nie:isStoredAs(?image)) nie:mimeType(?image) ?image nfo:fileLastModified(?image) nie:contentCreated(?image) nie:identifier(?imagelist) nie:title(?imagelist) nfo:entryCounter(?imagelist) "\
" WHERE { ?imagelist nfo:hasMediaFileListEntry ?entry . ?entry nfo:entryContent ?image "\
" { SELECT ?imagelist WHERE {?imagelist a nmm:ImageList ; nie:identifier '%1'} } }";
@@ -44,19 +43,24 @@
static const QString SqlDeleteObjectTag = "DELETE {?tag a rdfs:Resource } WHERE {?object nao:hasTag ?tag . ?tag nao:identifier '%1' . " \
" { SELECT ?object WHERE {?object a nie:InformationElement . FILTER (str(?object) = '%2') } } }";
+static const QString SqlGetPhotoInfoFromURN = "SELECT ?url ?mimetype ?placeholder ?lastmodified ?contentcreated " \
+ " { OPTIONAL { <%1> nie:url ?url . } " \
+ " OPTIONAL { <%1> nie:mimeType ?mimetype . } " \
+ " OPTIONAL { <%1> nie:mimeType ?mimetype . } " \
+ " OPTIONAL { <%1> nfo:fileLastModified ?lastmodified . } " \
+ " OPTIONAL { <%1> nie:contentCreated ?contentcreated .} }";
+
static const QString SqlGetUrlFromURN = "SELECT ?url {<%1> nie:url ?url}";
static const QString SqlGetMimeTypeFromURN = "SELECT ?mimetype {<%1> nie:mimeType ?mimetype}";
bool SearchEngine::getAllPhoto(QVector<QStringList> &result)
{
- qDebug() << "SearchEngine::getAllPhoto " << SqlGetAllPhoto;
result = ::tracker()->rawSparqlQuery(SqlGetAllPhoto);
return TRUE;
}
bool SearchEngine::getAllPhotoAlbums(QVector<QStringList> &result)
{
- qDebug() << "SearchEngine::getAllPhotoAlbums " << SqlGetAllPhotoAlbums;
result = ::tracker()->rawSparqlQuery(SqlGetAllPhotoAlbums);
return TRUE;
}
@@ -64,7 +68,6 @@
bool SearchEngine::getAlbumPhotos(const QString &albumIdentifier, QVector<QStringList> &result)
{
QString sql = QString(SqlGetAlbumPhotos).arg(albumIdentifier);
- qDebug() << "SearchEngine::getAlbumPhotos " << sql;
result = ::tracker()->rawSparqlQuery(sql);
return TRUE;
}
@@ -83,7 +86,6 @@
}
sql += SqlCreateAlbumEnd;
- qDebug() << "SearchEngine::createAlbum " << sql;
::tracker()->rawSparqlUpdateQuery(sql);
return TRUE;
}
@@ -91,7 +93,6 @@
bool SearchEngine::deleteAlbum(const QString &albumIdentifier)
{
QString sql = QString(SqlRemoveAlbum).arg(albumIdentifier);
- qDebug() << "SearchEngine::deleteAlbum " << sql;
::tracker()->rawSparqlUpdateQuery(sql);
return TRUE;
}
@@ -101,7 +102,6 @@
QString sql = QString(SqlQueryAlbumCoverTag).arg(albumURN);
bool needDelete = FALSE;
- qDebug() << "SearchEngine::setAlbumCover query album tag " << sql;
QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
for (QVector<QStringList>::iterator i = result.begin(); i != result.end(); i++) {
@@ -113,12 +113,10 @@
if (needDelete) {
sql = QString(SqlDeleteAlbumCoverTag).arg(albumURN);
- qDebug() << "SearchEngine::setAlbumCover delete album tag " << sql;
::tracker()->rawSparqlUpdateQuery(sql);
}
sql = QString(SqlInsertAlbumCoverTag).arg(coverPath).arg(albumURN);
- qDebug() << "SearchEngine::setAlbumCover insert album tag " << sql;
::tracker()->rawSparqlUpdateQuery(sql);
return TRUE;
@@ -127,7 +125,6 @@
bool SearchEngine::getAlbumCover(const QString &albumURN, QString &coverPath)
{
QString sql = QString(SqlQueryAlbumCoverTag).arg(albumURN);
- qDebug() << "SearchEngine::getAlbumCover " << sql;
QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
@@ -160,7 +157,6 @@
{
QString sql = QString(SqlInsertObjectTag).arg(tagInfo).arg(tagIdentifier).arg(objectURN);
- qDebug() << "SearchEngine::setObjectTag " << sql;
::tracker()->rawSparqlUpdateQuery(sql);
@@ -171,7 +167,6 @@
{
QString sql = QString(SqlQueryObjectTag).arg(tagIdentifier).arg(objectURN);
- qDebug() << "SearchEngine::getObjectTag " << sql;
QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
@@ -191,7 +186,6 @@
{
QString sql = QString(SqlDeleteObjectTag).arg(tagIdentifier).arg(objectURN);
- qDebug() << "SearchEngine::deleteObjectTag " << sql;
::tracker()->rawSparqlUpdateQuery(sql);
@@ -203,8 +197,6 @@
QString sql = QString(SqlGetUrlFromURN).arg(objectURN);
QString url;
- qDebug() << "SearchEngine::getUrl " << sql;
-
QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
if (result.count() != 0)
url = result[0][0];
@@ -216,9 +208,18 @@
QString sql = QString(SqlGetMimeTypeFromURN).arg(objectURN);
QString mimeType;
- qDebug() << "SearchEngine::getMimeType " << sql;
-
QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
mimeType = result[0][0];
return mimeType;
}
+
+QStringList SearchEngine::getOnePhoto(const QString &urn)
+{
+ QString sql = QString(SqlGetPhotoInfoFromURN).arg(urn);
+
+ QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+ QStringList ret = result[0];
+ ret[2] = urn;
+ return ret;
+}
+
--- src/searchengine.h
+++ src/searchengine.h
@@ -17,6 +17,30 @@
{
public:
static bool getAllPhoto(QVector<QStringList> &result);
+ static inline QString getPhotoUrn(const QStringList &photoResult)
+ {
+ return photoResult[2];
+ }
+
+ static inline QString getPhotoUri(const QStringList &photoResult)
+ {
+ return photoResult[0];
+ }
+
+ static inline QString getPhotoLastModified(const QStringList &photoResult)
+ {
+ return photoResult[3];
+ }
+
+ static inline QString getPhotoMimeType(const QStringList &photoResult)
+ {
+ return photoResult[1];
+ }
+
+ static inline QString getPhotoContentCreated(const QStringList &photoResult)
+ {
+ return photoResult[4];
+ }
/// @brief get all photo albums from tracker, including nie:title; nie:identifier; nfo:entryCounter
static bool getAllPhotoAlbums(QVector<QStringList> &result);
@@ -52,5 +76,8 @@
static QString getUrl(const QString &objectURN);
static QString getMimeType(const QString &objectURN);
+
+ static QStringList getOnePhoto(const QString &photoUrn);
+
};
#endif
--- themes/.gitattributes
+++ themes/.gitattributes
-meego export-ignore
++++++ meego-handset-photos.yaml
--- meego-handset-photos.yaml
+++ meego-handset-photos.yaml
@@ -1,6 +1,6 @@
Name: meego-handset-photos
Summary: A Photo Viewer
-Version: 0.0.21
+Version: 0.0.22
Release: 1
Group: System/Libraries
License: Apache License, Version 2.0
More information about the MeeGo-commits
mailing list