current "What's missing" points ( wich are also "help me on this" )
1 - delete the pictures struct when the file closes 2 - load the saved picture 3 - correct the position the pictures on the profile 4 - smaller pixmap on the profile, 4 - smooth animation on "hover" to make it a bit bigger, but not much while moving the mouse around 5 - display the full picture on "click" 6 - close the full picture somehow
From 21dd441a5dabd30ac1e0477c09a847cefa77ceb5 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava <[email protected]> Date: Tue, 3 Jun 2014 14:26:27 -0300 Subject: [PATCH 1/7] Add photo saving for the XML backend. This code correctly saves the added pictures on the xml backend. next: git backend. Signed-off-by: Tomaz Canabrava <[email protected]> --- save-xml.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/save-xml.c b/save-xml.c index e52cfdf..f2cb17d 100644 --- a/save-xml.c +++ b/save-xml.c @@ -369,6 +369,17 @@ static void save_dc(struct membuffer *b, struct dive *dive, struct divecomputer put_format(b, " </divecomputer>\n"); } +static void save_picture(struct membuffer *b, struct picture *pic){ + put_string(b, " <picture filename='"); + put_string(b, pic->filename); + put_string(b, "'"); + if (pic->latitude.udeg || pic->longitude.udeg) { + put_degrees(b, pic->latitude, " gps='", " "); + put_degrees(b, pic->longitude, "", "'"); + } + put_string(b, "/>\n"); +} + void save_one_dive(struct membuffer *b, struct dive *dive) { struct divecomputer *dc; @@ -394,6 +405,8 @@ void save_one_dive(struct membuffer *b, struct dive *dive) /* Save the dive computer data */ for_each_dc(dive, dc) save_dc(b, dive, dc); + FOR_EACH_PICTURE(dive) + save_picture(b, picture); put_format(b, "</dive>\n"); } -- 2.0.0
From 1fdd42eb4eeed8441b5f8e701efae3cbf4219a4c Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava <[email protected]> Date: Tue, 3 Jun 2014 14:51:47 -0300 Subject: [PATCH 2/7] Fix linked list corruption, move code to C. The picture list is a single linked list where the pictures have a node to it's next element. When adding the same picture to two dives, things got way way wrong and crashes were appearing. this will replicate the information (filename, latitude and longitude) for each dive that has the picture, BUT it still tries to save as much as possible on the actual pixmap. Signed-off-by: Tomaz Canabrava <[email protected]> --- dive.c | 11 +++++++++++ dive.h | 1 + qt-ui/divelistview.cpp | 9 +-------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/dive.c b/dive.c index 065d455..52a95ef 100644 --- a/dive.c +++ b/dive.c @@ -2269,6 +2269,17 @@ struct picture *alloc_picture() return pic; } +void dive_create_picture(struct dive *d, char *filename, int shift_time) +{ + struct picture *p = alloc_picture(); + if (p->timestamp) + p->timestamp += shift_time; + p->filename = filename; + picture_load_exif_data(p); + dive_add_picture(d, p); + dive_set_geodata_from_picture(d, p); +} + void dive_add_picture(struct dive *d, struct picture *picture) { if (d->picture_list == NULL) { diff --git a/dive.h b/dive.h index 7372781..cdef2cd 100644 --- a/dive.h +++ b/dive.h @@ -297,6 +297,7 @@ struct picture { extern struct picture *alloc_picture(); +extern void dive_create_picture(struct dive *d, char *filename, int shift_time); extern void dive_add_picture(struct dive *d, struct picture *pic); extern void dive_remove_picture(struct dive *d, struct picture *pic); extern unsigned int dive_get_picture_count(struct dive *d); diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp index 57ad3f2..78186ec 100644 --- a/qt-ui/divelistview.cpp +++ b/qt-ui/divelistview.cpp @@ -775,19 +775,12 @@ void DiveListView::loadImages() updateLastImageTimeOffset(shiftDialog.amount()); Q_FOREACH(const QString& fileName, fileNames) { - picture *p = alloc_picture(); - p->filename = qstrdup(fileName.toUtf8().data()); - picture_load_exif_data(p); - - if (p->timestamp) - p->timestamp += shiftDialog.amount(); // TODO: this should be cached and passed to the C-function int j = 0; struct dive *dive; for_each_dive (j, dive) { if (!dive->selected) continue; - dive_add_picture(dive, p); - dive_set_geodata_from_picture(dive, p); + dive_create_picture(dive, qstrdup(fileName.toUtf8().data()), shiftDialog.amount()); } } -- 2.0.0
From 8aad7b7da47d1d8bb8f69456ab51a33b54377370 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava <[email protected]> Date: Tue, 3 Jun 2014 19:04:50 -0300 Subject: [PATCH 3/7] Add a static 'instance()' member for the Photos model. This will make referencing it from a few places more easy. Signed-off-by: Tomaz Canabrava <[email protected]> --- qt-ui/divepicturewidget.cpp | 8 +++++++- qt-ui/divepicturewidget.h | 3 ++- qt-ui/maintab.cpp | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/qt-ui/divepicturewidget.cpp b/qt-ui/divepicturewidget.cpp index e5824e6..5da7c73 100644 --- a/qt-ui/divepicturewidget.cpp +++ b/qt-ui/divepicturewidget.cpp @@ -8,7 +8,13 @@ void DivePictureDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o QStyledItemDelegate::paint(painter, option, index); } -DivePictureModel::DivePictureModel(QObject *parent): QAbstractTableModel(parent) +DivePictureModel *DivePictureModel::instance() +{ + static DivePictureModel* self = new DivePictureModel(); + return self; +} + +DivePictureModel::DivePictureModel() { } diff --git a/qt-ui/divepicturewidget.h b/qt-ui/divepicturewidget.h index 4660bd0..351ae44 100644 --- a/qt-ui/divepicturewidget.h +++ b/qt-ui/divepicturewidget.h @@ -9,12 +9,13 @@ class DivePictureModel : public QAbstractTableModel { Q_OBJECT public: - DivePictureModel(QObject *parent); + static DivePictureModel *instance(); virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; void updateDivePictures(int divenr); private: + DivePictureModel(); int numberOfPictures; // Currently, load the images on the fly // Later, use a thread to load the images diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 7c28a49..90af5ba 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -31,7 +31,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), weightModel(new WeightModel(this)), cylindersModel(CylindersModel::instance()), editMode(NONE), - divePictureModel(new DivePictureModel(this)) + divePictureModel(DivePictureModel::instance()) { ui.setupUi(this); -- 2.0.0
From ff0d95214bf53258ba2f15e00a6702d88dece441 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava <[email protected]> Date: Tue, 3 Jun 2014 19:09:12 -0300 Subject: [PATCH 4/7] Connect & Disconnect the PictureModel on the Profile ignore the warnings for now, this patch connects and disconnects the (not done yet) plotPictures() method. Signed-off-by: Tomaz Canabrava <[email protected]> --- qt-ui/profile/profilewidget2.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/qt-ui/profile/profilewidget2.cpp b/qt-ui/profile/profilewidget2.cpp index ccdbe18..af2480e 100644 --- a/qt-ui/profile/profilewidget2.cpp +++ b/qt-ui/profile/profilewidget2.cpp @@ -701,6 +701,11 @@ void ProfileWidget2::setProfileState() return; disconnectTemporaryConnections(); + connect(DivePictureModel::instance(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(plotPictures())); + connect(DivePictureModel::instance(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),this, SLOT(plotPictureS())); + connect(DivePictureModel::instance(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),this, SLOT(plotPictures())); + /* show the same stuff that the profile shows. */ + //TODO: Move the DC handling to another method. MainWindow::instance()->enableDcShortcuts(); @@ -1044,6 +1049,10 @@ void ProfileWidget2::disconnectTemporaryConnections() disconnect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), this, SLOT(pointsRemoved(const QModelIndex &, int, int))); + disconnect(DivePictureModel::instance(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(plotPictures())); + disconnect(DivePictureModel::instance(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),this, SLOT(plotPictureS())); + disconnect(DivePictureModel::instance(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),this, SLOT(plotPictures())); + Q_FOREACH (QAction *action, actionsForKeys.values()) action->setShortcut(QKeySequence()); } -- 2.0.0
From c66ad96956e84c50383bf1322eced3368c126516 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava <[email protected]> Date: Tue, 3 Jun 2014 19:24:01 -0300 Subject: [PATCH 5/7] Added a method to plot the pictures on the profile. It plots on the wrong place for now, because I need to change the model a bit. but it shares the same pixmap on the other widget wich is nice. :) Signed-off-by: Tomaz Canabrava <[email protected]> --- qt-ui/profile/profilewidget2.cpp | 20 ++++++++++++++++++-- qt-ui/profile/profilewidget2.h | 2 ++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/qt-ui/profile/profilewidget2.cpp b/qt-ui/profile/profilewidget2.cpp index af2480e..a42eaee 100644 --- a/qt-ui/profile/profilewidget2.cpp +++ b/qt-ui/profile/profilewidget2.cpp @@ -702,7 +702,7 @@ void ProfileWidget2::setProfileState() disconnectTemporaryConnections(); connect(DivePictureModel::instance(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(plotPictures())); - connect(DivePictureModel::instance(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),this, SLOT(plotPictureS())); + connect(DivePictureModel::instance(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),this, SLOT(plotPictures())); connect(DivePictureModel::instance(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),this, SLOT(plotPictures())); /* show the same stuff that the profile shows. */ @@ -1050,7 +1050,7 @@ void ProfileWidget2::disconnectTemporaryConnections() this, SLOT(pointsRemoved(const QModelIndex &, int, int))); disconnect(DivePictureModel::instance(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(plotPictures())); - disconnect(DivePictureModel::instance(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),this, SLOT(plotPictureS())); + disconnect(DivePictureModel::instance(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),this, SLOT(plotPictures())); disconnect(DivePictureModel::instance(), SIGNAL(rowsRemoved(const QModelIndex &, int, int)),this, SLOT(plotPictures())); Q_FOREACH (QAction *action, actionsForKeys.values()) @@ -1286,3 +1286,19 @@ void ProfileWidget2::keyEscAction() if (plannerModel->isPlanner()) plannerModel->cancelPlan(); } + +void ProfileWidget2::plotPictures() +{ + qDeleteAll(pictures); + pictures.clear(); + + DivePictureModel *m = DivePictureModel::instance(); + for(int i = 0; i < m->rowCount(); i++){ + DivePixmapItem *item = new DivePixmapItem(); + item->setPixmap(m->index(i,0).data(Qt::DecorationRole).value<QPixmap>()); + item->setPos(10,10); // TODO: put the item in the correct place. + item->setFlag(QGraphicsItem::ItemIgnoresTransformations); + scene()->addItem(item); + pictures.push_back(item); + } +} diff --git a/qt-ui/profile/profilewidget2.h b/qt-ui/profile/profilewidget2.h index 9c76105..a1ba7a2 100644 --- a/qt-ui/profile/profilewidget2.h +++ b/qt-ui/profile/profilewidget2.h @@ -91,6 +91,7 @@ slots: // Necessary to call from QAction's signals. void makeFirstDC(); void pointInserted(const QModelIndex &parent, int start, int end); void pointsRemoved(const QModelIndex &, int start, int end); + void plotPictures(); void replot(); /* this is called for every move on the handlers. maybe we can speed up this a bit? */ @@ -159,6 +160,7 @@ private: //specifics for ADD and PLAN QList<DiveHandler *> handles; QList<QGraphicsSimpleTextItem *> gases; + QList<DivePixmapItem*> pictures; void repositionDiveHandlers(); int fixHandlerIndex(DiveHandler *activeHandler); friend class DiveHandler; -- 2.0.0
From 95bd475b81ad802b369c8365bd16b28894d7e2a6 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava <[email protected]> Date: Tue, 3 Jun 2014 19:34:36 -0300 Subject: [PATCH 6/7] Also hold a pointer to the struct picture on the model. Changes to hold a pointer to the struct picture on the model, so we can use it to determine the correct positioning of the image on the profile. Signed-off-by: Tomaz Canabrava <[email protected]> --- qt-ui/divepicturewidget.cpp | 23 ++++++++++++++++------- qt-ui/divepicturewidget.h | 8 +++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/qt-ui/divepicturewidget.cpp b/qt-ui/divepicturewidget.cpp index 5da7c73..97b7bd2 100644 --- a/qt-ui/divepicturewidget.cpp +++ b/qt-ui/divepicturewidget.cpp @@ -43,15 +43,17 @@ void DivePictureModel::updateDivePictures(int divenr) return; } + stringPixmapCache.clear(); QStringList pictures; FOR_EACH_PICTURE( d ) { + stringPixmapCache[QString(picture->filename)].picture = picture; pictures.push_back(QString(picture->filename)); } - stringPixmapCache.clear(); + SPixmapList retList = QtConcurrent::blockingMapped<SPixmapList>( pictures, scaleImages); Q_FOREACH(const SPixmap & pixmap, retList) - stringPixmapCache[pixmap.first] = pixmap.second; + stringPixmapCache[pixmap.first].image = pixmap.second; beginInsertRows(QModelIndex(), 0, numberOfPictures-1); endInsertRows(); @@ -59,7 +61,7 @@ void DivePictureModel::updateDivePictures(int divenr) int DivePictureModel::columnCount(const QModelIndex &parent) const { - return 1; + return 2; } QVariant DivePictureModel::data(const QModelIndex &index, int role) const @@ -69,10 +71,17 @@ QVariant DivePictureModel::data(const QModelIndex &index, int role) const return ret; QString key = stringPixmapCache.keys().at(index.row()); - switch(role){ - case Qt::ToolTipRole : ret = key; break; - case Qt::DecorationRole : ret = stringPixmapCache[key]; break; - case Qt::DisplayRole : ret = QFileInfo(key).fileName(); + if(index.column() == 0){ + switch(role){ + case Qt::ToolTipRole : ret = key; break; + case Qt::DecorationRole : ret = stringPixmapCache[key].image; break; + case Qt::DisplayRole : ret = QFileInfo(key).fileName(); + } + } + else if (index.column() == 1){ + switch(role){ + case Qt::UserRole : ret = QVariant::fromValue( (void*) stringPixmapCache[key].picture); + } } return ret; } diff --git a/qt-ui/divepicturewidget.h b/qt-ui/divepicturewidget.h index 351ae44..d66b305 100644 --- a/qt-ui/divepicturewidget.h +++ b/qt-ui/divepicturewidget.h @@ -6,6 +6,12 @@ #include <QListView> #include <QThread> +struct picture; +struct PhotoHelper{ + QImage image; + struct picture *picture; +}; + class DivePictureModel : public QAbstractTableModel { Q_OBJECT public: @@ -20,7 +26,7 @@ private: // Currently, load the images on the fly // Later, use a thread to load the images // Later, save the thumbnails so we don't need to reopen every time. - QHash<QString, QImage> stringPixmapCache; + QHash<QString, PhotoHelper> stringPixmapCache; }; class DivePictureDelegate : QStyledItemDelegate { -- 2.0.0
From 948afc0fbc7ca5bbe0c7c8e6fb477b169a7df7e9 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava <[email protected]> Date: Tue, 3 Jun 2014 19:42:47 -0300 Subject: [PATCH 7/7] Do not plot pictures that doesn't have a timestamp. Signed-off-by: Tomaz Canabrava <[email protected]> --- qt-ui/profile/profilewidget2.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/qt-ui/profile/profilewidget2.cpp b/qt-ui/profile/profilewidget2.cpp index a42eaee..8b0a34a 100644 --- a/qt-ui/profile/profilewidget2.cpp +++ b/qt-ui/profile/profilewidget2.cpp @@ -1294,9 +1294,15 @@ void ProfileWidget2::plotPictures() DivePictureModel *m = DivePictureModel::instance(); for(int i = 0; i < m->rowCount(); i++){ + struct picture *pic = (struct picture*) m->index(i,1).data(Qt::UserRole).value<void*>(); + // it's a correct picture, but doesn't have a timestamp: only show on the widget near the + // information area. + if(!pic->timestamp) + continue; DivePixmapItem *item = new DivePixmapItem(); item->setPixmap(m->index(i,0).data(Qt::DecorationRole).value<QPixmap>()); - item->setPos(10,10); // TODO: put the item in the correct place. + // TODO: put the item in the correct place. use the pic.timestamp to find where it belongs on the dive. + item->setPos(10 ,10); item->setFlag(QGraphicsItem::ItemIgnoresTransformations); scene()->addItem(item); pictures.push_back(item); -- 2.0.0
_______________________________________________ subsurface mailing list [email protected] http://lists.hohndel.org/cgi-bin/mailman/listinfo/subsurface
