[meego-commits] 5556: Changes to Trunk:Handset/meego-handset-photos

longbu long.bu at intel.com
Mon Jul 12 06:12:05 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 #5556:

  submit:   devel:ux:handset/meego-handset-photos(r14) -> Trunk:Handset/meego-handset-photos


Message:
    0.0.19

State:   new          2010-07-11T18:07:10 longbu
Comment: None



changes files:
--------------
--- meego-handset-photos.changes
+++ meego-handset-photos.changes
@@ -0,0 +1,11 @@
+* Mon Jul 12 2010 Long Bu <long.bu at intel.com>
+ - Handle photos remove/add runtime
+ - Add confirmation dialog when deleting photo.
+ - Adjust CSS to work with libdui 0.20.25
+ - Use QSort in album-generation
+ - bug fix: #3532, #3602, #3541, #3600, #3481
+ - Add thumbnailer error handling
+ - Implement only-one spinner effects
+ 
+
+

old:
----
  meego-handset-photos-0.0.18.tar.bz2

new:
----
  meego-handset-photos-0.0.19.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.18
+Version:    0.0.19
 Release:    1
 Group:      System/Libraries
 License:    Apache License, Version 2.0

other changes:
--------------

++++++ meego-handset-photos-0.0.18.tar.bz2 -> meego-handset-photos-0.0.19.tar.bz2
--- abstractdeleteconfirm.h
+++ abstractdeleteconfirm.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_DELETE_CONFIRM
+#define ABSTRACT_DELETE_CONFIRM
+#include <QObject>
+//an abstract interface to be called when user
+//clicks Yes or No of the  delte confirmation dialog
+//
+class AbstractDeleteConfirm : public QObject{
+    Q_OBJECT
+public slots:
+    virtual void onAccepted() = 0;
+    virtual void onRejected() = 0;
+};
+
+#endif
--- abstracttasklet.cpp
+++ abstracttasklet.cpp
@@ -39,6 +39,17 @@
     job.dump();
     processSingleJob(job);
 
-    if(jobs.count() > 0)
-        QTimer::singleShot(0, this, SLOT(processJobQueue()));
+/*    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";
+}
+
--- abstracttasklet.h
+++ abstracttasklet.h
@@ -19,16 +19,12 @@
 
 #include "mplistmodel.h"
 
+struct MPListItem;
 struct Job {
     QModelIndex row;
     QVariant userData;
 
-    //for debug
-    void dump() {
-        MPListItem *entry = static_cast<MPListItem *>(userData.value<void *>());
-        qDebug() << "Job at row " << row.row() << ":" << entry->thumbnailURI;
-
-    }
+    void dump();
 };
 
 class AbstractTasklet : public QObject
--- album-generator/albumsmerge.cpp
+++ album-generator/albumsmerge.cpp
@@ -12,16 +12,18 @@
 #include <QDate>
 #include <QFileInfo>
 #include <QUrl>
+#include <QtAlgorithms>
 
 #include "searchengine.h"
 #include "albumsmerge.h"
 #include "../appwindow.h"
+#include "mpsettings.h"
 
 void albumsMerge::storeAlbumNameID(QString urn, QString albumID, QString albumName)
 {
-    QStringList value;
-    value << albumID << albumName;
-    AppWindow::instance()->settings.setValue(urn, value);
+    MPSettings settings;
+    settings.setAlbumID(urn, albumID);
+    settings.setAlbumName(urn, albumName);
 }
 
 bool albumsMerge::Merge(QVector<QStringList> *photos)
@@ -45,26 +47,12 @@
          }
      }
 
-     /*sort the date interval*/
-     int temp = 0;
+      qSort(intervalVector->begin(), intervalVector->end());
+      
+      /*create the albums not more than MaxAlbum(20)*/
+      
+      int intervalNum = 1;
 
-     for (QVector<int>::iterator i = intervalVector->begin(); i != intervalVector->end(); i++) {
-         int flag = 0 ;
-         for(QVector<int>::iterator j = i; j != intervalVector->end(); j++) {
-             if(*j < *(j+1)){
-                 temp = *j;
-                 *j = *(j+1);
-                 *(j+1) = temp;
-                 flag = 1;
-              }
-          }
-        if (flag == 0)
-		    break;
-    }
-    
-     /*create the albums not more than MaxAlbum(20)*/ 
-     
-	  int intervalNum = 1/*, counterSum = 0*/;
       QStringList lastAlbumphotoUrns;
     
       for (QVector<int>::iterator j = intervalVector->begin(); j != intervalVector->end(); j++) {
--- album-generator/albumsmergethread.cpp
+++ album-generator/albumsmergethread.cpp
@@ -21,25 +21,5 @@
 	QVector<QStringList> *photos = new QVector<QStringList>();
     SearchEngine::getAllPhoto(*photos);
     albumsMerge::Merge(photos);
-    QVector<QStringList> result;
-	SearchEngine::getAllPhotoAlbums(result);
-    if (result.size() == 0 && photos->begin() != photos->end()) {
-        QStringList photosUrns;
-        //This is a bug. workaround it here.
-        //Need Sulei to fix it in Merge()
-        QUrl url = QUrl::fromEncoded((*(photos->begin()))[0].toAscii());
-        QString localFile = url.toLocalFile();
-        qDebug() << "cover " << localFile;
-        QString date = QFileInfo(localFile).created().date().toString();
-        qDebug() << "2222date" << date;
-        for (QVector<QStringList>::iterator i = photos->begin(); i != photos->end(); i++) {
-            photosUrns << (*i)[2];
-            albumsMerge::storeAlbumNameID((*i)[2], "album1", date);
-        }
-        SearchEngine::createAlbum("album1", date, photosUrns);//if the date is today ,set the album title is "Today"
-        QString AlbumURN;
-        SearchEngine::getAlbumURN("album1", AlbumURN);
-        SearchEngine::setAlbumCover(AlbumURN, localFile);
-    }
-    qDebug() << "result size:" << result.size();
+    delete photos;
 }
--- appwindow.cpp
+++ appwindow.cpp
@@ -29,11 +29,13 @@
 #include <MWidgetController>
 #include <MBasicLayoutAnimation>
 #include <MPositionIndicator>
+#include <MDialog>
 
 #include "appwindow.h"
-#include "photos.h"
 #include "photostrip.h"
 #include "mplabelwithclick.h"
+#include "mpsettings.h"
+#include "abstractdeleteconfirm.h"
 
 #define TOP_MARGIN  75
 #define TOP_MARGIN_ALBUM 129
@@ -41,7 +43,7 @@
 AppWindow *AppWindow::mainWindowInstance = NULL;
 
 AppWindow::AppWindow(QWidget *parent) : 
-    MApplicationWindow(parent), photosInOneAlbumList(NULL), currentPhotoList(NULL), settings("Intel", "meegotphots"),
+    MApplicationWindow(parent), photosInOneAlbumList(NULL), currentPhotoList(NULL),
     bottomToolbarLayout(NULL), albumInfoContainer(NULL), searchInput(NULL), startSearch(NULL), isSearchBarShown(false),
     homeButton(NULL), closeButton(NULL)
 {
@@ -448,6 +450,11 @@
  //   currentPage()->setComponentsDisplayMode(MApplicationPage::NavigationBar, MApplicationPageModel::Hide);
     bottomToolbar->disappear();
     topToolbar->disappear();
+    
+    if (currentPage() == singlePhotoPage) {
+        photoStrip->setStripSmall(false);
+    }
+
 }
 void AppWindow::showOverlay()
 {
@@ -469,17 +476,15 @@
         topToolbarLayout->insertItem(1, albumInfoFreestyleContainer);
         albumInfoFreestyleContainer->show();
 
-        QStringList albumIDName;
-        albumIDName = settings.value(currentPhotoUrn).toStringList();
-        if (albumIDName.count() > 1) {
-            currentAlbumName = albumIDName[1];
-            currentAlbumID = albumIDName[0];
-        }
+        MPSettings settings;
+        currentAlbumName = settings.getAlbumName(currentPhotoUrn);
+        currentAlbumID = settings.getAlbumID(currentPhotoUrn);
 
         albumInfoButtonInInfoContainer->setText(currentAlbumName);
         if (!isAllPhotoButtonActive)
             vsep2->show();
         photoInfoButtonInInfoContainer->show();
+        photoStrip->setStripSmall(true);
     }
     bottomToolbar->appear();
     topToolbar->appear();
@@ -493,6 +498,22 @@
     currentPhotoUrn = urn;
 }
 
+/* Popup a confirmation dialog.
+ * return true if the user confirms */
+bool AppWindow::deletePhoto(const QString &photoPath, const AbstractDeleteConfirm *callback)
+{
+    MDialog *dialog = new MDialog("Delete photo",
+            M::YesButton | M::NoButton);
+    QString text = "Are you sure to delete ";
+    text.append(photoPath);
+    dialog->setCentralWidget(new MLabel(text));
+    dialog->setObjectName("deleteConfirmDialog");
+
+    dialog->appear(MSceneWindow::DestroyWhenDone);
+    connect(dialog, SIGNAL(accepted()), callback, SLOT(onAccepted())); 
+    connect(dialog, SIGNAL(rejected()), callback, SLOT(onRejected())); 
+}
+
 void AppWindow::switchPageBack()
 {
     qDebug() << "AppWindow::switchPageBack()";
@@ -660,8 +681,7 @@
     photoStrip->setStripIndex(curIndex);
     allPhotosPage->disappear();
     singlePhotoPage->appear();
-    bottomToolbar->disappear();
-    topToolbar->disappear();
+    hideOverlay();
 }
 
 /*
@@ -683,6 +703,8 @@
      * The backPage is only used for deciding where the backbutton
      * in the singlePhotoPage should return too.
      */
+    if (page == NULL)
+        return;
     if (page != singlePhotoPage) {
         qDebug() << "updateBackPage : " << page->objectName();
         backPage = page;
--- appwindow.h
+++ appwindow.h
@@ -26,6 +26,7 @@
 #include "dynamicalbumlist.h"
 #include "mplabelwithclick.h"
 #include "searchengine.h"
+#include "abstractdeleteconfirm.h"
 
 class MApplicationPage;
 class MButton;
@@ -62,8 +63,8 @@
     static const int vSep2Index = 3;  /* index of the photoInfoButton in the top overlay layout */
 
     static const int albumInfoContainerIndex = 1;
+    static bool deletePhoto(const QString&, const AbstractDeleteConfirm *);
 
-    QSettings settings;
 
 public slots:
     void hideOverlay(void);
--- dynamicalbumlist.cpp
+++ dynamicalbumlist.cpp
@@ -21,11 +21,11 @@
 
 
 
-DynamicAlbumList::DynamicAlbumList(MWidget *parent) : DynamicMList(parent,  MContentItem::IconAndTwoTextLabels)
+DynamicAlbumList::DynamicAlbumList(MWidget *parent) : DynamicMList(parent,  MContentItem::IconAndTwoTextLabels, 1)
 {
     connect(this, SIGNAL(panningStopped()), this, SLOT(doTasklet()));
     connect(AppWindow::instance(), SIGNAL(orientationChanged(M::Orientation)), this, SLOT(onOrientationChanged(M::Orientation)));
-    albumListModel = new MPListModel("", MPListModel::Album);
+    albumListModel = new MPListModel(this, "", MPListModel::Album);
     albumTasklet = new PhotosTasklet(parent);
     setItemModel(albumListModel);
     setTasklet(albumTasklet);
@@ -103,6 +103,7 @@
         Job job; \
         job.userData = data; \
         job.row = index; \
+        qDebug() << "Q_JOB for album entry" << entry; \
         getTasklet()->addJob(job); \
 }  while (0) 
 
@@ -130,9 +131,27 @@
     if (lastRow >= model->listItemsVector.size())
         lastRow = model->listItemsVector.size() - 1;
  
-   qDebug() << "DynamicAlbumList::doTasklet" << "firstVRow" << firstVFlatRow << " lastVRow:" << lastVFlatRow;
+    qDebug() << "DynamicAlbumList::doTasklet" << "firstVRow" << firstVFlatRow << " lastVRow:" << lastVFlatRow;
 
    //Q tasklets
+    for (int i = firstVFlatRow; i <= lastRow; i++) {
+       QModelIndex index(firstVisibleIndex.sibling(i, 0));
+       if (!index.isValid()) {
+           qDebug() << "DynamicAlbumList index " << i << " not valid";
+           continue;
+       }
+       QVariant data = index.data(Qt::DisplayRole);
+       MPListItem *entry = static_cast<MPListItem *>(data.value<void *>());
+       qDebug() << "DynamicAlbumList entry" << entry;
+       if (entry)
+           qDebug() << "DynamicAlbumList index" << i << "loaded:" << entry->isLoaded;
+       if (entry == NULL || entry->isLoaded) 
+           continue; 
+       qDebug() << "DynamicAlbumList::doTasklet model: " << model << "setpinner to true: " << i;
+       model->setSpinner(index, true);
+       break;
+    }
+ 
     for (int i = firstVFlatRow; i <= lastVFlatRow; i++)
         Q_JOB();
     for (int i = lastVFlatRow + 1; i  <= lastRow; i++)
@@ -152,7 +171,20 @@
    
     // remove rows after lastVFlatRow + numItemsAfterLastvisibleOne
     for (int i = lastRow + 1; i < model->listItemsVector.size(); i++)
-        model->setDefaultThumbnail(i);
+        model->setDefaultThumbnail(i);  
+
+    int i = lastRow + 1;
+    if (i < model->listItemsVector.size()) {
+        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) {
+                qDebug() << "DynamicAlbumList::doTasklet model: " << model << "setpinner to true22: " << index;
+                model->setSpinner(index, true);
+            }
+        }
+    }
 
     getTasklet()->processJobQueue();
 }
@@ -160,9 +192,11 @@
 void DynamicAlbumList::updateAlbumModel()
 {
     qDebug() << "DynamicAlbumList::updateAlbumModel";
+    getTasklet()->stopJobQueue();   //The jobq may refer the old model
     MPListModel *old = albumListModel;
-    albumListModel = new MPListModel("", MPListModel::Album);
+    albumListModel = new MPListModel(this, "", MPListModel::Album);
     setItemModel(albumListModel);
+    qDebug() << "DynamicAlbumList::updateAlbumModel set model" << albumListModel;
     QTimer::singleShot(400, this, SLOT(doTasklet()));
     if (old)
         delete old;
--- dynamicmlist.cpp
+++ dynamicmlist.cpp
@@ -13,10 +13,10 @@
 #include "mcontentitemcreator.h"
 
 
-DynamicMList::DynamicMList(MWidget *parent, MContentItem::ContentItemStyle itemStyle) :
+DynamicMList::DynamicMList(MWidget *parent, MContentItem::ContentItemStyle itemStyle, int id) :
     MList(parent), tasklet(NULL)
 {
-    MContentItemCreator *thumbnailItemCreator = new MContentItemCreator(itemStyle);
+    MContentItemCreator *thumbnailItemCreator = new MContentItemCreator(itemStyle, id);
     setCellCreator(thumbnailItemCreator);
 }
 
--- dynamicmlist.h
+++ dynamicmlist.h
@@ -20,11 +20,13 @@
 
 #include "abstracttasklet.h"
 
+class AbstractTasklet;
+
 class DynamicMList : public MList
 {
 Q_OBJECT
 public:
-    explicit DynamicMList(MWidget *parent = 0, MContentItem::ContentItemStyle style = MContentItem::SingleIcon);
+    explicit DynamicMList(MWidget *parent = 0, MContentItem::ContentItemStyle style = MContentItem::SingleIcon, int id = 0);
     virtual ~DynamicMList();
 
     void setCellCreator(MCellCreator * itemCreator)
--- dynamicphotolist.cpp
+++ dynamicphotolist.cpp
@@ -19,14 +19,15 @@
 #include "appwindow.h"
 #include "photothumbnailscellprocessor.h"
 #include "mcontentitemex.h"
+#include "photolistdeleteconfirm.h"
 
 
 
-DynamicPhotoList::DynamicPhotoList(MWidget *parent, QString albumID) : DynamicMList(parent)
+DynamicPhotoList::DynamicPhotoList(MWidget *parent, QString albumID) : DynamicMList(parent), photoListDeleteConfirm(NULL)
 {
     connect(this, SIGNAL(panningStopped()), this, SLOT(doTasklet()));
     connect(AppWindow::instance(), SIGNAL(orientationChanged(M::Orientation)), this, SLOT(onOrientationChanged(M::Orientation)));
-    photosListModel = new MPListModel(albumID);
+    photosListModel = new MPListModel(this, albumID);
     photosTasklet = new PhotosTasklet(parent);
     setItemModel(photosListModel);
     setTasklet(photosTasklet);
@@ -44,6 +45,8 @@
 {
    //The base class's destructor takes care of the model and the tasklet
     disconnect(this, SIGNAL(panningStopped()), this, SLOT(doTasklet()));
+    if (photoListDeleteConfirm)
+        delete photoListDeleteConfirm;
 }
 
 void DynamicPhotoList::onOrientationChanged(M::Orientation orientation)
@@ -72,8 +75,15 @@
 void DynamicPhotoList::objectMenuDelete()
 {
     MContentItemEx *itemEx = dynamic_cast<MContentItemEx *>(sender()->parent());
-    qDebug() << "DynamicPhotoList::objectMenuDelete(): row" << itemEx->index.row();
-    itemModel()->removeRow(itemEx->index.row());
+    QVariant data = itemEx->index.data(Qt::DisplayRole);
+    MPListItem *entry = static_cast<MPListItem *>(data.value<void *>());
+    if (entry) {
+        QString fileString = entry->photoURI.remove(QRegExp("^file:\/\/"));
+        if (!photoListDeleteConfirm)
+            photoListDeleteConfirm = new PhotoListDeleteConfirm();
+        photoListDeleteConfirm->setFile(fileString);
+        AppWindow::instance()->deletePhoto(fileString, photoListDeleteConfirm);
+    }
 }
 
 const int DynamicPhotoList::numItemsBeforeFirstVisibleOne = 4*8; 
@@ -122,6 +132,17 @@
    qDebug() << "DynamicPhotoList::doTasklet" << "firstVRow" << firstVFlatRow << " lastVRow:" << lastVFlatRow;
 
    //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++)
@@ -143,6 +164,17 @@
     for (int i = lastRow + 1; i < model->listItemsVector.size(); i++)
         model->setDefaultThumbnail(i);
 
+    int i = lastRow + 1;
+    if (i < model->listItemsVector.size()) {
+       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();
 }
 
@@ -173,33 +205,11 @@
     f.close();
 }
 
-void DynamicPhotoList::resizeEvent(QGraphicsSceneResizeEvent *event) {
-    return; //this causes the one album view flicking. diable it for now.
-    //Ugly way to resize MContentItem size. Tell me if you know a better way 
-        MList::resizeEvent(event);
-        if (columns()) {
-            qreal edge = size().width() / columns();
-            qDebug() << "size is" << size().width() << " edge:" << edge;
-            if (edge > 1.0) {
-                const char *tmpCSS = "/tmp/meegophotosTmp.css";
-                ::genCSSFile(tmpCSS, edge);
-                MTheme::instance()->loadCSS(tmpCSS);
-                QFile(tmpCSS).remove();
-                MContentItemCreator *photothumbnailCreator = dynamic_cast<MContentItemCreator *>(cellCreator());
-                photothumbnailCreator->setCellObjectName("photoThumbnail2");
-                /* Have to made changes to columns so the itemHeight of MList will be recalculated */
-                setColumns(7);
-                setColumns(8);
-            }
-        }
-}
-
-
 void DynamicPhotoList::setAlbumID(QString newID)
 {
     MPListModel *model;
     model = dynamic_cast<MPListModel *>(itemModel());
-    photosListModel = new MPListModel(newID);
+    photosListModel = new MPListModel(this, newID);
     setItemModel(photosListModel);
     delete model;
     photosTasklet->stopJobQueue();
--- dynamicphotolist.h
+++ dynamicphotolist.h
@@ -16,6 +16,7 @@
 #include "dynamicmlist.h"
 #include "mplistmodel.h"
 #include "photostasklet.h"
+#include "photolistdeleteconfirm.h"
 
 class DynamicPhotoList : public DynamicMList
 {
@@ -28,7 +29,6 @@
     static const int numItemsBeforeFirstVisibleOne;
     static const int numItemsAfterLastVisibleOne;
 
-    virtual void resizeEvent(QGraphicsSceneResizeEvent *event);
     void setAlbumID(QString albumID);
 
 public slots:
@@ -42,6 +42,7 @@
 private:
     MPListModel *photosListModel;
     PhotosTasklet *photosTasklet;
+    PhotoListDeleteConfirm *photoListDeleteConfirm;
 };
 
 #endif // DYNAMICPHOTOLIST_H
--- main.cpp
+++ main.cpp
@@ -22,6 +22,10 @@
 {
     MApplication app(argc, argv);
 
+    QCoreApplication::setOrganizationName("Intel");
+    QCoreApplication::setOrganizationDomain("www.intel.com");
+    QCoreApplication::setApplicationName("Meego Photos");
+
     AppWindow w;
     w.show();
 
--- mcontentitemcreator.cpp
+++ mcontentitemcreator.cpp
@@ -16,7 +16,7 @@
 
 void MContentItemCreator::updateCell(const QModelIndex &index, MWidget *cell) const
 {
-    MContentItem *contentItem = qobject_cast<MContentItem *>(cell);
+    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;
 
@@ -26,9 +26,14 @@
     qDebug() << "updateCell row:" << index.row() << "thumbnail" << item->thumbnailURI;
     qDebug() << "cellSize" << cell->size().width() << "," << cell->size().height();
     contentItem->setPixmap(*(item->thumbnail));
-    contentItem->boundingRect();
+    if (item->showSpinner) {
+        contentItem->showSpinner();
+    } else  {
+        contentItem->hideSpinner();
+    }
 
-    if (contentItem->itemStyle() ==  MContentItem::IconAndTwoTextLabels) {
+    //if (contentItem->itemStyle() ==  MContentItem::TwoIconsTwoWidgets) {
+    if (id == 1) {
         QString text = "<b>" + item->albumName + "</b>    ";
         contentItem->setTitle(text);
         text = QString().setNum(item->numPhotos) + " Photos";
--- mcontentitemcreator.h
+++ mcontentitemcreator.h
@@ -27,8 +27,8 @@
 class MContentItemCreator : public MAbstractCellCreator<MContentItemEx>
 {
 public:
-    MContentItemCreator(MContentItemEx::ContentItemStyle style) : itemStyle(MContentItemEx::SingleIcon),
-        cellProcessor(NULL)
+    MContentItemCreator(MContentItemEx::ContentItemStyle style, int _id = 0) : itemStyle(MContentItemEx::TwoIconsTwoWidgets),
+        cellProcessor(NULL), id(_id)
     {
         itemStyle = style;
         size = MAbstractCellCreator<MContentItemEx>::cellSize();
@@ -72,7 +72,7 @@
         recycler.setMaxItemsPerClass(0);
         MContentItemEx *cell = dynamic_cast<MContentItemEx *>(recycler.take(MContentItem::staticMetaObject.className()));
         if (cell == NULL) {
-            cell = new MContentItemEx(itemStyle);
+            cell = new MContentItemEx(itemStyle, NULL, id);
 
             cell->index = index;
             if (!cellViewType.isEmpty())
@@ -107,7 +107,7 @@
 
 private:
     void updateSize() {
-        MContentItemEx *cell = new MContentItemEx(itemStyle);
+        MContentItemEx *cell = new MContentItemEx(itemStyle, NULL, id);
         if (!cellViewType.isEmpty())
             cell->setViewType(cellViewType);
         if (!cellObjectName.isEmpty())
@@ -122,6 +122,8 @@
    QString cellObjectName;
    MContentItemEx::ContentItemStyle itemStyle;
    AbstractCellProcessor *cellProcessor;    //A chance to process cell after which has been created
+
+   int id; //identify the cell is for photo or album
 };
 
 
--- mcontentitemex.cpp
+++ mcontentitemex.cpp
@@ -10,3 +10,29 @@
 
 
 #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;
+}
+
--- mcontentitemex.h
+++ mcontentitemex.h
@@ -18,14 +18,22 @@
 {
 public:
 
-    MContentItemEx(MContentItem::ContentItemStyle itemStyle = MContentItem::IconAndTwoTextLabels, QGraphicsItem *parent = 0)
-        :   MContentItem(itemStyle, parent)
+    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);
 
 };
 
--- meegophotos.pro
+++ meegophotos.pro
@@ -48,7 +48,12 @@
   photostriplayout.cpp \
   mplabelwithclick.cpp \
   "album-generator/albumsmerge.cpp" \
-  "album-generator/albumsmergethread.cpp"
+  "album-generator/albumsmergethread.cpp" \
+  stripimageview.cpp \
+  mpsettings.cpp \
+  mcontentitemex.cpp \
+  trackerlistener.cpp \
+  photolistdeleteconfirm.cpp
 
 HEADERS += \
   appwindow.h \
@@ -72,14 +77,22 @@
   photostriplayout.h \
   mplabelwithclick.h \
   "album-generator/albumsmerge.h" \
-  "album-generator/albumsmergethread.h"
+  "album-generator/albumsmergethread.h" \
+  stripimageview.h \
+  stripimagestyle.h \
+  mpsettings.h \
+  mcontentitemex.h \
+  trackerlistener.h \
+  abstractdeleteconfirm.h \
+  photolistdeleteconfirm.h
 
 
 MODEL_HEADERS += \
   photostripmodel.h
 
 STYLE_HEADERS += \
-  photostripstyle.h
+  photostripstyle.h \
+  stripimagestyle.h
 
 INSTALLS += target theme desktop desktop_icon
 
--- mplabelwithclick.h
+++ mplabelwithclick.h
@@ -25,7 +25,8 @@
     virtual ~MPLabelWithClick() {};
 
 protected:
-     virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) {Q_UNUSED(event); emit clicked();};
+     virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {Q_UNUSED(event); emit clicked();};
+     virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) {Q_UNUSED(event);};
 
 Q_SIGNALS:
      void clicked();
--- mplistmodel.cpp
+++ mplistmodel.cpp
@@ -18,12 +18,20 @@
 #include "thumbnailer.h"
 #include "photostasklet.h"
 #include "appwindow.h"
+#include "trackerlistener.h"
 
-MPListModel::MPListModel(QString albumID, DataType dataType)
+QHash<QString, QString> MPListModel::urnToPathHashMap;
+
+MPListModel::MPListModel(DynamicMList *controller, QString albumID, DataType type) : list(controller), dataType(type)
 {
     //Create Thumbnailer
     Thumbnailer::instance();
-    QObject::connect(Thumbnailer::instance(), SIGNAL(ready(uint,QStringList)), this, SLOT(handleReady(uint,QStringList)));
+    TrackerListener::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)));
+    QObject::connect(TrackerListener::instance(), SIGNAL(SubjectsAdded(const QStringList &)), this, SLOT(handlePhotoAdded(const QStringList &)), Qt::QueuedConnection);
+    QObject::connect(TrackerListener::instance(), SIGNAL(SubjectsRemoved(const QStringList &)), this, SLOT(handlePhotoRemoved(const QStringList &)), Qt::QueuedConnection);
     int indexValue = 0;
 
     //Build photoItemVector
@@ -65,6 +73,8 @@
                 qDebug() << "album cover:" << (*i)[5];
                 t->photoURI = (*i)[5];
                 listItemsVector << t;
+            
+                pathToIndexHashMap.insert(QUrl::fromEncoded(t->photoURI.toAscii()).toLocalFile(), indexValue++);
             }
         }
 
@@ -92,29 +102,166 @@
             item->urn = (*i)[2];
             listItemsVector << item;
 
-            pathToIndexHashMap.insert(url.toLocalFile(), indexValue++);
+            pathToIndexHashMap.insert(url.toLocalFile(), indexValue);
+            urnToPathHashMap.insert(item->urn, url.toLocalFile());
+            indexValue++;
         }
     }
+
+    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)
 {
-    qDebug() << "Thumbnail Ready " << handler << " " << urls; //avoid warning
+    qDebug() << "MPListModel:" << this << "Thumbnail Ready " << handler << " " << urls; //avoid warning
     for (QStringList::const_iterator i = urls.begin(); i != urls.end(); i++) {
         QString localPath = *i;
-        int indexValue = pathToIndexHashMap.value(localPath.remove(QRegExp("^file:\/\/")));
+        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, AppWindow::instance()->photoList->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;
+    qDebug() << "MPListModel:" << this << "Thumbnail Error " << handler << " " << urls << "errorCode " << errorCode << "message " << message; //avoid warning
+    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);
+        qDebug() << "key " << key << " indexValue" << indexValue;
+        if (indexValue == -1)
+            continue;
+        MPListItem *entry = listItemsVector[indexValue];
+        entry->thumbnail = new QPixmap(PhotosTasklet::squareQPixmapFromPath(entry->thumbnailURI, AppWindow::instance()->photoList->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) {
+                qDebug() << "xxxxxxxxxxxxxxxxxxx";
+                next_entry->showSpinner = true;
+            }
+            thumbnailWasLoaded(next);   //emit date changed signal;
+        }
+ 
+        thumbnailWasLoaded(modelIndex);
+        QTimer::singleShot(0, list->getTasklet(), SLOT(processJobQueue()));
+    }
+}
+
+void MPListModel::handlePhotoRemoved(const QStringList  &urns)
+{
+    qDebug() << "MPListModel::handlePhotoRemoved ";
+    if (dataType == Album) {
+        //Todo: re-generate albums 
+        return;
+    }
+ 
+    emit layoutAboutToBeChanged();
+    for (int i = 0; i < urns.count(); i++) {
+        //We don't remove this urn from the hashmap since it may be used later by 
+        //other model
+        QString urn = urns[i];
+        QString path = urnToPathHashMap.value(urn, QString());
+        if (!path.isEmpty()) {
+            int index = pathToIndexHashMap.value(path, -1);
+            qDebug() << "MPListModel::handlePhotoRemoved index" << index;
+            if (index != -1) {
+                beginRemoveRows(QModelIndex(), index, index);
+                listItemsVector.remove(index);
+                endRemoveRows();
+            }
+        }
+    }
+    emit layoutChanged();
+}
+
+void MPListModel::handlePhotoAdded(const QStringList  &urns)
+{
+    qDebug() << "PhotoAdded urns count" << urns.count();
+    if (dataType == Album) {
+        //Todo: re-generate albums 
+        return;
+    }
+    emit layoutAboutToBeChanged();
+    int cnt = listItemsVector.count();
+    beginInsertRows(QModelIndex(), cnt - 1, cnt - 1);
+    for (int i = 0; i < urns.count(); i++) {
+        QString urn = urns[i];
+        QString path = SearchEngine::getUrl(urn);
+        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);
+        MPListItem *item = new MPListItem(path, "", pDefaultThumbnail, mime);
+        item->urn = urn;
+        listItemsVector << item;
+        pathToIndexHashMap.insert(key, listItemsVector.count()-1);
+        urnToPathHashMap.insert(item->urn, key);
+        qDebug() << "PhotoAdded xx" << listItemsVector.count()-1;
+    }
+    endInsertRows();
+    emit layoutChanged();
+    QModelIndex addedIndex = index(listItemsVector.count()-1, 0);
+    emit dataChanged(addedIndex, addedIndex);
+    list->doTasklet();
+    
+}
+
 MPListModel::~MPListModel()
 {
     QObject::disconnect(Thumbnailer::instance(), SIGNAL(ready(uint,QStringList)), this, SLOT(handleReady(uint,QStringList)));
-    for (int i = 0; i < listItemsVector.size(); i++) {
+    QObject::disconnect(Thumbnailer::instance(), SIGNAL(error(uint, QStringList, const int &, const QString &)), this, SLOT(handleError(uint,QStringList, const int &, const QString &)));
+    QObject::disconnect(TrackerListener::instance(), SIGNAL(SubjectsAdded(const QStringList &)), this, SLOT(handlePhotoAdded(const QStringList &)));
+    QObject::disconnect(TrackerListener::instance(), SIGNAL(SubjectsRemoved(const QStringList &)), this, SLOT(handlePhotoRemoved(const QStringList &)));
+    for (int i = 0; i < listItemsVector.count(); i++) {
         delete listItemsVector[i];
     }
 
@@ -145,6 +292,7 @@
 int MPListModel::rowCount(const QModelIndex &parent) const
 {
     Q_UNUSED(parent);
+    qDebug() << "mplistmodel" << this << " row count" << listItemsVector.size();
 
     return listItemsVector.size();
 }
@@ -156,11 +304,13 @@
     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];
@@ -181,15 +331,19 @@
         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++) {
@@ -202,8 +356,10 @@
 
     }
     endRemoveRows();
+    emit layoutChanged();
     return true;
 }
+*/
 
 void MPListModel::thumbnailWasLoaded(const QModelIndex &index)
 {
--- mplistmodel.h
+++ mplistmodel.h
@@ -15,27 +15,29 @@
 #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) :
-            photoURI(newphotoURI), thumbnailURI(newThumbnailURI), isLoaded(false), mimetype(newmimetype), numPhotos(0)
+            thumbnail(NULL), showSpinner(false), photoURI(newphotoURI), thumbnailURI(newThumbnailURI), isLoaded(false), mimetype(newmimetype), numPhotos(0)
     {
         thumbnail = t;   //implicit data sharing
     }
 
     MPListItem(QString _albumName, int _numPhotos) :
-        isLoaded(false), albumName(_albumName), numPhotos(_numPhotos) {};
+        thumbnail(NULL), showSpinner(false), isLoaded(false), albumName(_albumName), numPhotos(_numPhotos) {};
 
     MPListItem(QString _albumName, int _numPhotos, QString _albumID) :
-        isLoaded(false), albumName(_albumName), albumID(_albumID), numPhotos(_numPhotos) {};
+        thumbnail(NULL), showSpinner(false), isLoaded(false), albumName(_albumName), 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;
@@ -49,7 +51,7 @@
  //   explicit MPListItem();   //disable default constructor
 };
 
-
+class DynamicMList;
 //Data model for photo listing and album listing
 class MPListModel: public QAbstractTableModel
 {
@@ -66,7 +68,7 @@
         Photo
     };
 
-    MPListModel(QString sparql = "", DataType type = Photo);
+    MPListModel(DynamicMList *controller, QString sparql = "", DataType type = Photo);
     virtual ~MPListModel();
 
     virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
@@ -74,9 +76,9 @@
     virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
     void setSparql(QString qlString);
 
-    bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
+/*    bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
     bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
-
+*/
     void thumbnailWasLoaded(const QModelIndex &index);
 
     void setDefaultThumbnail(int index)
@@ -88,6 +90,21 @@
         }
     }
 
+    void setSpinner(const QModelIndex &index, bool showSpinner)
+    {
+        int i = index.row();
+        qDebug() << "setSpinner: row:" << i << "showSpinner" << showSpinner << "loaded: " << listItemsVector[i]->isLoaded;
+        if (listItemsVector[i]->isLoaded && !showSpinner)
+            listItemsVector[i]->showSpinner = false;
+        else if (!listItemsVector[i]->isLoaded)
+            listItemsVector[i]->showSpinner = showSpinner;
+
+        thumbnailWasLoaded(index);
+    }
+
+    void addOutstandingThumbnailRequest(QString ruquestPath);
+    void removeOutstandingThumbnailRequest(QString ruquestPath);
+
     static QString testThumbnailDir;
     QString homePath;
     QString thumbnail_folder;
@@ -99,11 +116,18 @@
     QVector<MPListItem *> listItemsVector;
     QPixmap *pDefaultThumbnail;
     QHash<QString, int> pathToIndexHashMap;
+    static QHash<QString, QString> urnToPathHashMap;
+    QSet<QString> outstandingThumbnailRequest;
+    DynamicMList *list;
+    DataType dataType;
 
     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);
+    void handlePhotoAdded(const QStringList  &urns);
+    void handlePhotoRemoved(const QStringList  &urns);
 };
 
 
--- mpsettings.cpp
+++ mpsettings.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 <QString>
+#include "mpsettings.h"
+
+
+const QString MPSettings::LOCATION_KEY = "MP_LOCATION_KEY";
+const QString MPSettings::ALBUM_ID_KEY = "MP_ALBUM_ID_KEY";
+const QString MPSettings::ALBUM_NAME_KEY = "MP_ALBUM_NAME_KEY";
+
+MPSettings::MPSettings(const QString & organization, const QString & application, QObject * parent) : 
+    settings(organization, application, parent)
+{
+}
+
+MPSettings::MPSettings()
+{
+}
+
+MPSettings::~MPSettings()
+{
+}
+
+void MPSettings::setValue(QString photoUrn, QString key, QVariant value)
+{
+    PhotoMetaData photoMeta;
+    photoMeta = settings.value(photoUrn, photoMeta).value<PhotoMetaData>();
+        
+    photoMeta.insert(key, value);
+    settings.setValue(photoUrn, photoMeta);
+}
+
+
+QVariant MPSettings::value(QString photoUrn, QString key) const
+{
+    PhotoMetaData photoMeta;
+    photoMeta = settings.value(photoUrn, photoMeta).value<PhotoMetaData>();
+    return photoMeta.value(key);
+}
+
+void MPSettings::setLocation(QString photoUrn, QString location)
+{
+    setValue(photoUrn, LOCATION_KEY, location);
+}
+
+QString MPSettings::getLocation(QString photoUrn)
+{
+    return value(photoUrn, LOCATION_KEY).toString();
+}
+        
+void MPSettings::setAlbumID(QString photoUrn, QString albumID)
+{
+    setValue(photoUrn, ALBUM_ID_KEY, albumID);
+}
+
+QString MPSettings::getAlbumID(QString photoUrn)
+{
+    return value(photoUrn, ALBUM_ID_KEY).toString();
+}
+            
+void MPSettings::setAlbumName(QString photoUrn, QString albumName)
+{
+    setValue(photoUrn, ALBUM_NAME_KEY, albumName);
+}
+
+QString MPSettings::getAlbumName(QString photoUrn)
+{
+    return value(photoUrn, ALBUM_NAME_KEY).toString();
+}
+
--- mpsettings.h
+++ mpsettings.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 MPSETTINGS_H
+#define MPSETTINGS_H
+
+#include <QString>
+#include <QSettings>
+
+class MPSettings {
+public:
+    MPSettings(const QString & organization, const QString & application = QString(), QObject * parent = 0 );
+    MPSettings();
+    ~MPSettings();
+     
+    void setLocation(QString photoUrn, QString location);
+    QString getLocation(QString photoUrn);
+
+    void setAlbumID(QString photoUrn, QString albumID);
+    QString getAlbumID(QString photoUrn);
+
+    void setAlbumName(QString photoUrn, QString albumName);
+    QString getAlbumName(QString photoUrn);
+    static const QString LOCATION_KEY;
+
+protected:
+    static const QString ALBUM_ID_KEY;
+    static const QString ALBUM_NAME_KEY;
+
+    void setValue(QString photoUrn, QString key, QVariant value);
+    QVariant value(QString photoUrn, QString key) const;
+
+private:
+    QSettings settings;
+    typedef QHash<QString, QVariant> PhotoMetaData;
+};
+
+#endif
--- photolistdeleteconfirm.cpp
+++ photolistdeleteconfirm.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 <QFile>
+
+#include "photolistdeleteconfirm.h"
+
+void PhotoListDeleteConfirm::onAccepted()
+{
+    qDebug() << "User accepts ";
+    QFile::remove(file);
+}
+
+
+void PhotoListDeleteConfirm::setFile(QString fileToBeDeleted)
+{
+    file = fileToBeDeleted;
+}
+
+void PhotoListDeleteConfirm::onRejected()
+{
+    qDebug() << "User rejects ";
+}
+
--- photolistdeleteconfirm.h
+++ photolistdeleteconfirm.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 PHOTO_LIST_DELETE_CONFIRM
+#define PHOTO_LIST_DELETE_CONFIRM
+
+#include "abstractdeleteconfirm.h"
+class PhotoListDeleteConfirm : public AbstractDeleteConfirm {
+    Q_OBJECT
+public:
+    void setFile(QString);
+
+public slots:
+    virtual void onRejected();
+    virtual void onAccepted();
+
+private:
+    QString file;
+};
+
+#endif
--- photos.cpp
+++ photos.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 "photos.h"
-#include "appwindow.h"
-
-Photos::Photos(QGraphicsItem *parent) :
-  MWidgetController(new PhotosModel(), parent)
-{
-}
-
-Photos::~Photos()
-{
-}
-
-/*
-void Photos::showPhoto()
-{
-    QString res = sender()->objectName();
-
-    AppWindow *window = AppWindow::instance();
-    window->showSinglePhoto(res);
-}
-*/
-
-void Photos::showPhotoFromObjectMenu()
-{
-    // Since we are dealing with a slot triggered by 
-    // an objectmenu action, then find the res string
-    // by looking in the parent of the sender
-    QString res = sender()->parent()->objectName();
-
-    AppWindow *window = AppWindow::instance();
-    window->showSinglePhoto(res);    
-}
-
-void Photos::deletePhoto()
-{
-    QString res = sender()->parent()->objectName();
-
-    qDebug() << "deletePhoto : " << res;
-
-    // open a confirmation dialog and then delete the photo
-    // if confirmed
-}
--- photos.h
+++ photos.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 PHOTOS_H
-#define PHOTOS_H
-
-#include <MWidgetController>
-#include "photosview.h"
-#include "photosmodel.h"
-
-class M_EXPORT Photos : public MWidgetController
-{
-    Q_OBJECT
-    M_CONTROLLER(Photos);
-
-public:
-    Photos(QGraphicsItem *parent = 0);
-    virtual ~Photos();
-    const PhotosView *getView() {return dynamic_cast<const PhotosView *>(view()); };
-
-public Q_SLOTS:
-    void setQuery(QString query) {
-	    model()->setQuery(query);
-    };
-    void showPhoto();
-    void showPhotoFromObjectMenu();
-    void deletePhoto();
-
-private:
-    friend class PhotosView;
-};
-
-#endif // PHOTOS_H
--- photostasklet.cpp
+++ photostasklet.cpp
@@ -99,8 +99,9 @@
         //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() << path  << " " << "thumbnailURI generated is " << entry->thumbnailURI;
+        qDebug() << "entry " << entry << " " << path  << " " << "thumbnailURI generated is " << entry->thumbnailURI;
     }
+    qDebug() << "entry " << entry << "thumbnailURI is " << entry->thumbnailURI;
 
     //Some thumbnails may have not been created yet
     QFile f;
@@ -110,27 +111,22 @@
         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;
+        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 {
-        //request thumbnail from Tumbler
-        photoModel->thumbnailDir->setNameFilters(QStringList(QString(md5Result.toHex()) + "*"));
-        qDebug() << "filter is " << QStringList(QString(md5Result.toHex()) + "*");
-        qDebug() << "result is " << photoModel->thumbnailDir->entryList();
-
-        //does not found even failed thumbnails
-        if ((photoModel->thumbnailDir->entryList()).length() == 0) {
-            QUrl url = QUrl::fromEncoded(entry->photoURI.toAscii());
-            qDebug() << "Request thumbnail for file file://" << url.path() << "mimetype is " << entry->mimetype;
-            Thumbnailer::instance()->requestThumbnail(QString(("file://" + url.path())), entry->mimetype);
-            thumbnailsToBeGenerated << ThumbnailCheckJob(j); 
-            if (thumbnailsToBeGenerated.count() > 0 && !outstandingChecking) {
-                QTime now;
-                now.start();
-                qDebug() << "schedule PhotosTasklet::checkThumbnailsGenerated() time" << now << ":" << now.msec();
-               /* QTimer::singleShot(100, this, SLOT(checkThumbnailsGenerated()));*/
-                outstandingChecking = true;
-            }
-        }
+        QUrl url = QUrl::fromEncoded(entry->photoURI.toAscii());
+        qDebug() << "model" << photoModel << "Request thumbnail for file file://" << url.path() << "mimetype is " << entry->mimetype;
+        photoModel->addOutstandingThumbnailRequest(url.path());
+        Thumbnailer::instance()->requestThumbnail(QString(("file://" + url.path())), entry->mimetype);
     }
 
 #endif
--- photostrip.h
+++ photostrip.h
@@ -32,6 +32,9 @@
     void setSlideShow(bool on) {
         model()->setSlideShow(on);
     };
+    void setStripSmall(bool on) {
+        model()->setStripSmall(on);
+    };
 
 protected:
     virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
--- photostripmodel.cpp
+++ photostripmodel.cpp
@@ -24,6 +24,12 @@
     memberModified(SlideShow);
 }
 
+void PhotoStripModel::setStripSmall(const bool &on)
+{
+    _stripSmall() = on;
+    memberModified(StripSmall);
+}
+
 const QModelIndex &PhotoStripModel::stripIndex() const
 {
     return _stripIndex();
@@ -33,3 +39,8 @@
 {
     return _slideShow();
 }
+
+const bool &PhotoStripModel::stripSmall() const
+{
+    return _stripSmall();
+}
--- photostripmodel.h
+++ photostripmodel.h
@@ -21,6 +21,7 @@
     M_MODEL(PhotoStripModel);
     M_MODEL_PROPERTY(QModelIndex, stripIndex, StripIndex, false, QModelIndex());
     M_MODEL_PROPERTY(bool, slideShow, SlideShow, false, false);
+    M_MODEL_PROPERTY(bool, stripSmall, StripSmall, false, false);
 
 private:
 };
--- photostripview.cpp
+++ photostripview.cpp
@@ -27,6 +27,7 @@
 #include "appwindow.h"
 #include "photostripphysics.h"
 #include "mplistmodel.h"
+#include "stripimageview.h"
 #include "photostriplayout.h"
 /*************************************************************************
  * PhotoStripView
@@ -51,6 +52,15 @@
     MWidgetController::mouseReleaseEvent(event);
 }
 
+void Viewport::cancelEvent(MCancelEvent *event)
+{
+    Q_UNUSED(event);
+    /* we don't want to ungrab mouse, keep pan gesture */
+    /* overwrite MPannableWidget::cancelEvent() */
+    /* fix bug #3532 */
+}
+
+
 
 const int PhotoStripView::BUFFERSIZE = 2;
 const int PhotoStripView::SLIDESHOW_INTERVAL = 3000; // ms
@@ -125,7 +135,9 @@
         (AppWindow::instance())->switchPageBack();
     } else {
         point.setX(point.x() + width);
+        physics->setEnabled(false);
         viewport->setPosition(point);
+        physics->setEnabled(true);
         updateSnapInterval();
     }
 }
@@ -153,6 +165,9 @@
             updateView(model()->stripIndex());
             startSlideShow();
         }
+
+        if (member == PhotoStripModel::StripSmall)
+            setStripSmall(model()->stripSmall());
     }
 }
 
@@ -213,7 +228,9 @@
         while (!itemList.isEmpty()) {
             StripItem *item = static_cast<StripItem *>(itemList.first());
             itemList.removeFirst();
+            qDebug() << "item is " << item;
             delete item;
+            qDebug() << "after delet item\n";
         }
         widgets.clear();
 
@@ -256,7 +273,9 @@
     }
 
     int width = (AppWindow::instance())->visibleSceneSize().width() + ITEM_SPACING;
+    physics->setEnabled(false);
     viewport->setPosition(QPointF(focusedWidget * width, 0));
+    physics->setEnabled(true);
     QVariant focusedData = currentModel->data(currentModel->index(focusedWidget, 0),
                                                             Qt::DisplayRole);
     MPListItem *focusedItem = static_cast<MPListItem *>(focusedData.value<void *>());
@@ -265,6 +284,16 @@
     updateSnapInterval();
 }
 
+void PhotoStripView::setStripSmall(bool on)
+{
+    QList<StripItem *> itemList = widgets.values();
+    while (!itemList.isEmpty()) {
+        StripItem *item = static_cast<StripItem *>(itemList.first());
+        itemList.removeFirst();
+        item->StripImgView()->setStyleSmall(on);
+    }
+}
+
 void PhotoStripView::startSlideShow()
 {
     timer->start();
--- photostripview.h
+++ photostripview.h
@@ -32,6 +32,7 @@
     Q_OBJECT
     virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
     virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+    virtual void cancelEvent(MCancelEvent *event);
 
 Q_SIGNALS:
     void mousePress();
@@ -67,6 +68,8 @@
 private:
     void updateView(QString query);
     void updateView(QModelIndex stripIndex);
+    void setStripSmall(bool on);
+
     void updateSnapInterval();
     void startSlideShow();
 
--- searchengine.cpp
+++ searchengine.cpp
@@ -30,7 +30,7 @@
 
 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 nao:Tag } WHERE {?imagelist nao:hasTag ?tag . ?tag nao:identifier 'AlbumCover' . " \
+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') }";
@@ -41,9 +41,12 @@
                                          " 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 nao:Tag } WHERE {?object nao:hasTag ?tag . ?tag nao:identifier '%1' . " \
+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)
 {
     qDebug() << "SearchEngine::getAllPhoto " << SqlGetAllPhoto;
@@ -193,3 +196,27 @@
 
     return TRUE;
 }
+
+QString SearchEngine::getUrl(const QString &objectURN)
+{
+    QString sql = QString(SqlGetUrlFromURN).arg(objectURN);
+    QString url;
+
+    qDebug() << "SearchEngine::getUrl " << sql;
+
+    QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+    url = result[0][0];
+    return url;
+}
+
+QString SearchEngine::getMimeType(const QString &objectURN)
+{
+    QString sql = QString(SqlGetMimeTypeFromURN).arg(objectURN);
+    QString mimeType;
+
+    qDebug() << "SearchEngine::getMimeType " << sql;
+
+    QVector<QStringList> result = ::tracker()->rawSparqlQuery(sql);
+    mimeType = result[0][0];
+    return mimeType;
+}
--- searchengine.h
+++ searchengine.h
@@ -47,5 +47,10 @@
 
     /// @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);
 };
 #endif
--- stripimagemodel.h
+++ stripimagemodel.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 STRIPIMAGEMODEL_H
+#define STRIPIMAGEMODEL_H
+
+#include <mimagewidgetmodel.h>
+
+class M_EXPORT StripImageModel : public MImageWidgetModel
+{
+    Q_OBJECT
+    M_MODEL(StripImageModel)
+};
+
+#endif // STRIPIMAGEMODEL_H
--- stripimagestyle.h
+++ stripimagestyle.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 STRIPIMAGESTYLE_H
+#define STRIPIMAGESTYLE_H
+
+#include <mimagewidgetstyle.h>
+
+class StripImageStyle : public MImageWidgetStyle
+{
+    Q_OBJECT
+    M_STYLE(StripImageStyle)
+};
+
+class StripImageStyleContainer : public MImageWidgetStyleContainer
+{
+    M_STYLE_CONTAINER(StripImageStyle)
+    M_STYLE_MODE(Small)
+};
+
+
+#endif // STRIPIMAGESTYLE_H
--- stripimageview.cpp
+++ stripimageview.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 "stripimageview.h"
+#include <QtGui>
+
+StripImageView::StripImageView(MImageWidget *controller) :
+    MImageWidgetView(controller)
+{
+}
+
+void StripImageView::setStyleSmall(bool on)
+{
+    if (on)
+        style().setModeSmall();
+    else
+        style().setModeDefault();
+    update();
+}
+
+StripImageView::~StripImageView()
+{
+}
--- stripimageview.h
+++ stripimageview.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 STRIPIMAGEVIEW_H
+#define STRIPIMAGEVIEW_H
+
+#include <mimagewidgetview.h>
+#include "stripimagestyle.h"
+#include "stripimagemodel.h"
+#include <mimagewidget.h>
+
+class StripImageView : public MImageWidgetView
+{
+    Q_OBJECT
+    M_VIEW(StripImageModel, StripImageStyle)
+
+public:
+    StripImageView(MImageWidget *controller);
+    virtual ~StripImageView();
+    void updateStyleMode(int mode);
+    void setStyleSmall(bool on);
+
+};
+
+#endif // STRIPIMAGEVIEW_H
--- stripitem.cpp
+++ stripitem.cpp
@@ -12,6 +12,7 @@
 #include "stripitem.h"
 #include "appwindow.h"
 #include "photostripview.h"
+#include "stripimageview.h"
 #include <QtGui>
 #include <MAction>
 #include <MImageWidget>
@@ -22,7 +23,7 @@
 }
 
 StripItem::StripItem(QString uri, PhotoStripView *view) :
-    stripURI(uri), isLoaded(false), stripView(view)
+    stripURI(uri), isLoaded(false), stripView(view), photoListDeleteConfirm(NULL)
 {
     
     qDebug() << "StripItem uri" << uri;
@@ -30,7 +31,10 @@
         defaultPic = const_cast<QPixmap *>(MTheme::pixmap("defaultThumbnail"));
 
     stripImg = new MImageWidget();
-    stripImg->setObjectName("PhotoStripImage");
+    stripImgView = new StripImageView(stripImg);
+    stripImg->setView(stripImgView);
+    //stripImg->setObjectName("PhotoStripImage");
+    
     stripImg->setPixmap(*defaultPic);
 
     MAction* ssAction = new MAction ("Slide Show", stripImg);
@@ -73,6 +77,8 @@
 {
     unload();
     delete stripImg;
+    if (photoListDeleteConfirm)
+        delete photoListDeleteConfirm;
 }
 
 MImageWidget* StripItem::StripImg()
@@ -80,6 +86,11 @@
     return stripImg;
 }
 
+StripImageView* StripItem::StripImgView()
+{
+    return stripImgView;
+}
+
 void StripItem::load()
 {
     if (isLoaded)
@@ -117,8 +128,22 @@
 
 void StripItem::copyPhoto()
 {
-    QAbstractItemModel *model = AppWindow::instance()->photoList->itemModel();
-    model->insertRow(stripView->getFocusedWidget());
+    QUrl url = QUrl::fromEncoded(stripURI.toAscii());
+    QString path = url.path();
+    QStringList list = path.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(path, targetString);
 }
 
 void StripItem::rotateCW()
@@ -138,7 +163,11 @@
 void StripItem::deletePhoto()
 {
     /* delete photo */
-    QAbstractItemModel *model = AppWindow::instance()->photoList->itemModel();
-    model->removeRow(stripView->getFocusedWidget());
+    QUrl url = QUrl::fromEncoded(stripURI.toAscii());
+    QString path = url.path();
+    if (!photoListDeleteConfirm)
+        photoListDeleteConfirm = new PhotoListDeleteConfirm();
+    photoListDeleteConfirm->setFile(path);
+    AppWindow::instance()->deletePhoto(path, photoListDeleteConfirm);
 }
 
--- stripitem.h
+++ stripitem.h
@@ -14,10 +14,14 @@
 
 #include <QtGui>
 
+#include "photolistdeleteconfirm.h"
+
 class MImageWidget;
+class StripImageView;
 class PhotoStripView;
 
 
+
 class StripItem : public QObject
 {
 Q_OBJECT
@@ -26,6 +30,7 @@
     StripItem(QString uri, PhotoStripView *view);
     virtual ~StripItem();
     MImageWidget* StripImg();
+    StripImageView* StripImgView();
     void load();
     void unload();
 
@@ -41,10 +46,12 @@
 private:
     explicit StripItem(); // disable default constructor
     MImageWidget *stripImg;
+    StripImageView *stripImgView;
     QString stripURI;
     bool isLoaded;
     static QPixmap *defaultPic;
     PhotoStripView *stripView;
+    PhotoListDeleteConfirm *photoListDeleteConfirm;
 };
 
 #endif // STRIPITEM_H
--- themes/style/meegophotos.css
+++ themes/style/meegophotos.css
@@ -1,5 +1,5 @@
 /* 
- * Copyright (c) 2010, Nokia Corporation. 
+  Copyright (c) 2010, Nokia Corporation. 
  * Copyright (c) 2010, Intel Corporation.                               
  *  
  * This program is free software; you can redistribute it and/or modify it
@@ -209,6 +209,39 @@
 
 }
 
+StripImageStyle {
+    minimum-size: 100% $SINGLE_PHOTO_H;
+    maximum-size: 100% $SINGLE_PHOTO_H;
+    preferred-size: 100% $SINGLE_PHOTO_H;
+
+    margin-top: 0;
+    margin-left: 0;
+    margin-bottom: 0;
+    margin-right: 0;
+
+    padding-top: 0;
+    padding-left: 0;
+    padding-right: 0;
+    padding-bottom: 0;
+}
+
+StripImageStyle:small {
+    minimum-size: 100% $SINGLE_PHOTO_H;
+    maximum-size: 100% $SINGLE_PHOTO_H;
+    preferred-size: 100% $SINGLE_PHOTO_H;
+
+    margin-top: 135;
+    margin-left: 0;
+    margin-bottom: 100;
+    margin-right: 0;
+
+    padding-top: 0;
+    padding-left: 0;
+    padding-right: 0;
+    padding-bottom: 0;
+
+}
+
 #AllPhotos {
     margin-left: 0;
     margin-top: 0;
@@ -383,7 +416,7 @@
 	maximum-size: 100% -1;
 
 	margin-left: 0;
-	margin-top: 0;
+	margin-top: 30px;
 	margin-right: 0;
 	margin-bottom: 0;
 	padding-left: 0px;
@@ -1164,3 +1197,21 @@
     padding-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;
+
+}
+
+#deleteConfirmDialog {
+    vertical-align: center;
+    offset: 0 -80px;
+}
--- thumbnailer.cpp
+++ thumbnailer.cpp
@@ -35,11 +35,20 @@
     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()
--- thumbnailer.h
+++ thumbnailer.h
@@ -120,10 +120,14 @@
     /// @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
--- trackerlistener.cpp
+++ trackerlistener.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 "trackerlistener.h"
+
+const QString TrackerListener::service = "org.freedesktop.Tracker1";
+const QString TrackerListener::path = "/org/freedesktop/Tracker1/Resources/Classes/nfo/Image";
+const char   *TrackerListener::interface = "org.freedesktop.Tracker1.Resources.Class";
+
+TrackerListener *TrackerListener::trackerListenerInstance = NULL;
+
+TrackerListener *TrackerListener::instance()
+{
+    if (trackerListenerInstance)
+        return trackerListenerInstance;
+    else {
+        trackerListenerInstance = new TrackerListener(QDBusConnection::sessionBus(), NULL);
+        return trackerListenerInstance;
+    }
+}
+
+
+void TrackerListener::emitSubjectsChangedSignal(const QStringList &subject, const QStringList &predicates)
+{
+    qDebug() << "TrackerListener::emitSubjectsChangedSignal " << subject << " " << predicates;
+    emit SubjectsChanged(subject, predicates);
+}
+
+void TrackerListener::emitSubjectsAddedSignal(const QStringList &subjects)
+{
+    qDebug() << "TrackerListener::emitSubjectsAddedSignal " << subjects;
+    emit SubjectsAdded(subjects);
+}
+
+void TrackerListener::emitSubjectsRemovedSignal(const QStringList &subjects)
+{
+    qDebug() << "TrackerListener::emitSubjectsRemovedSignal " << subjects;
+    emit SubjectsRemoved(subjects);
+}
+
+
+TrackerListener::TrackerListener(const QDBusConnection &connection, QObject *parent) :
+        QDBusAbstractInterface(service, path, interface, connection, parent)
+{
+
+    qDebug() << "TrackerListener try to connect SubjectsChanged ";
+    QDBusConnection::sessionBus().connect(service, path, interface,
+                                    "SubjectsChanged", this, SLOT(emitSubjectsChangedSignal(const QStringList, const QStringList)));
+
+    qDebug() << "TrackerListener try to connect SubjectsAdded ";
+    QDBusConnection::sessionBus().connect(service, path, interface,
+                                    "SubjectsAdded", this, SLOT(emitSubjectsAddedSignal(const QStringList)));
+
+    qDebug() << "TrackerListener try to connect SubjectsRemoved ";
+    QDBusConnection::sessionBus().connect(service, path, interface,
+                                    "SubjectsRemoved", this, SLOT(emitSubjectsRemovedSignal(const QStringList)));
+}
+
+TrackerListener::~TrackerListener()
+{
+    qDebug() << "TrackerListener::~TrackerListener()";
+}
--- trackerlistener.h
+++ trackerlistener.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 TRACKERLISTENER_H
+#define TRACKERLISTENER_H
+
+#include <QtCore/QtCore>
+#include <QtCore/QObject>
+#include <QtDBus/QtDBus>
+
+
+class TrackerListener: public QDBusAbstractInterface
+{
+    Q_OBJECT
+public:
+
+    static TrackerListener *instance();
+
+    /// @brief Destructor
+    ~TrackerListener();
+
+private:
+    // Constructor is private because this is a singleton.
+    // Construct it using the instance() method.
+    TrackerListener(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;
+
+    static TrackerListener *trackerListenerInstance;
+
+public Q_SLOTS:
+
+
+    void emitSubjectsChangedSignal(const QStringList &subject, const QStringList &predicates);
+
+    void emitSubjectsAddedSignal(const QStringList &subjects);
+
+    void emitSubjectsRemovedSignal(const QStringList &subjects);
+
+signals:
+
+    void SubjectsChanged(const QStringList &subject, const QStringList &predicates);
+
+    void SubjectsAdded(const QStringList &subjects);
+
+    void SubjectsRemoved(const QStringList &subjects);
+};
+#endif

++++++ 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.18
+Version: 0.0.19
 Release: 1
 Group: System/Libraries
 License:  Apache License, Version 2.0



More information about the MeeGo-commits mailing list