diff options
Diffstat (limited to 'qt-ui/locationinformation.cpp')
-rw-r--r-- | qt-ui/locationinformation.cpp | 316 |
1 files changed, 277 insertions, 39 deletions
diff --git a/qt-ui/locationinformation.cpp b/qt-ui/locationinformation.cpp index bf8300426..6e6db0b34 100644 --- a/qt-ui/locationinformation.cpp +++ b/qt-ui/locationinformation.cpp @@ -7,12 +7,15 @@ #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) { @@ -256,64 +259,299 @@ void LocationInformationWidget::resetPallete() ui.diveSiteNotes->setPalette(p); } -bool LocationManagementEditHelper::eventFilter(QObject *obj, QEvent *ev) +void LocationInformationWidget::reverseGeocode() { - QListView *view = qobject_cast<QListView*>(obj); - if(!view) - return false; + ReverseGeoLookupThread *geoLookup = ReverseGeoLookupThread::instance(); + geoLookup->lookup(&displayed_dive_site); + updateLabels(); +} - if(ev->type() == QEvent::Show) { - last_uuid = 0; - qDebug() << "EventFilter: " << last_uuid; +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 +{ + 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 "Create a new dive site"; + case Qt::DecorationRole : return QIcon(":plus"); + } + } + + // 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 QIcon(":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()) +{ + 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); + + connect(this, &QLineEdit::textEdited, this, &DiveLocationLineEdit::setTemporaryDiveSiteName); + connect(view, &QAbstractItemView::activated, this, &DiveLocationLineEdit::itemActivated); +} - if(ev->type() == QEvent::KeyPress) { - QKeyEvent *keyEv = (QKeyEvent*) ev; - if(keyEv->key() == Qt::Key_Return) { - handleActivation(view->currentIndex()); +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) { + 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 LocationManagementEditHelper::handleActivation(const QModelIndex& activated) +void DiveLocationLineEdit::focusOutEvent(QFocusEvent* ev) { - if (!activated.isValid()) - return; - QModelIndex uuidIdx = activated.model()->index( - activated.row(), LocationInformationModel::UUID); - last_uuid = uuidIdx.data().toInt(); - - /* if we are in 'recently added divesite mode, create a new divesite, - * and go to dive site edit edit mode. */ - if (last_uuid == RECENTLY_ADDED_DIVESITE) { - uint32_t ds_uuid = create_dive_site_from_current_dive(qPrintable(activated.data().toString())); - qDebug() << "ds_uuid" << ds_uuid; - struct dive_site *ds = get_dive_site_by_uuid(ds_uuid); - copy_dive_site(ds, &displayed_dive_site); - displayed_dive.dive_site_uuid = ds->uuid; - last_uuid = ds->uuid; - // Move this out of here later. - MainWindow::instance()->startDiveSiteEdit(); + if (!view->isVisible()) { + QLineEdit::focusOutEvent(ev); } +} - qDebug() << "Selected dive_site: " << last_uuid; +void DiveLocationLineEdit::itemActivated(const QModelIndex& index) +{ + 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(index.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 LocationManagementEditHelper::resetDiveSiteUuid() { - last_uuid = 0; - qDebug() << "Reset: " << last_uuid; +void DiveLocationLineEdit::refreshDiveSiteCache() +{ + model->resetModel(); } -uint32_t LocationManagementEditHelper::diveSiteUuid() const { - return last_uuid; +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 LocationInformationWidget::reverseGeocode() +void DiveLocationLineEdit::setTemporaryDiveSiteName(const QString& s) { - ReverseGeoLookupThread *geoLookup = ReverseGeoLookupThread::instance(); - geoLookup->lookup(&displayed_dive_site); - updateLabels(); + 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->setCurrentIndex(view->model()->index(0,1)); + } +} + +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) +{ + } |