aboutsummaryrefslogtreecommitdiffstats
path: root/desktop-widgets/locationinformation.cpp
diff options
context:
space:
mode:
authorGravatar Tomaz Canabrava <tomaz.canabrava@intel.com>2015-09-03 14:20:19 -0300
committerGravatar Dirk Hohndel <dirk@hohndel.org>2015-10-30 10:36:49 -0700
commite49d6213ad129284a45d53c3fcdc03249e84efe2 (patch)
tree2946a666ab38af3375e7bb2b8c5dd887d4a7f9a1 /desktop-widgets/locationinformation.cpp
parent588abd019fb2ed3f607682f2b6c7fe86a7a5bb90 (diff)
downloadsubsurface-e49d6213ad129284a45d53c3fcdc03249e84efe2.tar.gz
Move qt-ui to desktop-widgets
Since we have now destkop and mobile versions, 'qt-ui' was a very poor name choice for a folder that contains only destkop-enabled widgets. Also, move the graphicsview-common.h/cpp to subsurface-core because it doesn't depend on qgraphicsview, it merely implements all the colors that we use throughout Subsurface, and we will use colors on both desktop and mobile versions Same thing applies for metrics.h/cpp Signed-off-by: Tomaz Canabrava <tomaz.canabrava@intel.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'desktop-widgets/locationinformation.cpp')
-rw-r--r--desktop-widgets/locationinformation.cpp618
1 files changed, 618 insertions, 0 deletions
diff --git a/desktop-widgets/locationinformation.cpp b/desktop-widgets/locationinformation.cpp
new file mode 100644
index 000000000..aee0b7328
--- /dev/null
+++ b/desktop-widgets/locationinformation.cpp
@@ -0,0 +1,618 @@
+#include "locationinformation.h"
+#include "dive.h"
+#include "mainwindow.h"
+#include "divelistview.h"
+#include "qthelper.h"
+#include "globe.h"
+#include "filtermodels.h"
+#include "divelocationmodel.h"
+#include "divesitehelpers.h"
+#include "modeldelegates.h"
+
+#include <QDebug>
+#include <QShowEvent>
+#include <QItemSelectionModel>
+#include <qmessagebox.h>
+#include <cstdlib>
+#include <QDesktopWidget>
+#include <QScrollBar>
+
+LocationInformationWidget::LocationInformationWidget(QWidget *parent) : QGroupBox(parent), modified(false)
+{
+ ui.setupUi(this);
+ ui.diveSiteMessage->setCloseButtonVisible(false);
+
+ acceptAction = new QAction(tr("Apply changes"), this);
+ connect(acceptAction, SIGNAL(triggered(bool)), this, SLOT(acceptChanges()));
+
+ rejectAction = new QAction(tr("Discard changes"), this);
+ connect(rejectAction, SIGNAL(triggered(bool)), this, SLOT(rejectChanges()));
+
+ ui.diveSiteMessage->setText(tr("Dive site management"));
+ ui.diveSiteMessage->addAction(acceptAction);
+ ui.diveSiteMessage->addAction(rejectAction);
+
+ connect(this, SIGNAL(startFilterDiveSite(uint32_t)), MultiFilterSortModel::instance(), SLOT(startFilterDiveSite(uint32_t)));
+ connect(this, SIGNAL(stopFilterDiveSite()), MultiFilterSortModel::instance(), SLOT(stopFilterDiveSite()));
+ connect(ui.geoCodeButton, SIGNAL(clicked()), this, SLOT(reverseGeocode()));
+
+ SsrfSortFilterProxyModel *filter_model = new SsrfSortFilterProxyModel(this);
+ filter_model->setSourceModel(LocationInformationModel::instance());
+ filter_model->setFilterRow(filter_same_gps_cb);
+ ui.diveSiteListView->setModel(filter_model);
+ ui.diveSiteListView->setModelColumn(LocationInformationModel::NAME);
+ ui.diveSiteListView->installEventFilter(this);
+#ifndef NO_MARBLE
+ // Globe Management Code.
+ connect(this, &LocationInformationWidget::requestCoordinates,
+ GlobeGPS::instance(), &GlobeGPS::prepareForGetDiveCoordinates);
+ connect(this, &LocationInformationWidget::endRequestCoordinates,
+ GlobeGPS::instance(), &GlobeGPS::endGetDiveCoordinates);
+ connect(GlobeGPS::instance(), &GlobeGPS::coordinatesChanged,
+ this, &LocationInformationWidget::updateGpsCoordinates);
+ connect(this, &LocationInformationWidget::endEditDiveSite,
+ GlobeGPS::instance(), &GlobeGPS::repopulateLabels);
+#endif
+}
+
+bool LocationInformationWidget::eventFilter(QObject *, QEvent *ev)
+{
+ if (ev->type() == QEvent::ContextMenu) {
+ QContextMenuEvent *ctx = (QContextMenuEvent *)ev;
+ QMenu contextMenu;
+ contextMenu.addAction(tr("Merge into current site"), this, SLOT(mergeSelectedDiveSites()));
+ contextMenu.exec(ctx->globalPos());
+ return true;
+ }
+ return false;
+}
+
+void LocationInformationWidget::mergeSelectedDiveSites()
+{
+ if (QMessageBox::warning(MainWindow::instance(), tr("Merging dive sites"),
+ tr("You are about to merge dive sites, you can't undo that action \n Are you sure you want to continue?"),
+ QMessageBox::Ok, QMessageBox::Cancel) != QMessageBox::Ok)
+ return;
+
+ QModelIndexList selection = ui.diveSiteListView->selectionModel()->selectedIndexes();
+ uint32_t *selected_dive_sites = (uint32_t *)malloc(sizeof(uint32_t) * selection.count());
+ int i = 0;
+ Q_FOREACH (const QModelIndex &idx, selection) {
+ selected_dive_sites[i] = (uint32_t)idx.data(LocationInformationModel::UUID_ROLE).toInt();
+ i++;
+ }
+ merge_dive_sites(displayed_dive_site.uuid, selected_dive_sites, i);
+ LocationInformationModel::instance()->update();
+ QSortFilterProxyModel *m = (QSortFilterProxyModel *)ui.diveSiteListView->model();
+ m->invalidate();
+ free(selected_dive_sites);
+}
+
+void LocationInformationWidget::updateLabels()
+{
+ if (displayed_dive_site.name)
+ ui.diveSiteName->setText(displayed_dive_site.name);
+ else
+ ui.diveSiteName->clear();
+ if (displayed_dive_site.description)
+ ui.diveSiteDescription->setText(displayed_dive_site.description);
+ else
+ ui.diveSiteDescription->clear();
+ if (displayed_dive_site.notes)
+ ui.diveSiteNotes->setPlainText(displayed_dive_site.notes);
+ else
+ ui.diveSiteNotes->clear();
+ if (displayed_dive_site.latitude.udeg || displayed_dive_site.longitude.udeg) {
+ const char *coords = printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg);
+ ui.diveSiteCoordinates->setText(coords);
+ free((void *)coords);
+ } else {
+ ui.diveSiteCoordinates->clear();
+ }
+
+ ui.locationTags->setText(constructLocationTags(displayed_dive_site.uuid));
+
+ emit startFilterDiveSite(displayed_dive_site.uuid);
+ emit startEditDiveSite(displayed_dive_site.uuid);
+}
+
+void LocationInformationWidget::updateGpsCoordinates()
+{
+ QString oldText = ui.diveSiteCoordinates->text();
+ const char *coords = printGPSCoords(displayed_dive_site.latitude.udeg, displayed_dive_site.longitude.udeg);
+ ui.diveSiteCoordinates->setText(coords);
+ free((void *)coords);
+ if (oldText != ui.diveSiteCoordinates->text())
+ markChangedWidget(ui.diveSiteCoordinates);
+}
+
+void LocationInformationWidget::acceptChanges()
+{
+ char *uiString;
+ struct dive_site *currentDs;
+ uiString = ui.diveSiteName->text().toUtf8().data();
+
+ if (get_dive_site_by_uuid(displayed_dive_site.uuid) != NULL)
+ currentDs = get_dive_site_by_uuid(displayed_dive_site.uuid);
+ else
+ currentDs = get_dive_site_by_uuid(create_dive_site_from_current_dive(uiString));
+
+ currentDs->latitude = displayed_dive_site.latitude;
+ currentDs->longitude = displayed_dive_site.longitude;
+ if (!same_string(uiString, currentDs->name)) {
+ free(currentDs->name);
+ currentDs->name = copy_string(uiString);
+ }
+ uiString = ui.diveSiteDescription->text().toUtf8().data();
+ if (!same_string(uiString, currentDs->description)) {
+ free(currentDs->description);
+ currentDs->description = copy_string(uiString);
+ }
+ uiString = ui.diveSiteNotes->document()->toPlainText().toUtf8().data();
+ if (!same_string(uiString, currentDs->notes)) {
+ free(currentDs->notes);
+ currentDs->notes = copy_string(uiString);
+ }
+ if (!ui.diveSiteCoordinates->text().isEmpty()) {
+ double lat, lon;
+ parseGpsText(ui.diveSiteCoordinates->text(), &lat, &lon);
+ currentDs->latitude.udeg = lat * 1000000.0;
+ currentDs->longitude.udeg = lon * 1000000.0;
+ }
+ if (dive_site_is_empty(currentDs)) {
+ LocationInformationModel::instance()->removeRow(get_divesite_idx(currentDs));
+ displayed_dive.dive_site_uuid = 0;
+ }
+ copy_dive_site(currentDs, &displayed_dive_site);
+ mark_divelist_changed(true);
+ resetState();
+ emit endRequestCoordinates();
+ emit endEditDiveSite();
+ emit stopFilterDiveSite();
+ emit coordinatesChanged();
+}
+
+void LocationInformationWidget::rejectChanges()
+{
+ resetState();
+ emit endRequestCoordinates();
+ emit stopFilterDiveSite();
+ emit endEditDiveSite();
+ emit coordinatesChanged();
+}
+
+void LocationInformationWidget::showEvent(QShowEvent *ev)
+{
+ if (displayed_dive_site.uuid) {
+ updateLabels();
+ ui.geoCodeButton->setEnabled(dive_site_has_gps_location(&displayed_dive_site));
+ QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel *>(ui.diveSiteListView->model());
+ emit startFilterDiveSite(displayed_dive_site.uuid);
+ if (m)
+ m->invalidate();
+ }
+ emit requestCoordinates();
+
+ QGroupBox::showEvent(ev);
+}
+
+void LocationInformationWidget::markChangedWidget(QWidget *w)
+{
+ QPalette p;
+ qreal h, s, l, a;
+ if (!modified)
+ enableEdition();
+ qApp->palette().color(QPalette::Text).getHslF(&h, &s, &l, &a);
+ p.setBrush(QPalette::Base, (l <= 0.3) ? QColor(Qt::yellow).lighter() : (l <= 0.6) ? QColor(Qt::yellow).light() : /* else */ QColor(Qt::yellow).darker(300));
+ w->setPalette(p);
+ modified = true;
+}
+
+void LocationInformationWidget::resetState()
+{
+ modified = false;
+ resetPallete();
+ MainWindow::instance()->dive_list()->setEnabled(true);
+ MainWindow::instance()->setEnabledToolbar(true);
+ ui.diveSiteMessage->setText(tr("Dive site management"));
+}
+
+void LocationInformationWidget::enableEdition()
+{
+ MainWindow::instance()->dive_list()->setEnabled(false);
+ MainWindow::instance()->setEnabledToolbar(false);
+ ui.diveSiteMessage->setText(tr("You are editing a dive site"));
+}
+
+void LocationInformationWidget::on_diveSiteCoordinates_textChanged(const QString &text)
+{
+ uint lat = displayed_dive_site.latitude.udeg;
+ uint lon = displayed_dive_site.longitude.udeg;
+ const char *coords = printGPSCoords(lat, lon);
+ if (!same_string(qPrintable(text), coords)) {
+ double latitude, longitude;
+ if (parseGpsText(text, &latitude, &longitude)) {
+ displayed_dive_site.latitude.udeg = latitude * 1000000;
+ displayed_dive_site.longitude.udeg = longitude * 1000000;
+ markChangedWidget(ui.diveSiteCoordinates);
+ emit coordinatesChanged();
+ ui.geoCodeButton->setEnabled(latitude != 0 && longitude != 0);
+ } else {
+ ui.geoCodeButton->setEnabled(false);
+ }
+ }
+ free((void *)coords);
+}
+
+void LocationInformationWidget::on_diveSiteDescription_textChanged(const QString &text)
+{
+ if (!same_string(qPrintable(text), displayed_dive_site.description))
+ markChangedWidget(ui.diveSiteDescription);
+}
+
+void LocationInformationWidget::on_diveSiteName_textChanged(const QString &text)
+{
+ if (!same_string(qPrintable(text), displayed_dive_site.name))
+ markChangedWidget(ui.diveSiteName);
+}
+
+void LocationInformationWidget::on_diveSiteNotes_textChanged()
+{
+ if (!same_string(qPrintable(ui.diveSiteNotes->toPlainText()), displayed_dive_site.notes))
+ markChangedWidget(ui.diveSiteNotes);
+}
+
+void LocationInformationWidget::resetPallete()
+{
+ QPalette p;
+ ui.diveSiteCoordinates->setPalette(p);
+ ui.diveSiteDescription->setPalette(p);
+ ui.diveSiteName->setPalette(p);
+ ui.diveSiteNotes->setPalette(p);
+}
+
+void LocationInformationWidget::reverseGeocode()
+{
+ ReverseGeoLookupThread *geoLookup = ReverseGeoLookupThread::instance();
+ geoLookup->lookup(&displayed_dive_site);
+ updateLabels();
+}
+
+DiveLocationFilterProxyModel::DiveLocationFilterProxyModel(QObject *parent)
+{
+}
+
+DiveLocationLineEdit *location_line_edit = 0;
+
+bool DiveLocationFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
+{
+ if (source_row == 0)
+ return true;
+
+ QString sourceString = sourceModel()->index(source_row, DiveLocationModel::NAME).data(Qt::DisplayRole).toString();
+ return sourceString.toLower().startsWith(location_line_edit->text().toLower());
+}
+
+bool DiveLocationFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
+{
+ return source_left.data().toString() <= source_right.data().toString();
+}
+
+
+DiveLocationModel::DiveLocationModel(QObject *o)
+{
+ resetModel();
+}
+
+void DiveLocationModel::resetModel()
+{
+ beginResetModel();
+ endResetModel();
+}
+
+QVariant DiveLocationModel::data(const QModelIndex &index, int role) const
+{
+ static const QIcon plusIcon(":plus");
+ static const QIcon geoCode(":geocode");
+
+ if (index.row() <= 1) { // two special cases.
+ if (index.column() == UUID) {
+ return RECENTLY_ADDED_DIVESITE;
+ }
+ switch (role) {
+ case Qt::DisplayRole:
+ return new_ds_value[index.row()];
+ case Qt::ToolTipRole:
+ return displayed_dive_site.uuid ?
+ tr("Create a new dive site, copying relevant information from the current dive.") :
+ tr("Create a new dive site with this name");
+ case Qt::DecorationRole:
+ return plusIcon;
+ }
+ }
+
+ // The dive sites are -2 because of the first two items.
+ struct dive_site *ds = get_dive_site(index.row() - 2);
+ switch (role) {
+ case Qt::EditRole:
+ case Qt::DisplayRole:
+ switch (index.column()) {
+ case UUID:
+ return ds->uuid;
+ case NAME:
+ return ds->name;
+ case LATITUDE:
+ return ds->latitude.udeg;
+ case LONGITUDE:
+ return ds->longitude.udeg;
+ case DESCRIPTION:
+ return ds->description;
+ case NOTES:
+ return ds->name;
+ }
+ break;
+ case Qt::DecorationRole: {
+ if (dive_site_has_gps_location(ds))
+ return geoCode;
+ }
+ }
+ return QVariant();
+}
+
+int DiveLocationModel::columnCount(const QModelIndex &parent) const
+{
+ return COLUMNS;
+}
+
+int DiveLocationModel::rowCount(const QModelIndex &parent) const
+{
+ return dive_site_table.nr + 2;
+}
+
+bool DiveLocationModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!index.isValid())
+ return false;
+ if (index.row() > 1)
+ return false;
+
+ new_ds_value[index.row()] = value.toString();
+
+ dataChanged(index, index);
+ return true;
+}
+
+DiveLocationLineEdit::DiveLocationLineEdit(QWidget *parent) : QLineEdit(parent),
+ proxy(new DiveLocationFilterProxyModel()),
+ model(new DiveLocationModel()),
+ view(new DiveLocationListView()),
+ currType(NO_DIVE_SITE)
+{
+ currUuid = 0;
+ location_line_edit = this;
+
+ proxy->setSourceModel(model);
+ proxy->setFilterKeyColumn(DiveLocationModel::NAME);
+
+ view->setModel(proxy);
+ view->setModelColumn(DiveLocationModel::NAME);
+ view->setItemDelegate(new LocationFilterDelegate());
+ view->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view->setSelectionBehavior(QAbstractItemView::SelectRows);
+ view->setSelectionMode(QAbstractItemView::SingleSelection);
+ view->setParent(0, Qt::Popup);
+ view->installEventFilter(this);
+ view->setFocusPolicy(Qt::NoFocus);
+ view->setFocusProxy(this);
+ view->setMouseTracking(true);
+
+ connect(this, &QLineEdit::textEdited, this, &DiveLocationLineEdit::setTemporaryDiveSiteName);
+ connect(view, &QAbstractItemView::activated, this, &DiveLocationLineEdit::itemActivated);
+ connect(view, &QAbstractItemView::entered, this, &DiveLocationLineEdit::entered);
+ connect(view, &DiveLocationListView::currentIndexChanged, this, &DiveLocationLineEdit::currentChanged);
+}
+
+bool DiveLocationLineEdit::eventFilter(QObject *o, QEvent *e)
+{
+ if (e->type() == QEvent::KeyPress) {
+ QKeyEvent *keyEv = (QKeyEvent *)e;
+
+ if (keyEv->key() == Qt::Key_Escape) {
+ view->hide();
+ return true;
+ }
+
+ if (keyEv->key() == Qt::Key_Return ||
+ keyEv->key() == Qt::Key_Enter) {
+#if __APPLE__
+ // for some reason it seems like on a Mac hitting return/enter
+ // doesn't call 'activated' for that index. so let's do it manually
+ if (view->currentIndex().isValid())
+ itemActivated(view->currentIndex());
+#endif
+ view->hide();
+ return false;
+ }
+
+ if (keyEv->key() == Qt::Key_Tab) {
+ itemActivated(view->currentIndex());
+ view->hide();
+ return false;
+ }
+ event(e);
+ } else if (e->type() == QEvent::MouseButtonPress) {
+ if (!view->underMouse()) {
+ view->hide();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void DiveLocationLineEdit::focusOutEvent(QFocusEvent *ev)
+{
+ if (!view->isVisible()) {
+ QLineEdit::focusOutEvent(ev);
+ }
+}
+
+void DiveLocationLineEdit::itemActivated(const QModelIndex &index)
+{
+ QModelIndex idx = index;
+ if (index.column() == DiveLocationModel::UUID)
+ idx = index.model()->index(index.row(), DiveLocationModel::NAME);
+
+ QModelIndex uuidIndex = index.model()->index(index.row(), DiveLocationModel::UUID);
+ uint32_t uuid = uuidIndex.data().toInt();
+ currType = uuid == 1 ? NEW_DIVE_SITE : EXISTING_DIVE_SITE;
+ currUuid = uuid;
+ setText(idx.data().toString());
+ if (currUuid == NEW_DIVE_SITE)
+ qDebug() << "Setting a New dive site";
+ else
+ qDebug() << "Setting a Existing dive site";
+ if (view->isVisible())
+ view->hide();
+ emit diveSiteSelected(currUuid);
+}
+
+void DiveLocationLineEdit::refreshDiveSiteCache()
+{
+ model->resetModel();
+}
+
+static struct dive_site *get_dive_site_name_start_which_str(const QString &str)
+{
+ struct dive_site *ds;
+ int i;
+ for_each_dive_site (i, ds) {
+ QString dsName(ds->name);
+ if (dsName.toLower().startsWith(str.toLower())) {
+ return ds;
+ }
+ }
+ return NULL;
+}
+
+void DiveLocationLineEdit::setTemporaryDiveSiteName(const QString &s)
+{
+ QModelIndex i0 = model->index(0, DiveLocationModel::NAME);
+ QModelIndex i1 = model->index(1, DiveLocationModel::NAME);
+ model->setData(i0, text());
+
+ QString i1_name = INVALID_DIVE_SITE_NAME;
+ if (struct dive_site *ds = get_dive_site_name_start_which_str(text())) {
+ const QString orig_name = QString(ds->name).toLower();
+ const QString new_name = text().toLower();
+ if (new_name != orig_name)
+ i1_name = QString(ds->name);
+ }
+
+ model->setData(i1, i1_name);
+ proxy->invalidate();
+ fixPopupPosition();
+ if (!view->isVisible())
+ view->show();
+}
+
+void DiveLocationLineEdit::keyPressEvent(QKeyEvent *ev)
+{
+ QLineEdit::keyPressEvent(ev);
+ if (ev->key() != Qt::Key_Left &&
+ ev->key() != Qt::Key_Right &&
+ ev->key() != Qt::Key_Escape &&
+ ev->key() != Qt::Key_Return) {
+
+ if (ev->key() != Qt::Key_Up && ev->key() != Qt::Key_Down) {
+ currType = NEW_DIVE_SITE;
+ currUuid = RECENTLY_ADDED_DIVESITE;
+ } else {
+ showPopup();
+ }
+ } else if (ev->key() == Qt::Key_Escape) {
+ view->hide();
+ }
+}
+
+void DiveLocationLineEdit::fixPopupPosition()
+{
+ const QRect screen = QApplication::desktop()->availableGeometry(this);
+ const int maxVisibleItems = 5;
+ Qt::LayoutDirection dir = layoutDirection();
+ QPoint pos;
+ int rh, w;
+ int h = (view->sizeHintForRow(0) * qMin(maxVisibleItems, view->model()->rowCount()) + 3) + 3;
+ QScrollBar *hsb = view->horizontalScrollBar();
+ if (hsb && hsb->isVisible())
+ h += view->horizontalScrollBar()->sizeHint().height();
+
+ rh = height();
+ pos = mapToGlobal(QPoint(0, height() - 2));
+ w = width();
+
+ if (w > screen.width())
+ w = screen.width();
+ if ((pos.x() + w) > (screen.x() + screen.width()))
+ pos.setX(screen.x() + screen.width() - w);
+ if (pos.x() < screen.x())
+ pos.setX(screen.x());
+
+ int top = pos.y() - rh - screen.top() + 2;
+ int bottom = screen.bottom() - pos.y();
+ h = qMax(h, view->minimumHeight());
+ if (h > bottom) {
+ h = qMin(qMax(top, bottom), h);
+ if (top > bottom)
+ pos.setY(pos.y() - h - rh + 2);
+ }
+
+ view->setGeometry(pos.x(), pos.y(), w, h);
+ if (!view->currentIndex().isValid() && view->model()->rowCount()) {
+ view->setCurrentIndex(view->model()->index(0, 0));
+ }
+}
+
+void DiveLocationLineEdit::setCurrentDiveSiteUuid(uint32_t uuid)
+{
+ currUuid = uuid;
+ if (uuid == 0) {
+ currType = NO_DIVE_SITE;
+ }
+ struct dive_site *ds = get_dive_site_by_uuid(uuid);
+ if (!ds)
+ clear();
+ else
+ setText(ds->name);
+}
+
+void DiveLocationLineEdit::showPopup()
+{
+ fixPopupPosition();
+ if (!view->isVisible()) {
+ setTemporaryDiveSiteName(text());
+ proxy->invalidate();
+ view->show();
+ }
+}
+
+DiveLocationLineEdit::DiveSiteType DiveLocationLineEdit::currDiveSiteType() const
+{
+ return currType;
+}
+
+uint32_t DiveLocationLineEdit::currDiveSiteUuid() const
+{
+ return currUuid;
+}
+
+DiveLocationListView::DiveLocationListView(QWidget *parent)
+{
+}
+
+void DiveLocationListView::currentChanged(const QModelIndex &current, const QModelIndex &previous)
+{
+ QListView::currentChanged(current, previous);
+ emit currentIndexChanged(current);
+}