diff options
Diffstat (limited to 'qt-ui')
48 files changed, 1347 insertions, 1538 deletions
diff --git a/qt-ui/completionmodels.cpp b/qt-ui/completionmodels.cpp index 30e69d26a..7d7f7cd2b 100644 --- a/qt-ui/completionmodels.cpp +++ b/qt-ui/completionmodels.cpp @@ -8,7 +8,7 @@ QStringList list; \ struct dive *dive; \ int i = 0; \ - for_each_dive(i, dive) \ + for_each_dive (i, dive) \ { \ QString buddy(dive->diveStructMember); \ if (!list.contains(buddy)) { \ @@ -24,10 +24,10 @@ QSet<QString> set; \ struct dive *dive; \ int i = 0; \ - for_each_dive(i, dive) \ + for_each_dive (i, dive) \ { \ QString buddy(dive->diveStructMember); \ - foreach(const QString &value, buddy.split(",", QString::SkipEmptyParts)) \ + foreach (const QString &value, buddy.split(",", QString::SkipEmptyParts)) \ { \ set.insert(value.trimmed()); \ } \ diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp index 6fd5dee10..cbb75c102 100644 --- a/qt-ui/divelistview.cpp +++ b/qt-ui/divelistview.cpp @@ -9,6 +9,7 @@ #include "modeldelegates.h" #include "mainwindow.h" #include "subsurfacewebservices.h" +#include "divelogexportdialog.h" #include "../display.h" #include "exif.h" #include "../file.h" @@ -27,7 +28,8 @@ #include <iostream> #include "../qthelper.h" -DiveListView::DiveListView(QWidget *parent) : QTreeView(parent), mouseClickSelection(false), sortColumn(0), currentOrder(Qt::DescendingOrder), searchBox(this) +DiveListView::DiveListView(QWidget *parent) : QTreeView(parent), mouseClickSelection(false), sortColumn(0) + , currentOrder(Qt::DescendingOrder), searchBox(this), dontEmitDiveChangedSignal(false) { setItemDelegate(new DiveListDelegate(this)); setUniformRowHeights(true); @@ -57,7 +59,8 @@ DiveListView::DiveListView(QWidget *parent) : QTreeView(parent), mouseClickSelec searchBox.hide(); connect(showSearchBox, SIGNAL(triggered(bool)), this, SLOT(showSearchEdit())); connect(&searchBox, SIGNAL(textChanged(QString)), model, SLOT(setFilterFixedString(QString))); - setupUi(); + // calling setupUi() here appears to be too early; it does NOT correctly set the column widths + // setupUi(); } DiveListView::~DiveListView() @@ -122,7 +125,7 @@ void DiveListView::backupExpandedRows() void DiveListView::restoreExpandedRows() { setAnimated(false); - Q_FOREACH(const int & i, expandedRows) + Q_FOREACH (const int &i, expandedRows) setExpanded(model()->index(i, 0), true); setAnimated(true); } @@ -139,7 +142,7 @@ void DiveListView::rememberSelection() { selectedDives.clear(); QItemSelection selection = selectionModel()->selection(); - Q_FOREACH(const QModelIndex & index, selection.indexes()) { + Q_FOREACH (const QModelIndex &index, selection.indexes()) { if (index.column() != 0) // We only care about the dives, so, let's stick to rows and discard columns. continue; struct dive *d = (struct dive *)index.data(DiveTripModel::DIVE_ROLE).value<void *>(); @@ -151,18 +154,18 @@ void DiveListView::rememberSelection() void DiveListView::restoreSelection() { unselectDives(); - Q_FOREACH(dive_trip_t * trip, selectedDives.keys()) { + Q_FOREACH (dive_trip_t *trip, selectedDives.keys()) { QList<int> divesOnTrip = getDivesInTrip(trip); QList<int> selectedDivesOnTrip = selectedDives.values(trip); // Trip was not selected, let's select single-dives. if (trip == NULL || divesOnTrip.count() != selectedDivesOnTrip.count()) { - Q_FOREACH(int i, selectedDivesOnTrip) { + Q_FOREACH (int i, selectedDivesOnTrip) { selectDive(i); } } else { selectTrip(trip); - Q_FOREACH(int i, selectedDivesOnTrip) { + Q_FOREACH (int i, selectedDivesOnTrip) { selectDive(i); } } @@ -189,13 +192,20 @@ void DiveListView::selectTrip(dive_trip_t *trip) void DiveListView::unselectDives() { selectionModel()->clearSelection(); + // clearSelection should emit selectionChanged() but sometimes that + // appears not to happen + int i; + struct dive *dive; + for_each_dive(i, dive) { + deselect_dive(i); + } } QList<dive_trip_t *> DiveListView::selectedTrips() { QModelIndexList indexes = selectionModel()->selectedRows(); QList<dive_trip_t *> ret; - Q_FOREACH(const QModelIndex & index, indexes) { + Q_FOREACH (const QModelIndex &index, indexes) { dive_trip_t *trip = static_cast<dive_trip_t *>(index.data(DiveTripModel::TRIP_ROLE).value<void *>()); if (!trip) continue; @@ -211,6 +221,8 @@ void DiveListView::selectDive(int i, bool scrollto, bool toggle) QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel *>(model()); QModelIndexList match = m->match(m->index(0, 0), DiveTripModel::DIVE_IDX, i, 2, Qt::MatchRecursive); QItemSelectionModel::SelectionFlags flags; + if (match.isEmpty()) + return; QModelIndex idx = match.first(); flags = toggle ? QItemSelectionModel::Toggle : QItemSelectionModel::Select; flags |= QItemSelectionModel::Rows; @@ -231,54 +243,24 @@ void DiveListView::selectDives(const QList<int> &newDiveSelection) if (!newDiveSelection.count()) return; - disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, SLOT(selectionChanged(QItemSelection, QItemSelection))); - disconnect(selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), - this, SLOT(currentChanged(QModelIndex, QModelIndex))); + dontEmitDiveChangedSignal = true; + // select the dives, highest index first - this way the oldest of the dives + // becomes the selected_dive that we scroll to + QList<int> sortedSelection = newDiveSelection; + qSort(sortedSelection.begin(), sortedSelection.end()); + while (!sortedSelection.isEmpty()) + selectDive(sortedSelection.takeLast()); - setAnimated(false); - collapseAll(); QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel *>(model()); - QItemSelectionModel::SelectionFlags flags = QItemSelectionModel::Select | QItemSelectionModel::Rows; - - QItemSelection newDeselected = selectionModel()->selection(); - QModelIndexList diveList; - - //TODO: This should be called find_first_selected_dive and be ported to C code. - int firstSelectedDive = -1; - /* context for temp. variables. */ { - int i = 0; - struct dive *dive; - for_each_dive(i, dive) { - dive->selected = newDiveSelection.contains(i) == true; - if (firstSelectedDive == -1 && dive->selected) { - firstSelectedDive = i; - break; - } - } - } - select_dive(firstSelectedDive); - Q_FOREACH(int i, newDiveSelection) { - diveList.append(m->match(m->index(0, 0), DiveTripModel::DIVE_IDX, - i, 2, Qt::MatchRecursive).first()); - } - Q_FOREACH(const QModelIndex & idx, diveList) { - selectionModel()->select(idx, flags); - if (idx.parent().isValid() && !isExpanded(idx.parent())) { - expand(idx.parent()); - } - } - setAnimated(true); - QTreeView::selectionChanged(selectionModel()->selection(), newDeselected); - connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, SLOT(selectionChanged(QItemSelection, QItemSelection))); - connect(selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), - this, SLOT(currentChanged(QModelIndex, QModelIndex))); - Q_EMIT currentDiveChanged(selected_dive); QModelIndex idx = m->match(m->index(0, 0), DiveTripModel::DIVE_IDX, selected_dive, 2, Qt::MatchRecursive).first(); if (idx.parent().isValid()) scrollTo(idx.parent()); scrollTo(idx); + + // now that everything is up to date, update the widgets + Q_EMIT currentDiveChanged(selected_dive); + dontEmitDiveChangedSignal = false; + return; } void DiveListView::showSearchEdit() @@ -328,10 +310,19 @@ void DiveListView::headerClicked(int i) } } restoreSelection(); + // remember the new sort column + sortColumn = i; } void DiveListView::reload(DiveTripModel::Layout layout, bool forceSort) { + // we want to run setupUi() once we actually are displaying something + // in the widget + static bool first = true; + if (first && dive_table.nr > 0) { + setupUi(); + first = false; + } if (layout == DiveTripModel::CURRENT) layout = currentLayout; else @@ -368,7 +359,6 @@ void DiveListView::reload(DiveTripModel::Layout layout, bool forceSort) setCurrentIndex(firstDiveOrTrip); } } - setupUi(); if (selectedIndexes().count()) { QModelIndex curr = selectedIndexes().first(); curr = curr.parent().isValid() ? curr.parent() : curr; @@ -396,7 +386,7 @@ void DiveListView::reloadHeaderActions() QString settingName = QString("showColumn%1").arg(i); QAction *a = new QAction(title, header()); bool showHeaderFirstRun = !( - i == DiveTripModel::MAXCNS || i == DiveTripModel::NITROX || i == DiveTripModel::OTU || i == DiveTripModel::TEMPERATURE || i == DiveTripModel::TOTALWEIGHT || i == DiveTripModel::SUIT || i == DiveTripModel::CYLINDER || i == DiveTripModel::SAC); + i == DiveTripModel::MAXCNS || i == DiveTripModel::NITROX || i == DiveTripModel::OTU || i == DiveTripModel::TEMPERATURE || i == DiveTripModel::TOTALWEIGHT || i == DiveTripModel::SUIT || i == DiveTripModel::CYLINDER || i == DiveTripModel::SAC); bool shown = s.value(settingName, showHeaderFirstRun).toBool(); a->setCheckable(true); a->setChecked(shown); @@ -445,39 +435,26 @@ void DiveListView::selectionChanged(const QItemSelection &selected, const QItemS disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(selectionChanged(QItemSelection, QItemSelection))); disconnect(selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex, QModelIndex))); - Q_FOREACH(const QModelIndex & index, newDeselected.indexes()) { + Q_FOREACH (const QModelIndex &index, newDeselected.indexes()) { if (index.column() != 0) continue; const QAbstractItemModel *model = index.model(); struct dive *dive = (struct dive *)model->data(index, DiveTripModel::DIVE_ROLE).value<void *>(); - if (!dive) { // it's a trip! - //TODO: deselect_trip_dives on c-code? - if (model->rowCount(index)) { - struct dive *child = (struct dive *)model->data(index.child(0, 0), DiveTripModel::DIVE_ROLE).value<void *>(); - while (child) { - deselect_dive(get_divenr(child)); - child = child->next; - } - } - } else { + if (!dive) // it's a trip! + deselect_dives_in_trip((dive_trip_t *)model->data(index, DiveTripModel::TRIP_ROLE).value<void *>()); + else deselect_dive(get_divenr(dive)); - } } - Q_FOREACH(const QModelIndex & index, newSelected.indexes()) { + Q_FOREACH (const QModelIndex &index, newSelected.indexes()) { if (index.column() != 0) continue; const QAbstractItemModel *model = index.model(); struct dive *dive = (struct dive *)model->data(index, DiveTripModel::DIVE_ROLE).value<void *>(); if (!dive) { // it's a trip! - //TODO: select_trip_dives on C code? if (model->rowCount(index)) { QItemSelection selection; - struct dive *child = (struct dive *)model->data(index.child(0, 0), DiveTripModel::DIVE_ROLE).value<void *>(); - while (child) { - select_dive(get_divenr(child)); - child = child->next; - } + select_dives_in_trip((dive_trip_t *)model->data(index, DiveTripModel::TRIP_ROLE).value<void *>()); selection.select(index.child(0, 0), index.child(model->rowCount(index) - 1, 0)); selectionModel()->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows); selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select | QItemSelectionModel::NoUpdate); @@ -491,8 +468,8 @@ void DiveListView::selectionChanged(const QItemSelection &selected, const QItemS QTreeView::selectionChanged(selectionModel()->selection(), newDeselected); connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(selectionChanged(QItemSelection, QItemSelection))); connect(selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex, QModelIndex))); - // now that everything is up to date, update the widgets - Q_EMIT currentDiveChanged(selected_dive); + if(!dontEmitDiveChangedSignal) + Q_EMIT currentDiveChanged(selected_dive); } static bool can_merge(const struct dive *a, const struct dive *b) @@ -512,7 +489,7 @@ void DiveListView::mergeDives() int i; struct dive *dive, *maindive = NULL; - for_each_dive(i, dive) { + for_each_dive (i, dive) { if (dive->selected) { if (!can_merge(maindive, dive)) { maindive = dive; @@ -525,6 +502,12 @@ void DiveListView::mergeDives() MainWindow::instance()->refreshDisplay(); } +void DiveListView::renumberDives() +{ + RenumberDialog::instance()->renumberOnlySelected(); + RenumberDialog::instance()->show(); +} + void DiveListView::merge_trip(const QModelIndex &a, int offset) { int i = a.row() + offset; @@ -532,17 +515,9 @@ void DiveListView::merge_trip(const QModelIndex &a, int offset) dive_trip_t *trip_a = (dive_trip_t *)a.data(DiveTripModel::TRIP_ROLE).value<void *>(); dive_trip_t *trip_b = (dive_trip_t *)b.data(DiveTripModel::TRIP_ROLE).value<void *>(); - // TODO: merge_trip on the C code? some part of this needs to stay ( getting the trips from the model, - // but not the algorithm. if (trip_a == trip_b || !trip_a || !trip_b) return; - - if (!trip_a->location && trip_b->location) - trip_a->location = strdup(trip_b->location); - if (!trip_a->notes && trip_b->notes) - trip_a->notes = strdup(trip_b->notes); - while (trip_b->dives) - add_dive_to_trip(trip_b->dives, trip_a); + combine_trips(trip_a, trip_b); rememberSelection(); reload(currentLayout, false); fixMessyQtModelBehaviour(); @@ -566,7 +541,7 @@ void DiveListView::removeFromTrip() //TODO: move this to C-code. int i; struct dive *d; - for_each_dive(i, d) { + for_each_dive (i, d) { if (d->selected) remove_dive_from_trip(d, false); } @@ -587,7 +562,7 @@ void DiveListView::newTripAbove() int idx; rememberSelection(); trip = create_and_hookup_trip_from_dive(d); - for_each_dive(idx, d) { + for_each_dive (idx, d) { if (d->selected) add_dive_to_trip(d, trip); } @@ -610,7 +585,7 @@ void DiveListView::addToTripAbove() void DiveListView::addToTrip(bool below) { - int delta = (currentOrder == Qt::AscendingOrder) ? -1 : +1; + int delta = (currentOrder == Qt::AscendingOrder) ? -1 : +1; struct dive *d = (struct dive *)contextMenuIndex.data(DiveTripModel::DIVE_ROLE).value<void *>(); rememberSelection(); @@ -623,18 +598,10 @@ void DiveListView::addToTrip(bool below) if (d->selected) { // we are right-clicking on one of possibly many selected dive(s) // find the top selected dive, depending on the list order - if (delta == 1) { - for_each_dive(idx, d) { - if (d->selected) - pd = d; - } - d = pd; // this way we have the chronologically last - } else { - for_each_dive(idx, d) { - if (d->selected) - break; // now that's the chronologically first - } - } + if (delta == 1) + d = last_selected_dive(); + else + d = first_selected_dive(); } // now find the trip "above" in the dive list if ((pd = get_dive(get_divenr(d) + delta)) != NULL) { @@ -645,7 +612,7 @@ void DiveListView::addToTrip(bool below) return; add_dive_to_trip(d, trip); if (d->selected) { // there are possibly other selected dives that we should add - for_each_dive(idx, d) { + for_each_dive (idx, d) { if (d->selected) add_dive_to_trip(d, trip); } @@ -664,7 +631,7 @@ void DiveListView::markDiveInvalid() struct dive *d = (struct dive *)contextMenuIndex.data(DiveTripModel::DIVE_ROLE).value<void *>(); if (!d) return; - for_each_dive(i, d) { + for_each_dive (i, d) { if (!d->selected) continue; //TODO: this should be done in the future @@ -696,8 +663,7 @@ void DiveListView::deleteDive() // so instead of using the for_each_dive macro I'm using an explicit for loop // to make this easier to understand int lastDiveNr = -1; - for (i = 0; i < dive_table.nr; i++) { - d = get_dive(i); + for_each_dive (i, d) { if (!d->selected) continue; delete_single_dive(i); @@ -747,8 +713,23 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event) if (d) { popup.addAction(tr("remove dive(s) from trip"), this, SLOT(removeFromTrip())); popup.addAction(tr("create new trip above"), this, SLOT(newTripAbove())); - popup.addAction(tr("add dive(s) to trip immediately above"), this, SLOT(addToTripAbove())); - popup.addAction(tr("add dive(s) to trip immediately below"), this, SLOT(addToTripBelow())); + if (!d->divetrip) { + struct dive *top = d; + struct dive *bottom = d; + if (d->selected) { + if (currentOrder == Qt::AscendingOrder) { + top = first_selected_dive(); + bottom = last_selected_dive(); + } else { + top = last_selected_dive(); + bottom = first_selected_dive(); + } + } + if (is_trip_before_after(top, (currentOrder == Qt::AscendingOrder))) + popup.addAction(tr("add dive(s) to trip immediately above"), this, SLOT(addToTripAbove())); + if (is_trip_before_after(bottom, (currentOrder == Qt::DescendingOrder))) + popup.addAction(tr("add dive(s) to trip immediately below"), this, SLOT(addToTripBelow())); + } } if (trip) { popup.addAction(tr("merge trip with trip above"), this, SLOT(mergeTripAbove())); @@ -764,14 +745,10 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event) if (amount_selected > 1 && consecutive_selected()) popup.addAction(tr("merge selected dives"), this, SLOT(mergeDives())); if (amount_selected >= 1) { - popup.addAction(tr("save As"), this, SLOT(saveSelectedDivesAs())); - popup.addAction(tr("export As UDDF"), this, SLOT(exportSelectedDivesAsUDDF())); - popup.addAction(tr("export As CSV"), this, SLOT(exportSelectedDivesAsCSV())); + popup.addAction(tr("renumber dive(s)"), this, SLOT(renumberDives())); popup.addAction(tr("shift times"), this, SLOT(shiftTimes())); popup.addAction(tr("load images"), this, SLOT(loadImages())); } - if (d) - popup.addAction(tr("upload dive(s) to divelogs.de"), this, SLOT(uploadToDivelogsDE())); // "collapse all" really closes all trips, // "collapse" keeps the trip with the selected dive open QAction *actionTaken = popup.exec(event->globalPos()); @@ -784,56 +761,6 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event) event->accept(); } -void DiveListView::saveSelectedDivesAs() -{ - QSettings settings; - QString lastDir = QDir::homePath(); - - settings.beginGroup("FileDialog"); - if (settings.contains("LastDir")) { - if (QDir::setCurrent(settings.value("LastDir").toString())) { - lastDir = settings.value("LastDir").toString(); - } - } - settings.endGroup(); - - QString fileName = QFileDialog::getSaveFileName(MainWindow::instance(), tr("Save Dives As..."), QDir::homePath()); - if (fileName.isEmpty()) - return; - - // Keep last open dir - QFileInfo fileInfo(fileName); - settings.beginGroup("FileDialog"); - settings.setValue("LastDir", fileInfo.dir().path()); - settings.endGroup(); - - QByteArray bt = QFile::encodeName(fileName); - save_dives_logic(bt.data(), true); -} - -void DiveListView::exportSelectedDivesAsUDDF() -{ - QString filename; - QFileInfo fi(system_default_filename()); - - filename = QFileDialog::getSaveFileName(this, tr("Export UDDF File as"), fi.absolutePath(), - tr("UDDF files (*.uddf *.UDDF)")); - if (!filename.isNull() && !filename.isEmpty()) - export_dives_xslt(filename.toUtf8(), true, "uddf-export.xslt"); -} - -void DiveListView::exportSelectedDivesAsCSV() -{ - QString filename; - QFileInfo fi(system_default_filename()); - - filename = QFileDialog::getSaveFileName(this, tr("Export CSV File as"), fi.absolutePath(), - tr("CSV files (*.csv *.CSV)")); - if (!filename.isNull() && !filename.isEmpty()) - export_dives_xslt(filename.toUtf8(), true, "xml2csv.xslt"); -} - - void DiveListView::shiftTimes() { ShiftTimesDialog::instance()->show(); @@ -874,11 +801,10 @@ void DiveListView::loadImages() imagetime += shiftDialog.amount(); // TODO: this should be cached and passed to the C-function int j = 0; struct dive *dive; - for_each_dive(j, dive) { + for_each_dive (j, dive) { if (!dive->selected) continue; - dc = &(dive->dc); - while (dc) { + for_each_dc (dive, dc) { when = dc->when ? dc->when : dive->when; duration_s = dc->duration.seconds ? dc->duration.seconds : dive->duration.seconds; if (when - 3600 < imagetime && when + duration_s + 3600 > imagetime) { @@ -899,17 +825,11 @@ void DiveListView::loadImages() MainWindow::instance()->refreshDisplay(); MainWindow::instance()->graphics()->replot(); } - dc = dc->next; } } } } -void DiveListView::uploadToDivelogsDE() -{ - DivelogsDeWebServices::instance()->prepareDivesForUpload(); -} - QString DiveListView::lastUsedImageDir() { QSettings settings; diff --git a/qt-ui/divelistview.h b/qt-ui/divelistview.h index d946b1854..23ca1cc42 100644 --- a/qt-ui/divelistview.h +++ b/qt-ui/divelistview.h @@ -48,12 +48,9 @@ slots: void addToTripAbove(); void addToTripBelow(); void mergeDives(); - void saveSelectedDivesAs(); - void exportSelectedDivesAsUDDF(); - void exportSelectedDivesAsCSV(); + void renumberDives(); void shiftTimes(); void loadImages(); - void uploadToDivelogsDE(); static QString lastUsedImageDir(); signals: @@ -67,6 +64,7 @@ private: DiveTripModel::Layout currentLayout; QLineEdit searchBox; QModelIndex contextMenuIndex; + bool dontEmitDiveChangedSignal; /* if dive_trip_t is null, there's no problem. */ QMultiHash<dive_trip_t *, int> selectedDives; diff --git a/qt-ui/divelogexportdialog.cpp b/qt-ui/divelogexportdialog.cpp new file mode 100644 index 000000000..28f343257 --- /dev/null +++ b/qt-ui/divelogexportdialog.cpp @@ -0,0 +1,98 @@ +#include <QFileDialog> +#include <QString> +#include <QShortcut> +#include <QAbstractButton> +#include <QDebug> +#include <QSettings> + +#include "mainwindow.h" +#include "divelogexportdialog.h" +#include "ui_divelogexportdialog.h" +#include "subsurfacewebservices.h" +#include "worldmap-save.h" + +DiveLogExportDialog::DiveLogExportDialog(QWidget *parent) : QDialog(parent), + ui(new Ui::DiveLogExportDialog) +{ + ui->setupUi(this); + showExplanation(); + QShortcut *quit = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this); + connect(quit, SIGNAL(activated()), parent, SLOT(close())); + QShortcut *close = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this); + connect(close, SIGNAL(activated()), this, SLOT(close())); +} + +DiveLogExportDialog::~DiveLogExportDialog() +{ + delete ui; +} + +void DiveLogExportDialog::showExplanation() +{ + if (ui->exportUDDF->isChecked()) { + ui->description->setText("Generic format that is used for data exchange between a variety of diving related programs."); + } else if (ui->exportCSV->isChecked()) { + ui->description->setText("Comma separated values that include the most relevant information of the dive profile."); + } else if (ui->exportDivelogs->isChecked()) { + ui->description->setText("Send the dive data to Divelogs.de website."); + } else if (ui->exportWorldMap->isChecked()) { + ui->description->setText("HTML export of the dive locations, visualized on a world map."); + } else if (ui->exportSubsurfaceXML->isChecked()) { + ui->description->setText("Subsurface native XML format."); + } +} + +void DiveLogExportDialog::on_exportGroup_buttonClicked(QAbstractButton *button) +{ + showExplanation(); +} + +void DiveLogExportDialog::on_buttonBox_accepted() +{ + QString filename; + QString stylesheet; + QSettings settings; + QString lastDir = QDir::homePath(); + + settings.beginGroup("FileDialog"); + if (settings.contains("LastDir")) { + if (QDir::setCurrent(settings.value("LastDir").toString())) { + lastDir = settings.value("LastDir").toString(); + } + } + settings.endGroup(); + + if (ui->exportUDDF->isChecked()) { + stylesheet = "uddf-export.xslt"; + filename = QFileDialog::getSaveFileName(this, tr("Export UDDF File as"), lastDir, + tr("UDDF files (*.uddf *.UDDF)")); + } else if (ui->exportCSV->isChecked()) { + stylesheet = "xml2csv.xslt"; + filename = QFileDialog::getSaveFileName(this, tr("Export CSV File as"), lastDir, + tr("CSV files (*.csv *.CSV)")); + } else if (ui->exportDivelogs->isChecked()) { + DivelogsDeWebServices::instance()->prepareDivesForUpload(ui->exportSelected->isChecked()); + } else if (ui->exportWorldMap->isChecked()) { + filename = QFileDialog::getSaveFileName(this, tr("Export World Map"), lastDir, + tr("HTML files (*.html)")); + if (!filename.isNull() && !filename.isEmpty()) + export_worldmap_HTML(filename.toUtf8().data(), ui->exportSelected->isChecked()); + } else if (ui->exportSubsurfaceXML->isChecked()) { + filename = QFileDialog::getSaveFileName(this, tr("Export Subsurface XML"), lastDir, + tr("XML files (*.xml *.ssrf)")); + if (!filename.isNull() && !filename.isEmpty()) { + QByteArray bt = QFile::encodeName(filename); + save_dives_logic(bt.data(), true); + } + } + if (!filename.isNull() && !filename.isEmpty()) { + // remember the last export path + QFileInfo fileInfo(filename); + settings.beginGroup("FileDialog"); + settings.setValue("LastDir", fileInfo.dir().path()); + settings.endGroup(); + // the non XSLT exports are called directly above, the XSLT based ons are called here + if (!stylesheet.isEmpty()) + export_dives_xslt(filename.toUtf8(), ui->exportSelected->isChecked(), stylesheet.toStdString().c_str()); + } +} diff --git a/qt-ui/divelogexportdialog.h b/qt-ui/divelogexportdialog.h new file mode 100644 index 000000000..92510a7aa --- /dev/null +++ b/qt-ui/divelogexportdialog.h @@ -0,0 +1,28 @@ +#ifndef DIVELOGEXPORTDIALOG_H +#define DIVELOGEXPORTDIALOG_H + +#include <QDialog> +#include <QAbstractButton> + +namespace Ui { + class DiveLogExportDialog; +} + +class DiveLogExportDialog : public QDialog { + Q_OBJECT + +public: + explicit DiveLogExportDialog(QWidget *parent = 0); + ~DiveLogExportDialog(); + +private +slots: + void on_buttonBox_accepted(); + void on_exportGroup_buttonClicked(QAbstractButton *); + +private: + Ui::DiveLogExportDialog *ui; + void showExplanation(); +}; + +#endif // DIVELOGEXPORTDIALOG_H diff --git a/qt-ui/divelogexportdialog.ui b/qt-ui/divelogexportdialog.ui new file mode 100644 index 000000000..72e373127 --- /dev/null +++ b/qt-ui/divelogexportdialog.ui @@ -0,0 +1,283 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>DiveLogExportDialog</class> + <widget class="QDialog" name="DiveLogExportDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>448</width> + <height>473</height> + </rect> + </property> + <property name="windowTitle"> + <string>Export Dive Log Files</string> + </property> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="geometry"> + <rect> + <x>20</x> + <y>420</y> + <width>341</width> + <height>32</height> + </rect> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + <widget class="QLabel" name="label_3"> + <property name="geometry"> + <rect> + <x>-50</x> + <y>10</y> + <width>497</width> + <height>24</height> + </rect> + </property> + <property name="font"> + <font> + <family>Droid Sans [unknown]</family> + <pointsize>14</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="text"> + <string>Export Dive Log Files</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + <widget class="QGroupBox" name="exportFormat"> + <property name="geometry"> + <rect> + <x>20</x> + <y>70</y> + <width>201</width> + <height>211</height> + </rect> + </property> + <property name="title"> + <string>Export format</string> + </property> + <widget class="QRadioButton" name="exportUDDF"> + <property name="geometry"> + <rect> + <x>10</x> + <y>70</y> + <width>110</width> + <height>24</height> + </rect> + </property> + <property name="maximumSize"> + <size> + <width>110</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>UDDF</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <attribute name="buttonGroup"> + <string notr="true">exportGroup</string> + </attribute> + </widget> + <widget class="QRadioButton" name="exportDivelogs"> + <property name="geometry"> + <rect> + <x>10</x> + <y>100</y> + <width>131</width> + <height>24</height> + </rect> + </property> + <property name="text"> + <string>divelogs.de</string> + </property> + <attribute name="buttonGroup"> + <string notr="true">exportGroup</string> + </attribute> + </widget> + <widget class="QRadioButton" name="exportCSV"> + <property name="geometry"> + <rect> + <x>10</x> + <y>130</y> + <width>110</width> + <height>24</height> + </rect> + </property> + <property name="text"> + <string>CSV</string> + </property> + <attribute name="buttonGroup"> + <string notr="true">exportGroup</string> + </attribute> + </widget> + <widget class="QRadioButton" name="exportWorldMap"> + <property name="geometry"> + <rect> + <x>10</x> + <y>160</y> + <width>171</width> + <height>24</height> + </rect> + </property> + <property name="text"> + <string>Worldmap</string> + </property> + <attribute name="buttonGroup"> + <string notr="true">exportGroup</string> + </attribute> + </widget> + <widget class="QRadioButton" name="exportSubsurfaceXML"> + <property name="geometry"> + <rect> + <x>10</x> + <y>40</y> + <width>171</width> + <height>21</height> + </rect> + </property> + <property name="maximumSize"> + <size> + <width>171</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Subsurface XML</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <attribute name="buttonGroup"> + <string notr="true">exportGroup</string> + </attribute> + </widget> + </widget> + <widget class="QGroupBox" name="exportSelection"> + <property name="geometry"> + <rect> + <x>240</x> + <y>70</y> + <width>191</width> + <height>141</height> + </rect> + </property> + <property name="title"> + <string>Selection</string> + </property> + <widget class="QRadioButton" name="exportSelected"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>151</width> + <height>24</height> + </rect> + </property> + <property name="text"> + <string>Selected dives</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QRadioButton" name="exportAll"> + <property name="geometry"> + <rect> + <x>10</x> + <y>60</y> + <width>110</width> + <height>24</height> + </rect> + </property> + <property name="text"> + <string>All dives</string> + </property> + </widget> + </widget> + <widget class="Line" name="line"> + <property name="geometry"> + <rect> + <x>60</x> + <y>280</y> + <width>231</width> + <height>16</height> + </rect> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + <widget class="QLabel" name="description"> + <property name="geometry"> + <rect> + <x>30</x> + <y>310</y> + <width>341</width> + <height>91</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>DiveLogExportDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>DiveLogExportDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> + <buttongroups> + <buttongroup name="exportGroup"/> + </buttongroups> +</ui> diff --git a/qt-ui/divelogimportdialog.h b/qt-ui/divelogimportdialog.h index 4c499b03e..fb44faa94 100644 --- a/qt-ui/divelogimportdialog.h +++ b/qt-ui/divelogimportdialog.h @@ -6,8 +6,7 @@ #include "../dive.h" #include "../divelist.h" -namespace Ui -{ +namespace Ui { class DiveLogImportDialog; } diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp index 24aa7f697..ada2b4e73 100644 --- a/qt-ui/diveplanner.cpp +++ b/qt-ui/diveplanner.cpp @@ -43,264 +43,6 @@ QString dpGasToStr(const divedatapoint &p) static DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); -DivePlannerGraphics::DivePlannerGraphics(QWidget *parent) : QGraphicsView(parent), - verticalLine(new QGraphicsLineItem(fromPercent(0, Qt::Horizontal), fromPercent(0, Qt::Vertical), fromPercent(0, Qt::Horizontal), fromPercent(100, Qt::Vertical))), - horizontalLine(new QGraphicsLineItem(fromPercent(0, Qt::Horizontal), fromPercent(0, Qt::Vertical), fromPercent(100, Qt::Horizontal), fromPercent(0, Qt::Vertical))), - activeDraggedHandler(0), - diveBg(new QGraphicsPolygonItem()), - timeLine(new Ruler()), - timeString(new QGraphicsSimpleTextItem()), - depthString(new QGraphicsSimpleTextItem()), - depthHandler(new ExpanderGraphics()), - timeHandler(new ExpanderGraphics()), - minMinutes(TIME_INITIAL_MAX), - minDepth(M_OR_FT(40, 120)), - dpMaxTime(0) -{ - setBackgroundBrush(profile_color[BACKGROUND].at(0)); - setMouseTracking(true); - setScene(new QGraphicsScene()); - scene()->setSceneRect(0, 0, 1920, 1080); - - verticalLine->setPen(QPen(Qt::DotLine)); - scene()->addItem(verticalLine); - - horizontalLine->setPen(QPen(Qt::DotLine)); - scene()->addItem(horizontalLine); - - timeLine->setMinimum(0); - timeLine->setMaximum(TIME_INITIAL_MAX); - timeLine->setTickInterval(10); - timeLine->setColor(getColor(TIME_GRID)); - timeLine->setLine(fromPercent(10, Qt::Horizontal), - fromPercent(85, Qt::Vertical), - fromPercent(90, Qt::Horizontal), - fromPercent(85, Qt::Vertical)); - timeLine->setOrientation(Qt::Horizontal); - timeLine->setTickSize(fromPercent(1, Qt::Vertical)); - timeLine->setTextColor(getColor(TIME_TEXT)); - timeLine->updateTicks(); - scene()->addItem(timeLine); - - depthLine = new Ruler(); - depthLine->setMinimum(0); - depthLine->setMaximum(M_OR_FT(40, 120)); - depthLine->setTickInterval(M_OR_FT(10, 30)); - depthLine->setLine(fromPercent(10, Qt::Horizontal), - fromPercent(10, Qt::Vertical), - fromPercent(10, Qt::Horizontal), - fromPercent(85, Qt::Vertical)); - depthLine->setOrientation(Qt::Vertical); - depthLine->setTickSize(fromPercent(1, Qt::Horizontal)); - depthLine->setColor(getColor(DEPTH_GRID)); - depthLine->setTextColor(getColor(SAMPLE_DEEP)); - depthLine->updateTicks(); - depthLine->unitSystem = prefs.units.length; - scene()->addItem(depthLine); - - timeString->setFlag(QGraphicsItem::ItemIgnoresTransformations); - timeString->setBrush(profile_color[TIME_TEXT].at(0)); - scene()->addItem(timeString); - - depthString->setFlag(QGraphicsItem::ItemIgnoresTransformations); - depthString->setBrush(profile_color[SAMPLE_DEEP].at(0)); - scene()->addItem(depthString); - - diveBg->setPen(QPen(QBrush(), 0)); - scene()->addItem(diveBg); - - QString incrText; - if (prefs.units.length == units::METERS) - incrText = tr("10m"); - else - incrText = tr("30ft"); - - timeHandler->increaseBtn->setPixmap(QString(":plan_plus")); - timeHandler->decreaseBtn->setPixmap(QString(":plan_minus")); - timeHandler->icon->setPixmap(QString(":icon_time")); - connect(timeHandler->increaseBtn, SIGNAL(clicked()), this, SLOT(increaseTime())); - connect(timeHandler->decreaseBtn, SIGNAL(clicked()), this, SLOT(decreaseTime())); - timeHandler->setPos(fromPercent(83, Qt::Horizontal), fromPercent(100, Qt::Vertical)); - timeHandler->setZValue(-2); - scene()->addItem(timeHandler); - - depthHandler->increaseBtn->setPixmap(QString(":arrow_down")); - depthHandler->decreaseBtn->setPixmap(QString(":arrow_up")); - depthHandler->icon->setPixmap(QString(":icon_depth")); - connect(depthHandler->decreaseBtn, SIGNAL(clicked()), this, SLOT(decreaseDepth())); - connect(depthHandler->increaseBtn, SIGNAL(clicked()), this, SLOT(increaseDepth())); - depthHandler->setPos(fromPercent(0, Qt::Horizontal), fromPercent(100, Qt::Vertical)); - depthHandler->setZValue(-2); - scene()->addItem(depthHandler); - - QAction *action = NULL; - -#define ADD_ACTION(SHORTCUT, Slot) \ - action = new QAction(this); \ - action->setShortcut(SHORTCUT); \ - action->setShortcutContext(Qt::WindowShortcut); \ - addAction(action); \ - connect(action, SIGNAL(triggered(bool)), this, SLOT(Slot)) - - ADD_ACTION(Qt::Key_Escape, keyEscAction()); - ADD_ACTION(Qt::Key_Delete, keyDeleteAction()); - ADD_ACTION(Qt::Key_Up, keyUpAction()); - ADD_ACTION(Qt::Key_Down, keyDownAction()); - ADD_ACTION(Qt::Key_Left, keyLeftAction()); - ADD_ACTION(Qt::Key_Right, keyRightAction()); -#undef ADD_ACTION - - connect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(drawProfile())); - connect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(drawProfile())); - - connect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), - this, SLOT(pointInserted(const QModelIndex &, int, int))); - connect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), - this, SLOT(pointsRemoved(const QModelIndex &, int, int))); - setRenderHint(QPainter::Antialiasing); -} - -void DivePlannerGraphics::settingsChanged() -{ - if (depthLine->unitSystem == prefs.units.length) - return; - - depthLine->setTickInterval(M_OR_FT(10, 30)); - depthLine->updateTicks(); - depthLine->unitSystem = prefs.units.length; -} - -void DivePlannerGraphics::pointInserted(const QModelIndex &parent, int start, int end) -{ - DiveHandler *item = new DiveHandler(); - scene()->addItem(item); - handles << item; - - QGraphicsSimpleTextItem *gasChooseBtn = new QGraphicsSimpleTextItem(); - scene()->addItem(gasChooseBtn); - gasChooseBtn->setZValue(10); - gasChooseBtn->setFlag(QGraphicsItem::ItemIgnoresTransformations); - gases << gasChooseBtn; - if (plannerModel->recalcQ()) - drawProfile(); -} - -void DivePlannerGraphics::keyDownAction() -{ - Q_FOREACH(QGraphicsItem * i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - if (dp.depth >= depthLine->maximum()) - continue; - - dp.depth += M_OR_FT(1, 5); - plannerModel->editStop(row, dp); - } - } -} - -void DivePlannerGraphics::keyUpAction() -{ - Q_FOREACH(QGraphicsItem * i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - - if (dp.depth <= 0) - continue; - - dp.depth -= M_OR_FT(1, 5); - plannerModel->editStop(row, dp); - } - } - drawProfile(); -} - -void DivePlannerGraphics::keyLeftAction() -{ - Q_FOREACH(QGraphicsItem * i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - - if (dp.time / 60 <= 0) - continue; - - // don't overlap positions. - // maybe this is a good place for a 'goto'? - double xpos = timeLine->posAtValue((dp.time - 60) / 60); - bool nextStep = false; - Q_FOREACH(DiveHandler * h, handles) { - if (IS_FP_SAME(h->pos().x(), xpos)) { - nextStep = true; - break; - } - } - if (nextStep) - continue; - - dp.time -= 60; - plannerModel->editStop(row, dp); - } - } -} - -void DivePlannerGraphics::keyRightAction() -{ - Q_FOREACH(QGraphicsItem * i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - int row = handles.indexOf(handler); - divedatapoint dp = plannerModel->at(row); - if (dp.time / 60 >= timeLine->maximum()) - continue; - - // don't overlap positions. - // maybe this is a good place for a 'goto'? - double xpos = timeLine->posAtValue((dp.time + 60) / 60); - bool nextStep = false; - Q_FOREACH(DiveHandler * h, handles) { - if (IS_FP_SAME(h->pos().x(), xpos)) { - nextStep = true; - break; - } - } - if (nextStep) - continue; - - dp.time += 60; - plannerModel->editStop(row, dp); - } - } -} - -void DivePlannerGraphics::keyDeleteAction() -{ - int selCount = scene()->selectedItems().count(); - if (selCount) { - QVector<int> selectedIndexes; - Q_FOREACH(QGraphicsItem * i, scene()->selectedItems()) { - if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { - selectedIndexes.push_back(handles.indexOf(handler)); - } - } - plannerModel->removeSelectedPoints(selectedIndexes); - } -} - -void DivePlannerGraphics::pointsRemoved(const QModelIndex &, int start, int end) -{ // start and end are inclusive. - int num = (end - start) + 1; - for (int i = num; i != 0; i--) { - delete handles.back(); - handles.pop_back(); - delete gases.back(); - gases.pop_back(); - } - scene()->clearSelection(); - drawProfile(); -} - bool intLessThan(int a, int b) { return a <= b; @@ -317,83 +59,6 @@ void DivePlannerPointsModel::removeSelectedPoints(const QVector<int> &rows) endRemoveRows(); } -void DivePlannerGraphics::keyEscAction() -{ - if (scene()->selectedItems().count()) { - scene()->clearSelection(); - return; - } - if (DivePlannerPointsModel::instance()->isPlanner()) - plannerModel->cancelPlan(); -} - -qreal DivePlannerGraphics::fromPercent(qreal percent, Qt::Orientation orientation) -{ - qreal total = orientation == Qt::Horizontal ? sceneRect().width() : sceneRect().height(); - qreal result = (total * percent) / 100; - return result; -} - -void DivePlannerGraphics::increaseDepth() -{ - if (depthLine->maximum() + M_OR_FT(10, 30) > MAX_DEPTH) - return; - minDepth += M_OR_FT(10, 30); - depthLine->setMaximum(minDepth); - depthLine->updateTicks(); - drawProfile(); -} - -void DivePlannerGraphics::increaseTime() -{ - minMinutes += 10; - timeLine->setMaximum(minMinutes); - timeLine->updateTicks(); - drawProfile(); -} - -void DivePlannerGraphics::decreaseDepth() -{ - if (depthLine->maximum() - M_OR_FT(10, 30) < MIN_DEPTH) - return; - - Q_FOREACH(DiveHandler * d, handles) { - if (depthLine->valueAt(d->pos()) > depthLine->maximum() - M_OR_FT(10, 30)) { - QMessageBox::warning(MainWindow::instance(), - tr("Handler Position Error"), - tr("One or more of your stops will be lost with this operations, \n" - "Please, remove them first.")); - return; - } - } - minDepth -= M_OR_FT(10, 30); - depthLine->setMaximum(minDepth); - depthLine->updateTicks(); - drawProfile(); -} - -void DivePlannerGraphics::decreaseTime() -{ - if (timeLine->maximum() - 10 < TIME_INITIAL_MAX || timeLine->maximum() - 10 < dpMaxTime) - return; - - minMinutes -= 10; - timeLine->setMaximum(timeLine->maximum() - 10); - timeLine->updateTicks(); - drawProfile(); -} - -void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent *event) -{ - QPointF mappedPos = mapToScene(event->pos()); - if (isPointOutOfBoundaries(mappedPos)) - return; - - int minutes = rint(timeLine->valueAt(mappedPos)); - int milimeters = rint(depthLine->valueAt(mappedPos) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); - plannerModel->addStop(milimeters, minutes * 60, -1, 0, 0, true); -} - void DivePlannerPointsModel::createSimpleDive() { // plannerModel->addStop(0, 0, O2_IN_AIR, 0, 0); @@ -470,252 +135,31 @@ void DivePlannerPointsModel::removeDeco() setRecalc(oldrec); } +#if 0 void DivePlannerGraphics::drawProfile() { - if (!plannerModel->recalcQ()) - return; - qDeleteAll(lines); - lines.clear(); - - plannerModel->createTemporaryPlan(); - struct diveplan diveplan = plannerModel->getDiveplan(); - struct divedatapoint *dp = diveplan.dp; - unsigned int max_depth = 0; - - if (!dp) { - plannerModel->deleteTemporaryPlan(); - return; - } - //TODO: divedatapoint_list_get_max_depth on C - code? - while (dp->next) { - if (dp->time && dp->depth > max_depth) - max_depth = dp->depth; - dp = dp->next; - } - - if (!activeDraggedHandler && (timeLine->maximum() < dp->time / 60.0 + 5 || dp->time / 60.0 + 15 < timeLine->maximum())) { - minMinutes = fmax(dp->time / 60.0 + 5, minMinutes); - timeLine->setMaximum(minMinutes); - timeLine->updateTicks(); - } - if (!activeDraggedHandler && (depthLine->maximum() < max_depth + M_OR_FT(10, 30) || max_depth + M_OR_FT(10, 30) < depthLine->maximum())) { - minDepth = fmax(max_depth + M_OR_FT(10, 30), minDepth); - depthLine->setMaximum(minDepth); - depthLine->updateTicks(); - } - - // Re-position the user generated dive handlers - int last = 0; - for (int i = 0; i < plannerModel->rowCount(); i++) { - struct divedatapoint datapoint = plannerModel->at(i); - if (datapoint.time == 0) // those are the magic entries for tanks - continue; - DiveHandler *h = handles.at(i); - h->setPos(timeLine->posAtValue(datapoint.time / 60), depthLine->posAtValue(datapoint.depth)); - QPointF p1 = (last == i) ? QPointF(timeLine->posAtValue(0), depthLine->posAtValue(0)) : handles[last]->pos(); - QPointF p2 = handles[i]->pos(); - QLineF line(p1, p2); - QPointF pos = line.pointAt(0.5); - gases[i]->setPos(pos); - gases[i]->setText(dpGasToStr(plannerModel->at(i))); - last = i; - } - - // (re-) create the profile with different colors for segments that were - // entered vs. segments that were calculated - double lastx = timeLine->posAtValue(0); - double lasty = depthLine->posAtValue(0); - - QPolygonF poly; - poly.append(QPointF(lastx, lasty)); - + // Code ported to the new profile is deleted. This part that I left here + // is because I didn't fully understood the reason of the magic with + // the plannerModel. bool oldRecalc = plannerModel->setRecalc(false); plannerModel->removeDeco(); - - unsigned int lastdepth = 0; - for (dp = diveplan.dp; dp != NULL; dp = dp->next) { - if (dp->time == 0) // magic entry for available tank - continue; - double xpos = timeLine->posAtValue(dp->time / 60.0); - double ypos = depthLine->posAtValue(dp->depth); - if (!dp->entered) { - QGraphicsLineItem *item = new QGraphicsLineItem(lastx, lasty, xpos, ypos); - item->setPen(QPen(QBrush(Qt::red), 0)); - - scene()->addItem(item); - lines << item; - if (dp->depth) { - if (dp->depth == lastdepth || dp->o2 != dp->next->o2 || dp->he != dp->next->he) - plannerModel->addStop(dp->depth, dp->time, dp->next->o2, dp->next->he, 0, false); - lastdepth = dp->depth; - } - } - lastx = xpos; - lasty = ypos; - poly.append(QPointF(lastx, lasty)); - } + // Here we plotted the old planner profile. why there's the magic with the plannerModel here? plannerModel->setRecalc(oldRecalc); - - diveBg->setPolygon(poly); - QRectF b = poly.boundingRect(); - QLinearGradient pat( - b.x(), - b.y(), - b.x(), - b.height() + b.y()); - - pat.setColorAt(1, profile_color[DEPTH_BOTTOM].first()); - pat.setColorAt(0, profile_color[DEPTH_TOP].first()); - diveBg->setBrush(pat); - plannerModel->deleteTemporaryPlan(); } - -void DivePlannerGraphics::resizeEvent(QResizeEvent *event) -{ - QGraphicsView::resizeEvent(event); - fitInView(sceneRect(), Qt::IgnoreAspectRatio); -} - -void DivePlannerGraphics::showEvent(QShowEvent *event) -{ - QGraphicsView::showEvent(event); - fitInView(sceneRect(), Qt::IgnoreAspectRatio); -} - -void DivePlannerGraphics::mouseMoveEvent(QMouseEvent *event) -{ - QPointF mappedPos = mapToScene(event->pos()); - - - double xpos = timeLine->valueAt(mappedPos); - double ypos = depthLine->valueAt(mappedPos); - - xpos = (xpos > timeLine->maximum()) ? timeLine->posAtValue(timeLine->maximum()) : (xpos < timeLine->minimum()) ? timeLine->posAtValue(timeLine->minimum()) : timeLine->posAtValue(xpos); - - ypos = (ypos > depthLine->maximum()) ? depthLine->posAtValue(depthLine->maximum()) : (ypos < depthLine->minimum()) ? depthLine->posAtValue(depthLine->minimum()) : depthLine->posAtValue(ypos); - - verticalLine->setPos(xpos, fromPercent(0, Qt::Vertical)); - horizontalLine->setPos(fromPercent(0, Qt::Horizontal), ypos); - - depthString->setPos(fromPercent(1, Qt::Horizontal), ypos); - timeString->setPos(xpos + 1, fromPercent(95, Qt::Vertical)); - - if (isPointOutOfBoundaries(mappedPos)) - return; - - depthString->setText(get_depth_string(depthLine->valueAt(mappedPos), true, false)); - timeString->setText(QString::number(rint(timeLine->valueAt(mappedPos))) + "min"); - - // calculate the correct color for the depthString. - // QGradient doesn't returns it's interpolation, meh. - double percent = depthLine->percentAt(mappedPos); - QColor &startColor = profile_color[SAMPLE_SHALLOW].first(); - QColor &endColor = profile_color[SAMPLE_DEEP].first(); - short redDelta = (endColor.red() - startColor.red()) * percent + startColor.red(); - short greenDelta = (endColor.green() - startColor.green()) * percent + startColor.green(); - short blueDelta = (endColor.blue() - startColor.blue()) * percent + startColor.blue(); - depthString->setBrush(QColor(redDelta, greenDelta, blueDelta)); - - if (activeDraggedHandler) - moveActiveHandler(mappedPos, handles.indexOf(activeDraggedHandler)); - if (!handles.count()) - return; - - if (handles.last()->x() > mappedPos.x()) { - verticalLine->setPen(QPen(QBrush(Qt::red), 0, Qt::SolidLine)); - horizontalLine->setPen(QPen(QBrush(Qt::red), 0, Qt::SolidLine)); - } else { - verticalLine->setPen(QPen(Qt::DotLine)); - horizontalLine->setPen(QPen(Qt::DotLine)); - } -} - -void DivePlannerGraphics::moveActiveHandler(const QPointF &mappedPos, const int pos) -{ - divedatapoint data = plannerModel->at(pos); - int mintime = 0, maxtime = (timeLine->maximum() + 10) * 60; - if (pos > 0) - mintime = plannerModel->at(pos - 1).time; - if (pos < plannerModel->size() - 1) - maxtime = plannerModel->at(pos + 1).time; - - int minutes = rint(timeLine->valueAt(mappedPos)); - if (minutes * 60 <= mintime || minutes * 60 >= maxtime) - return; - - int milimeters = rint(depthLine->valueAt(mappedPos) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); - double xpos = timeLine->posAtValue(minutes); - double ypos = depthLine->posAtValue(milimeters); - - data.depth = milimeters; - data.time = rint(timeLine->valueAt(mappedPos)) * 60; - - plannerModel->editStop(pos, data); - - activeDraggedHandler->setPos(QPointF(xpos, ypos)); - qDeleteAll(lines); - lines.clear(); - drawProfile(); -} - -bool DivePlannerGraphics::isPointOutOfBoundaries(const QPointF &point) -{ - double xpos = timeLine->valueAt(point); - double ypos = depthLine->valueAt(point); - - if (xpos > timeLine->maximum() || - xpos < timeLine->minimum() || - ypos > depthLine->maximum() || - ypos < depthLine->minimum()) { - return true; - } - return false; -} - -void DivePlannerGraphics::mousePressEvent(QMouseEvent *event) -{ - if (event->modifiers()) { - QGraphicsView::mousePressEvent(event); - return; - } - - QPointF mappedPos = mapToScene(event->pos()); - if (event->button() == Qt::LeftButton) { - Q_FOREACH(QGraphicsItem * item, scene()->items(mappedPos, Qt::IntersectsItemBoundingRect, Qt::AscendingOrder, transform())) { - if (DiveHandler *h = qgraphicsitem_cast<DiveHandler *>(item)) { - activeDraggedHandler = h; - activeDraggedHandler->setBrush(Qt::red); - originalHandlerPos = activeDraggedHandler->pos(); - } - } - } - QGraphicsView::mousePressEvent(event); -} - -void DivePlannerGraphics::mouseReleaseEvent(QMouseEvent *event) -{ - if (activeDraggedHandler) { - /* we already deal with all the positioning in the life update, - * so all we need to do here is change the color of the handler */ - activeDraggedHandler->setBrush(QBrush(Qt::white)); - activeDraggedHandler = 0; - drawProfile(); - } -} +#endif DiveHandler::DiveHandler() : QGraphicsEllipseItem() { setRect(-5, -5, 10, 10); - setFlag(QGraphicsItem::ItemIgnoresTransformations); - setFlag(QGraphicsItem::ItemIsSelectable); + setFlags(ItemIgnoresTransformations | ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges); setBrush(Qt::white); setZValue(2); } int DiveHandler::parentIndex() { - DivePlannerGraphics *view = qobject_cast<DivePlannerGraphics *>(scene()->views().first()); + ProfileWidget2 *view = qobject_cast<ProfileWidget2 *>(scene()->views().first()); return view->handles.indexOf(this); } @@ -739,7 +183,7 @@ void DiveHandler::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) void DiveHandler::selfRemove() { setSelected(true); - DivePlannerGraphics *view = qobject_cast<DivePlannerGraphics *>(scene()->views().first()); + ProfileWidget2 *view = qobject_cast<ProfileWidget2 *>(scene()->views().first()); view->keyDeleteAction(); } @@ -750,210 +194,13 @@ void DiveHandler::changeGas() plannerModel->setData(index, action->text()); } -void DiveHandler::mousePressEvent(QGraphicsSceneMouseEvent *event) +void DiveHandler::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - if (event->button() != Qt::LeftButton) + ProfileWidget2 *view = qobject_cast<ProfileWidget2*>(scene()->views().first()); + if(view->isPointOutOfBoundaries(event->scenePos())) return; - - if (event->modifiers().testFlag(Qt::ControlModifier)) { - setSelected(true); - } - // mousePressEvent 'grabs' the mouse and keyboard, annoying. - ungrabMouse(); - - /* hack. Sometimes the keyboard is grabbed, sometime it's not, - so, let's force a grab and release, to get rid of a warning. */ - grabKeyboard(); - ungrabKeyboard(); -} - -void Ruler::setMaximum(double maximum) -{ - max = maximum; -} - -void Ruler::setMinimum(double minimum) -{ - min = minimum; -} - -void Ruler::setTextColor(const QColor &color) -{ - textColor = color; -} - -void Ruler::eraseAll() -{ - qDeleteAll(ticks); - ticks.clear(); - qDeleteAll(labels); - labels.clear(); -} - -Ruler::Ruler() : unitSystem(0), - orientation(Qt::Horizontal), - min(0), - max(0), - interval(0), - tickSize(0) -{ -} - -Ruler::~Ruler() -{ - eraseAll(); -} - -void Ruler::setOrientation(Qt::Orientation o) -{ - orientation = o; - // position the elements on the screen. - setMinimum(minimum()); - setMaximum(maximum()); -} - -void Ruler::updateTicks() -{ - eraseAll(); - - QLineF m = line(); - QGraphicsLineItem *item = NULL; - QGraphicsSimpleTextItem *label = NULL; - - double steps = (max - min) / interval; - qreal pos; - double currValue = min; - - if (orientation == Qt::Horizontal) { - double stepSize = (m.x2() - m.x1()) / steps; - for (pos = m.x1(); pos <= m.x2(); pos += stepSize, currValue += interval) { - item = new QGraphicsLineItem(pos, m.y1(), pos, m.y1() + tickSize, this); - item->setPen(pen()); - ticks.push_back(item); - - label = new QGraphicsSimpleTextItem(QString::number(currValue), this); - label->setBrush(QBrush(textColor)); - label->setFlag(ItemIgnoresTransformations); - label->setPos(pos - label->boundingRect().width() / 2, m.y1() + tickSize + 5); - labels.push_back(label); - } - } else { - double stepSize = (m.y2() - m.y1()) / steps; - for (pos = m.y1(); pos <= m.y2(); pos += stepSize, currValue += interval) { - item = new QGraphicsLineItem(m.x1(), pos, m.x1() - tickSize, pos, this); - item->setPen(pen()); - ticks.push_back(item); - - label = new QGraphicsSimpleTextItem(get_depth_string(currValue, false, false), this); - label->setBrush(QBrush(textColor)); - label->setFlag(ItemIgnoresTransformations); - label->setPos(m.x2() - 80, pos); - labels.push_back(label); - } - } -} - -void Ruler::setTickSize(qreal size) -{ - tickSize = size; -} - -void Ruler::setTickInterval(double i) -{ - interval = i; -} - -qreal Ruler::valueAt(const QPointF &p) -{ - QLineF m = line(); - double retValue = orientation == Qt::Horizontal ? - max * (p.x() - m.x1()) / (m.x2() - m.x1()) : - max * (p.y() - m.y1()) / (m.y2() - m.y1()); - return retValue; -} - -qreal Ruler::posAtValue(qreal value) -{ - QLineF m = line(); - double size = max - min; - double percent = value / size; - double realSize = orientation == Qt::Horizontal ? - m.x2() - m.x1() : - m.y2() - m.y1(); - double retValue = realSize * percent; - retValue = (orientation == Qt::Horizontal) ? - retValue + m.x1() : - retValue + m.y1(); - return retValue; -} - -qreal Ruler::percentAt(const QPointF &p) -{ - qreal value = valueAt(p); - double size = max - min; - double percent = value / size; - return percent; -} - -double Ruler::maximum() const -{ - return max; -} - -double Ruler::minimum() const -{ - return min; -} - -void Ruler::setColor(const QColor &color) -{ - QPen defaultPen(color); - defaultPen.setJoinStyle(Qt::RoundJoin); - defaultPen.setCapStyle(Qt::RoundCap); - defaultPen.setWidth(2); - defaultPen.setCosmetic(true); - setPen(defaultPen); -} - -Button::Button(QObject *parent, QGraphicsItem *itemParent) : QObject(parent), - QGraphicsRectItem(itemParent), - icon(new QGraphicsPixmapItem(this)), - text(new QGraphicsSimpleTextItem(this)) -{ - icon->setPos(0, 0); - text->setPos(0, 0); - setFlag(ItemIgnoresTransformations); - setPen(QPen(QBrush(), 0)); -} - -void Button::setPixmap(const QPixmap &pixmap) -{ - icon->setPixmap(pixmap); - if (pixmap.isNull()) - icon->hide(); - else - icon->show(); - - setRect(childrenBoundingRect()); -} - -void Button::setText(const QString &t) -{ - text->setText(t); - if (icon->pixmap().isNull()) { - icon->hide(); - text->setPos(0, 0); - } else { - icon->show(); - text->setPos(22, 0); - } - setRect(childrenBoundingRect()); -} - -void Button::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - event->ignore(); - emit clicked(); + QGraphicsEllipseItem::mouseMoveEvent(event); + emit moved(); } DivePlannerWidget::DivePlannerWidget(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) @@ -982,11 +229,11 @@ DivePlannerWidget::DivePlannerWidget(QWidget *parent, Qt::WindowFlags f) : QWidg connect(CylindersModel::instance(), SIGNAL(rowsRemoved(QModelIndex, int, int)), GasSelectionModel::instance(), SLOT(repopulate())); connect(CylindersModel::instance(), SIGNAL(dataChanged(QModelIndex, QModelIndex)), - plannerModel, SLOT(emitCylinderModelEdited())); + plannerModel, SIGNAL(cylinderModelEdited())); connect(CylindersModel::instance(), SIGNAL(rowsInserted(QModelIndex, int, int)), - plannerModel, SLOT(emitCylinderModelEdited())); + plannerModel, SIGNAL(cylinderModelEdited())); connect(CylindersModel::instance(), SIGNAL(rowsRemoved(QModelIndex, int, int)), - plannerModel, SLOT(emitCylinderModelEdited())); + plannerModel, SIGNAL(cylinderModelEdited())); ui.tableWidget->setBtnToolTip(tr("add dive data point")); connect(ui.startTime, SIGNAL(timeChanged(QTime)), plannerModel, SLOT(setStartTime(QTime))); @@ -1067,11 +314,6 @@ bool DivePlannerPointsModel::recalcQ() return recalc; } -void DivePlannerPointsModel::emitCylinderModelEdited() -{ - cylinderModelEdited(); -} - int DivePlannerPointsModel::columnCount(const QModelIndex &parent) const { return COLUMNS; @@ -1264,7 +506,9 @@ bool DivePlannerPointsModel::addGas(int o2, int he) sanitize_gasmix(&cyl->gasmix); /* The depth to change to that gas is given by the depth where its pO2 is 1.6 bar. * The user should be able to change this depth manually. */ - cyl->depth.mm = 1600 * 1000 / get_o2(&mix) * 10 - 10000; + pressure_t modppO2; + modppO2.mbar = 1600; + cyl->depth = gas_mod(&cyl->gasmix, modppO2); CylindersModel::instance()->setDive(stagingDive); return true; } @@ -1388,7 +632,7 @@ void DivePlannerPointsModel::remove(const QModelIndex &index) endRemoveRows(); } -struct diveplan DivePlannerPointsModel::getDiveplan() +struct diveplan &DivePlannerPointsModel::getDiveplan() { return diveplan; } @@ -1619,46 +863,3 @@ void DivePlannerPointsModel::createPlan() CylindersModel::instance()->update(); plannerModel->setRecalc(oldRecalc); } - -ExpanderGraphics::ExpanderGraphics(QGraphicsItem *parent) : QGraphicsRectItem(parent), - icon(new QGraphicsPixmapItem(this)), - increaseBtn(new Button(0, this)), - decreaseBtn(new Button(0, this)), - bg(new QGraphicsPixmapItem(this)), - leftWing(new QGraphicsPixmapItem(this)), - rightWing(new QGraphicsPixmapItem(this)) -{ - QPixmap p; -#define CREATE(item, pixmap) \ - p = QPixmap(QString(pixmap)); \ - item->setPixmap(p); - - CREATE(icon, ":icon_time"); - CREATE(bg, ":round_base"); - CREATE(leftWing, ":left_wing"); - CREATE(rightWing, ":right_wing"); -#undef CREATE - - decreaseBtn->setPixmap(QPixmap(":arrow_down")); - increaseBtn->setPixmap(QPixmap(":arrow_up")); - - setFlag(ItemIgnoresTransformations); - leftWing->setZValue(-2); - rightWing->setZValue(-2); - bg->setZValue(-1); - - leftWing->setPos(0, 0); - bg->setPos(leftWing->pos().x() + leftWing->boundingRect().width() - 60, 5); - rightWing->setPos(leftWing->pos().x() + leftWing->boundingRect().width() - 20, 0); - decreaseBtn->setPos(leftWing->pos().x(), leftWing->pos().y()); - increaseBtn->setPos(rightWing->pos().x(), rightWing->pos().y()); - icon->setPos(bg->pos().x(), bg->pos().y() - 5); - - //I need to bottom align the items, I need to make the 0,0 ( orgin ) to be - // the bottom of this item, so shift everything up. - QRectF r = childrenBoundingRect(); - Q_FOREACH(QGraphicsItem * i, childItems()) { - i->setPos(i->pos().x(), i->pos().y() - r.height()); - } - setScale(0.7); -} diff --git a/qt-ui/diveplanner.h b/qt-ui/diveplanner.h index 506953275..4aa5f0094 100644 --- a/qt-ui/diveplanner.h +++ b/qt-ui/diveplanner.h @@ -55,7 +55,7 @@ public: void editStop(int row, divedatapoint newData); divedatapoint at(int row); int size(); - struct diveplan getDiveplan(); + struct diveplan &getDiveplan(); QStringList &getGasList(); QVector<QPair<int, int> > collectGases(dive *d); int lastEnteredPoint(); @@ -80,7 +80,6 @@ slots: void deleteTemporaryPlan(); void loadFromDive(dive *d); void restoreBackupDive(); - void emitCylinderModelEdited(); signals: void planCreated(); @@ -102,47 +101,16 @@ private: QVector<QPair<int, int> > oldGases; }; -class Button : public QObject, public QGraphicsRectItem { - Q_OBJECT -public: - Button(QObject *parent = 0, QGraphicsItem *itemParent = 0); - void setText(const QString &text); - void setPixmap(const QPixmap &pixmap); - -protected: - virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); -signals: - void clicked(); - -private: - QGraphicsPixmapItem *icon; - QGraphicsSimpleTextItem *text; -}; - - -class ExpanderGraphics : public QGraphicsRectItem { -public: - ExpanderGraphics(QGraphicsItem *parent = 0); - - QGraphicsPixmapItem *icon; - Button *increaseBtn; - Button *decreaseBtn; - -private: - QGraphicsPixmapItem *bg; - QGraphicsPixmapItem *leftWing; - QGraphicsPixmapItem *rightWing; -}; - class DiveHandler : public QObject, public QGraphicsEllipseItem { Q_OBJECT public: DiveHandler(); protected: - void mousePressEvent(QGraphicsSceneMouseEvent *event); void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); - + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); +signals: + void moved(); private: int parentIndex(); public @@ -151,114 +119,6 @@ slots: void changeGas(); }; -class Ruler : public QGraphicsLineItem { -public: - Ruler(); - ~Ruler(); - void setMinimum(double minimum); - void setMaximum(double maximum); - void setTickInterval(double interval); - void setOrientation(Qt::Orientation orientation); - void setTickSize(qreal size); - void updateTicks(); - double minimum() const; - double maximum() const; - qreal valueAt(const QPointF &p); - qreal percentAt(const QPointF &p); - qreal posAtValue(qreal value); - void setColor(const QColor &color); - void setTextColor(const QColor &color); - int unitSystem; - -private: - void eraseAll(); - - Qt::Orientation orientation; - QList<QGraphicsLineItem *> ticks; - QList<QGraphicsSimpleTextItem *> labels; - double min; - double max; - double interval; - double tickSize; - QColor textColor; -}; - -class DivePlannerGraphics : public QGraphicsView { - Q_OBJECT -public: - DivePlannerGraphics(QWidget *parent = 0); - -protected: - virtual void mouseDoubleClickEvent(QMouseEvent *event); - virtual void showEvent(QShowEvent *event); - virtual void resizeEvent(QResizeEvent *event); - virtual void mouseMoveEvent(QMouseEvent *event); - virtual void mousePressEvent(QMouseEvent *event); - virtual void mouseReleaseEvent(QMouseEvent *event); - bool isPointOutOfBoundaries(const QPointF &point); - qreal fromPercent(qreal percent, Qt::Orientation orientation); -public -slots: - void settingsChanged(); -private -slots: - void keyEscAction(); - void keyDeleteAction(); - void keyUpAction(); - void keyDownAction(); - void keyLeftAction(); - void keyRightAction(); - void increaseTime(); - void increaseDepth(); - void decreaseTime(); - void decreaseDepth(); - void drawProfile(); - void pointInserted(const QModelIndex &, int start, int end); - void pointsRemoved(const QModelIndex &, int start, int end); - -private: - void moveActiveHandler(const QPointF &MappedPos, const int pos); - - /* This are the lines of the plotted dive. */ - QList<QGraphicsLineItem *> lines; - - /* This is the user-entered handles. */ - QList<DiveHandler *> handles; - QList<QGraphicsSimpleTextItem *> gases; - - /* those are the lines that follows the mouse. */ - QGraphicsLineItem *verticalLine; - QGraphicsLineItem *horizontalLine; - - /* This is the handler that's being dragged. */ - DiveHandler *activeDraggedHandler; - - // When we start to move the handler, this pos is saved. - // so we can revert it later. - QPointF originalHandlerPos; - - /* this is the background of the dive, the blue-gradient. */ - QGraphicsPolygonItem *diveBg; - - /* This is the bottom ruler - the x axis, and it's associated text */ - Ruler *timeLine; - QGraphicsSimpleTextItem *timeString; - - /* this is the left ruler, the y axis, and it's associated text. */ - Ruler *depthLine; - QGraphicsSimpleTextItem *depthString; - - /* Buttons */ - ExpanderGraphics *depthHandler; - ExpanderGraphics *timeHandler; - - int minMinutes; // this holds the minimum requested window time - int minDepth; // this holds the minimum requested window depth - int dpMaxTime; // this is the time of the dive calculated by the deco. - - friend class DiveHandler; -}; - #include "ui_diveplanner.h" class DivePlannerWidget : public QWidget { @@ -277,4 +137,7 @@ private: Ui::DivePlanner ui; }; +QString gasToStr(const int o2Permille, const int hePermille); +QString dpGasToStr(const divedatapoint &p); + #endif // DIVEPLANNER_H diff --git a/qt-ui/downloadfromdivecomputer.cpp b/qt-ui/downloadfromdivecomputer.cpp index 17c2a4eaa..71f428b14 100644 --- a/qt-ui/downloadfromdivecomputer.cpp +++ b/qt-ui/downloadfromdivecomputer.cpp @@ -34,8 +34,7 @@ struct mydescriptor { unsigned int model; }; -namespace DownloadFromDcGlobal -{ +namespace DownloadFromDcGlobal { const char *err_string; }; @@ -56,7 +55,6 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) : progress_bar_text = ""; - fill_device_list(); fill_computer_list(); ui.chooseDumpFile->setEnabled(ui.dumpToFile->isChecked()); @@ -74,7 +72,6 @@ DownloadFromDCWidget::DownloadFromDCWidget(QWidget *parent, Qt::WindowFlags f) : if (default_dive_computer_product) ui.product->setCurrentIndex(ui.product->findText(default_dive_computer_product)); } - connect(ui.product, SIGNAL(currentIndexChanged(int)), this, SLOT(on_product_currentIndexChanged()), Qt::UniqueConnection); if (default_dive_computer_device) ui.device->setEditText(default_dive_computer_device); @@ -104,7 +101,7 @@ void DownloadFromDCWidget::updateState(states state) return; if (state == INITIAL) { - fill_device_list(); + fill_device_list(DC_TYPE_OTHER); ui.progressBar->hide(); markChildrenAsEnabled(); timer->stop(); @@ -176,6 +173,7 @@ void DownloadFromDCWidget::updateState(states state) void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString &vendor) { + int dcType = DC_TYPE_SERIAL; QAbstractItemModel *currentModel = ui.product->model(); if (!currentModel) return; @@ -183,15 +181,19 @@ void DownloadFromDCWidget::on_vendor_currentIndexChanged(const QString &vendor) productModel = new QStringListModel(productList[vendor]); ui.product->setModel(productModel); + if (vendor == QString("Uemis")) + dcType = DC_TYPE_UEMIS; + fill_device_list(dcType); + // Memleak - but deleting gives me a crash. //currentModel->deleteLater(); } -void DownloadFromDCWidget::on_product_currentIndexChanged() +void DownloadFromDCWidget::on_product_currentIndexChanged(const QString &product) { // Set up the DC descriptor dc_descriptor_t *descriptor = NULL; - descriptor = descriptorLookup[ui.vendor->currentText() + ui.product->currentText()]; + descriptor = descriptorLookup[ui.vendor->currentText() + product]; // call dc_descriptor_get_transport to see if the dc_transport_t is DC_TRANSPORT_SERIAL if (dc_descriptor_get_transport(descriptor) == DC_TRANSPORT_SERIAL) { @@ -378,10 +380,20 @@ void DownloadFromDCWidget::onDownloadThreadFinished() // down in the dive_table for (int i = dive_table.nr - 1; i >= previousLast; i--) delete_single_dive(i); - } else { + } else if (dive_table.nr) { + int uniqId, idx; + // remember the last downloaded dive (on most dive computers this will be the chronologically + // first new dive) and select it again after processing all the dives + MainWindow::instance()->dive_list()->unselectDives(); + uniqId = get_dive(dive_table.nr - 1)->id; process_dives(true, preferDownloaded()); + // after process_dives does any merging or resorting needed, we need + // to recreate the model for the dive list so we can select the newest dive + MainWindow::instance()->recreateDiveList(); + idx = get_idx_by_uniq_id(uniqId); + MainWindow::instance()->dive_list()->selectDive(idx, true); } - } else if (currentState == CANCELLING || currentState == CANCELLED){ + } else if (currentState == CANCELLING || currentState == CANCELLED) { if (import_thread_cancelled) { // walk backwards so we don't keep moving the dives // down in the dive_table @@ -429,11 +441,11 @@ static void fillDeviceList(const char *name, void *data) comboBox->addItem(name); } -void DownloadFromDCWidget::fill_device_list() +void DownloadFromDCWidget::fill_device_list(int dc_type) { int deviceIndex; ui.device->clear(); - deviceIndex = enumerate_devices(fillDeviceList, ui.device); + deviceIndex = enumerate_devices(fillDeviceList, ui.device, dc_type); if (deviceIndex >= 0) ui.device->setCurrentIndex(deviceIndex); } diff --git a/qt-ui/downloadfromdivecomputer.h b/qt-ui/downloadfromdivecomputer.h index e20ba3051..3de102bfd 100644 --- a/qt-ui/downloadfromdivecomputer.h +++ b/qt-ui/downloadfromdivecomputer.h @@ -42,7 +42,7 @@ slots: void on_cancel_clicked(); void on_search_clicked(); void on_vendor_currentIndexChanged(const QString &vendor); - void on_product_currentIndexChanged(); + void on_product_currentIndexChanged(const QString &product); void onDownloadThreadFinished(); void updateProgressBar(); @@ -68,7 +68,7 @@ private: QStringListModel *vendorModel; QStringListModel *productModel; void fill_computer_list(); - void fill_device_list(); + void fill_device_list(int dc_type); QString logFile; QString dumpFile; QTimer *timer; diff --git a/qt-ui/exif.cpp b/qt-ui/exif.cpp index 82601577f..1aee47acb 100644 --- a/qt-ui/exif.cpp +++ b/qt-ui/exif.cpp @@ -34,8 +34,7 @@ using std::string; -namespace -{ +namespace { // IF Entry struct IFEntry { // Raw fields @@ -459,15 +458,15 @@ int EXIFInfo::parseFromEXIFSegment(const unsigned char *buf, unsigned len) // GPS latitude if (format == 5 && length == 3) { this->GeoLocation.LatComponents.degrees = - parseEXIFRational(buf + data + tiff_header_start, alignIntel); + parseEXIFRational(buf + data + tiff_header_start, alignIntel); this->GeoLocation.LatComponents.minutes = - parseEXIFRational(buf + data + tiff_header_start + 8, alignIntel); + parseEXIFRational(buf + data + tiff_header_start + 8, alignIntel); this->GeoLocation.LatComponents.seconds = - parseEXIFRational(buf + data + tiff_header_start + 16, alignIntel); + parseEXIFRational(buf + data + tiff_header_start + 16, alignIntel); this->GeoLocation.Latitude = - this->GeoLocation.LatComponents.degrees + - this->GeoLocation.LatComponents.minutes / 60 + - this->GeoLocation.LatComponents.seconds / 3600; + this->GeoLocation.LatComponents.degrees + + this->GeoLocation.LatComponents.minutes / 60 + + this->GeoLocation.LatComponents.seconds / 3600; if ('S' == this->GeoLocation.LatComponents.direction) this->GeoLocation.Latitude = -this->GeoLocation.Latitude; } @@ -484,15 +483,15 @@ int EXIFInfo::parseFromEXIFSegment(const unsigned char *buf, unsigned len) // GPS longitude if (format == 5 && length == 3) { this->GeoLocation.LonComponents.degrees = - parseEXIFRational(buf + data + tiff_header_start, alignIntel); + parseEXIFRational(buf + data + tiff_header_start, alignIntel); this->GeoLocation.LonComponents.minutes = - parseEXIFRational(buf + data + tiff_header_start + 8, alignIntel); + parseEXIFRational(buf + data + tiff_header_start + 8, alignIntel); this->GeoLocation.LonComponents.seconds = - parseEXIFRational(buf + data + tiff_header_start + 16, alignIntel); + parseEXIFRational(buf + data + tiff_header_start + 16, alignIntel); this->GeoLocation.Longitude = - this->GeoLocation.LonComponents.degrees + - this->GeoLocation.LonComponents.minutes / 60 + - this->GeoLocation.LonComponents.seconds / 3600; + this->GeoLocation.LonComponents.degrees + + this->GeoLocation.LonComponents.minutes / 60 + + this->GeoLocation.LonComponents.seconds / 3600; if ('W' == this->GeoLocation.LonComponents.direction) this->GeoLocation.Longitude = -this->GeoLocation.Longitude; } @@ -509,7 +508,7 @@ int EXIFInfo::parseFromEXIFSegment(const unsigned char *buf, unsigned len) // GPS altitude reference if (format == 5) { this->GeoLocation.Altitude = - parseEXIFRational(buf + data + tiff_header_start, alignIntel); + parseEXIFRational(buf + data + tiff_header_start, alignIntel); if (1 == this->GeoLocation.AltitudeRef) this->GeoLocation.Altitude = -this->GeoLocation.Altitude; } diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp index 1101500d3..8d234194e 100644 --- a/qt-ui/globe.cpp +++ b/qt-ui/globe.cpp @@ -64,7 +64,7 @@ GlobeGPS::GlobeGPS(QWidget *parent) : MarbleWidget(parent), setProjection(Marble::Spherical); setAnimationsEnabled(true); - Q_FOREACH(AbstractFloatItem * i, floatItems()) { + Q_FOREACH (AbstractFloatItem *i, floatItems()) { i->setVisible(false); } @@ -142,7 +142,7 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit) struct dive *dive; bool clear = !(QApplication::keyboardModifiers() & Qt::ControlModifier); QList<int> selectedDiveIds; - for_each_dive(idx, dive) { + for_each_dive (idx, dive) { long lat_diff, lon_diff; if (!dive_has_gps_location(dive)) continue; @@ -175,7 +175,7 @@ void GlobeGPS::repopulateLabels() int idx = 0; struct dive *dive; - for_each_dive(idx, dive) { + for_each_dive (idx, dive) { if (dive_has_gps_location(dive)) { GeoDataPlacemark *place = new GeoDataPlacemark(dive->location); place->setCoordinate(dive->longitude.udeg / 1000000.0, dive->latitude.udeg / 1000000.0, 0, GeoDataCoordinates::Degree); @@ -211,8 +211,7 @@ void GlobeGPS::centerOnCurrentDive() { struct dive *dive = current_dive; // dive has changed, if we had the 'editingDive', hide it. - if (messageWidget->isVisible() - && (!dive || dive_has_gps_location(dive) || amount_selected != 1 )) + if (messageWidget->isVisible() && (!dive || dive_has_gps_location(dive) || amount_selected != 1)) messageWidget->hide(); editingDiveLocation = false; @@ -222,8 +221,7 @@ void GlobeGPS::centerOnCurrentDive() qreal longitude = dive->longitude.udeg / 1000000.0; qreal latitude = dive->latitude.udeg / 1000000.0; - if ((!dive_has_gps_location(dive) || MainWindow::instance()->information()->isEditing()) - && amount_selected == 1) { + if ((!dive_has_gps_location(dive) || MainWindow::instance()->information()->isEditing()) && amount_selected == 1) { prepareForGetDiveCoordinates(); return; } @@ -261,7 +259,7 @@ void GlobeGPS::zoomOutForNoGPS() // this is called if the dive has no GPS location. // zoom out quite a bit to show the globe and remember that the next time // we show a dive with GPS location we need to zoom in again - if(fixZoomTimer->isActive()) + if (fixZoomTimer->isActive()) fixZoomTimer->stop(); setZoom(1200, Marble::Automatic); if (!needResetZoom) { @@ -300,7 +298,7 @@ void GlobeGPS::changeDiveGeoPosition(qreal lon, qreal lat, GeoDataCoordinates::U // but we keep the code here that changes the coordinates for each selected dive int i; struct dive *dive; - for_each_dive(i, dive) { + for_each_dive (i, dive) { if (!dive->selected) continue; dive->latitude.udeg = lrint(lat * 1000000.0); @@ -341,10 +339,23 @@ void GlobeGPS::resizeEvent(QResizeEvent *event) } #else -GlobeGPS::GlobeGPS(QWidget* parent) { setText("MARBLE DISABLED AT BUILD TIME"); } -void GlobeGPS::repopulateLabels() {} -void GlobeGPS::centerOn(dive* dive) {} -bool GlobeGPS::eventFilter(QObject *obj, QEvent *ev) {} -void GlobeGPS::prepareForGetDiveCoordinates(struct dive *dive) {} -void GlobeGPS::reload() {} +GlobeGPS::GlobeGPS(QWidget *parent) +{ + setText("MARBLE DISABLED AT BUILD TIME"); +} +void GlobeGPS::repopulateLabels() +{ +} +void GlobeGPS::centerOnCurrentDive() +{ +} +bool GlobeGPS::eventFilter(QObject *obj, QEvent *ev) +{ +} +void GlobeGPS::prepareForGetDiveCoordinates() +{ +} +void GlobeGPS::reload() +{ +} #endif diff --git a/qt-ui/globe.h b/qt-ui/globe.h index add04ede4..c40eefc46 100644 --- a/qt-ui/globe.h +++ b/qt-ui/globe.h @@ -54,10 +54,11 @@ public: GlobeGPS(QWidget *parent); void reload(); void repopulateLabels(); - void centerOn(struct dive* dive); - bool eventFilter(QObject*, QEvent*); -public slots: - void prepareForGetDiveCoordinates(struct dive *dive); + void centerOnCurrentDive(); + bool eventFilter(QObject *, QEvent *); +public +slots: + void prepareForGetDiveCoordinates(); }; #endif // NO_MARBLE diff --git a/qt-ui/groupedlineedit.cpp b/qt-ui/groupedlineedit.cpp index 517623119..4ba6621e6 100644 --- a/qt-ui/groupedlineedit.cpp +++ b/qt-ui/groupedlineedit.cpp @@ -108,7 +108,7 @@ QStringList GroupedLineEdit::getBlockStringList() { QStringList retList; Private::Block block; - foreach(block, d->blocks) + foreach (block, d->blocks) retList.append(block.text); return retList; } @@ -149,10 +149,10 @@ void GroupedLineEdit::removeAllBlocks() QSize GroupedLineEdit::sizeHint() const { QSize rs( - 40, - document()->findBlock(0).layout()->lineAt(0).height() + - document()->documentMargin() * 2 + - frameWidth() * 2); + 40, + document()->findBlock(0).layout()->lineAt(0).height() + + document()->documentMargin() * 2 + + frameWidth() * 2); return rs; } @@ -189,15 +189,15 @@ void GroupedLineEdit::paintEvent(QPaintEvent *e) QVectorIterator<QColor> i(d->colors); i.toFront(); - foreach(const Private::Block & block, d->blocks) { + foreach (const Private::Block &block, d->blocks) { qreal start_x = line.cursorToX(block.start, QTextLine::Trailing); qreal end_x = line.cursorToX(block.end + 1, QTextLine::Leading); QPainterPath path; QRectF rectangle( - start_x - 1.0 - double(horizontalScrollBar()->value()), - 1.0, - end_x - start_x + 2.0, - double(viewport()->height() - 2)); + start_x - 1.0 - double(horizontalScrollBar()->value()), + 1.0, + end_x - start_x + 2.0, + double(viewport()->height() - 2)); if (!i.hasNext()) i.toFront(); path.addRoundedRect(rectangle, 5.0, 5.0); diff --git a/qt-ui/kmessagewidget.cpp b/qt-ui/kmessagewidget.cpp index c21dea867..2f9ac6870 100644 --- a/qt-ui/kmessagewidget.cpp +++ b/qt-ui/kmessagewidget.cpp @@ -74,7 +74,7 @@ void KMessageWidgetPrivate::createLayout() qDeleteAll(buttons); buttons.clear(); - Q_FOREACH(QAction * action, q->actions()) { + Q_FOREACH (QAction *action, q->actions()) { QToolButton *button = new QToolButton(content); button->setDefaultAction(action); button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); @@ -94,7 +94,7 @@ void KMessageWidgetPrivate::createLayout() QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(); - Q_FOREACH(QToolButton * button, buttons) { + Q_FOREACH (QToolButton *button, buttons) { // For some reason, calling show() is necessary if wordwrap is true, // otherwise the buttons do not show up. It is not needed if // wordwrap is false. @@ -108,7 +108,7 @@ void KMessageWidgetPrivate::createLayout() layout->addWidget(iconLabel); layout->addWidget(textLabel); - Q_FOREACH(QToolButton * button, buttons) { + Q_FOREACH (QToolButton *button, buttons) { layout->addWidget(button); } @@ -238,7 +238,7 @@ void KMessageWidget::setMessageType(KMessageWidget::MessageType type) bg2 = bg1.darker(110); border = bg2.darker(110); d->content->setStyleSheet( - QString(".QFrame {" + QString(".QFrame {" "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," " stop: 0 %1," " stop: 0.1 %2," @@ -248,16 +248,16 @@ void KMessageWidget::setMessageType(KMessageWidget::MessageType type) "margin: %5px;" "}" ".QLabel { color: %6; }").arg(bg0.name()) - .arg(bg1.name()) - .arg(bg2.name()) - .arg(border.name()) - /* + .arg(bg1.name()) + .arg(bg2.name()) + .arg(border.name()) + /* DefaultFrameWidth returns the size of the external margin + border width. We know our border is 1px, so we subtract this from the frame normal QStyle FrameWidth to get our margin */ - .arg(style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this) - 1) - .arg(fg.name())); + .arg(style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this) - 1) + .arg(fg.name())); } QSize KMessageWidget::sizeHint() const diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp index 172e4e2d7..2bb261448 100644 --- a/qt-ui/maintab.cpp +++ b/qt-ui/maintab.cpp @@ -70,7 +70,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), ui.tagWidget->installEventFilter(this); QList<QObject *> statisticsTabWidgets = ui.statisticsTab->children(); - Q_FOREACH(QObject * obj, statisticsTabWidgets) { + Q_FOREACH (QObject *obj, statisticsTabWidgets) { QLabel *label = qobject_cast<QLabel *>(obj); if (label) label->setAlignment(Qt::AlignHCenter); @@ -136,7 +136,7 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent), " background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," " stop: 0 #E0E0E0, stop: 1 #FFFFFF);" "}"); - Q_FOREACH(QGroupBox * box, findChildren<QGroupBox *>()) { + Q_FOREACH (QGroupBox *box, findChildren<QGroupBox *>()) { box->setStyleSheet(gnomeCss); } } @@ -270,10 +270,8 @@ void MainTab::enableEdition(EditMode newEditMode) // We may be editing one or more dives here. backup everything. struct dive *mydive; - for (int i = 0; i < dive_table.nr; i++) { - mydive = get_dive(i); - if (!mydive) - continue; + int i; + for_each_dive (i, mydive) { if (!mydive->selected) continue; @@ -335,6 +333,11 @@ void MainTab::clearEquipment() weightModel->clear(); } +void MainTab::nextInputField(QKeyEvent *event) +{ + keyPressEvent(event); +} + void MainTab::clearInfo() { ui.sacText->clear(); @@ -591,14 +594,12 @@ void MainTab::reload() #define EDIT_SELECTED_DIVES(WHAT) \ do { \ struct dive *mydive = NULL; \ + int _i; \ if (editMode == NONE) \ return; \ \ - for (int _i = 0; _i < dive_table.nr; _i++) { \ - mydive = get_dive(_i); \ - if (!mydive || mydive == current_dive)\ - continue; \ - if (!mydive->selected) \ + for_each_dive (_i, mydive) { \ + if (!mydive->selected || mydive == current_dive) \ continue; \ \ WHAT; \ @@ -666,7 +667,7 @@ void MainTab::acceptChanges() ui.coordinates->text().trimmed().isEmpty())) { struct dive *dive; int i = 0; - for_each_dive(i, dive) { + for_each_dive (i, dive) { QString location(dive->location); if (location == ui.location->text() && (dive->latitude.udeg || dive->longitude.udeg)) { @@ -690,7 +691,7 @@ void MainTab::acceptChanges() DivePlannerPointsModel::instance()->copyCylinders(curr); } else if (editMode != ADD && cylindersModel->changed) { mark_divelist_changed(true); - Q_FOREACH(dive * d, notesBackup.keys()) { + Q_FOREACH (dive *d, notesBackup.keys()) { for (int i = 0; i < MAX_CYLINDERS; i++) { if (notesBackup.keys().count() > 1) // only copy the cylinder type, none of the other values @@ -704,7 +705,7 @@ void MainTab::acceptChanges() if (weightModel->changed) { mark_divelist_changed(true); - Q_FOREACH(dive * d, notesBackup.keys()) { + Q_FOREACH (dive *d, notesBackup.keys()) { for (int i = 0; i < MAX_WEIGHTSYSTEMS; i++) { d->weightsystem[i] = multiEditEquipmentPlaceholder.weightsystem[i]; } @@ -729,7 +730,7 @@ void MainTab::acceptChanges() } // each dive that was selected might have had the temperatures in its active divecomputer changed // so re-populate the temperatures - easiest way to do this is by calling fixup_dive - Q_FOREACH(dive * d, notesBackup.keys()) { + Q_FOREACH (dive *d, notesBackup.keys()) { if (d) fixup_dive(d); } @@ -746,7 +747,7 @@ void MainTab::acceptChanges() // and then clear that flag out on the other side of the sort_table() d->selected = true; sort_table(&dive_table); - for_each_dive(rememberSelected, d) { + for_each_dive (rememberSelected, d) { if (d->selected) { d->selected = false; break; @@ -760,6 +761,7 @@ void MainTab::acceptChanges() editMode = NONE; MainWindow::instance()->refreshDisplay(); MainWindow::instance()->graphics()->replot(); + emit addDiveFinished(); } else { editMode = NONE; MainWindow::instance()->dive_list()->rememberSelection(); @@ -831,10 +833,8 @@ void MainTab::rejectChanges() } struct dive *mydive; - for (int i = 0; i < dive_table.nr; i++) { - mydive = get_dive(i); - if (!mydive) - continue; + int i; + for_each_dive (i, mydive) { if (!mydive->selected) continue; @@ -862,6 +862,7 @@ void MainTab::rejectChanges() delete_single_dive(selected_dive); MainWindow::instance()->dive_list()->reload(DiveTripModel::CURRENT); MainWindow::instance()->dive_list()->restoreSelection(); + emit addDiveFinished(); } if (selected_dive >= 0) { multiEditEquipmentPlaceholder = *get_dive(selected_dive); @@ -938,7 +939,7 @@ void MainTab::on_watertemp_textChanged(const QString &text) validate_temp_field(ui.watertemp, text); } -void MainTab::validate_temp_field(QLineEdit *tempField,const QString &text) +void MainTab::validate_temp_field(QLineEdit *tempField, const QString &text) { static bool missing_unit = false; static bool missing_precision = false; @@ -980,11 +981,11 @@ void MainTab::on_dateTimeEdit_dateTimeChanged(const QDateTime &datetime) void MainTab::saveTags() { EDIT_SELECTED_DIVES( - QString tag; - taglist_free(mydive->tag_list); - mydive->tag_list = NULL; - foreach(tag, ui.tagWidget->getBlockStringList()) - taglist_add_tag(&mydive->tag_list, tag.toUtf8().data());); + QString tag; + taglist_free(mydive->tag_list); + mydive->tag_list = NULL; + foreach (tag, ui.tagWidget->getBlockStringList()) + taglist_add_tag(&mydive->tag_list, tag.toUtf8().data());); } void MainTab::on_tagWidget_textChanged() diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h index d201d2a47..90d3c49ef 100644 --- a/qt-ui/maintab.h +++ b/qt-ui/maintab.h @@ -66,6 +66,10 @@ public: void initialUiSetup(); bool isEditing(); void updateCoordinatesText(qreal lat, qreal lon); + void nextInputField(QKeyEvent *event); +signals: + void addDiveFinished(); + public slots: void addCylinder_clicked(); @@ -81,7 +85,7 @@ slots: void on_notes_textChanged(); void on_airtemp_textChanged(const QString &text); void on_watertemp_textChanged(const QString &text); - void validate_temp_field(QLineEdit *tempField,const QString &text); + void validate_temp_field(QLineEdit *tempField, const QString &text); void on_dateTimeEdit_dateTimeChanged(const QDateTime &datetime); void on_rating_valueChanged(int value); void on_visibility_valueChanged(int value); diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 709693c30..19a16a886 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -43,6 +43,7 @@ #include "printdialog.h" #endif #include "divelogimportdialog.h" +#include "divelogexportdialog.h" #ifndef NO_USERMANUAL #include "usermanual.h" #endif @@ -67,13 +68,13 @@ MainWindow::MainWindow() : QMainWindow(), connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui.ListWidget, SLOT(update())); connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui.ListWidget, SLOT(reloadHeaderActions())); connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui.InfoWidget, SLOT(updateDiveInfo())); - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui.divePlanner, SLOT(settingsChanged())); connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui.divePlannerWidget, SLOT(settingsChanged())); connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), TankInfoModel::instance(), SLOT(update())); connect(ui.actionRecent1, SIGNAL(triggered(bool)), this, SLOT(recentFileTriggered(bool))); connect(ui.actionRecent2, SIGNAL(triggered(bool)), this, SLOT(recentFileTriggered(bool))); connect(ui.actionRecent3, SIGNAL(triggered(bool)), this, SLOT(recentFileTriggered(bool))); connect(ui.actionRecent4, SIGNAL(triggered(bool)), this, SLOT(recentFileTriggered(bool))); + connect(information(), SIGNAL(addDiveFinished()), ui.newProfile, SLOT(setProfileState())); ui.mainErrorMessage->hide(); initialUiSetup(); @@ -84,10 +85,8 @@ MainWindow::MainWindow() : QMainWindow(), ui.globe->reload(); ui.ListWidget->expand(ui.ListWidget->model()->index(0, 0)); ui.ListWidget->scrollTo(ui.ListWidget->model()->index(0, 0), QAbstractItemView::PositionAtCenter); - ui.divePlanner->settingsChanged(); ui.divePlannerWidget->settingsChanged(); - #ifndef ENABLE_PLANNER ui.menuLog->removeAction(ui.actionDivePlanner); #endif @@ -124,14 +123,14 @@ MainWindow *MainWindow::instance() } // this gets called after we download dives from a divecomputer -void MainWindow::refreshDisplay(bool recreateDiveList) +void MainWindow::refreshDisplay(bool doRecreateDiveList) { showError(get_error_string()); ui.InfoWidget->reload(); TankInfoModel::instance()->update(); ui.globe->reload(); - if (recreateDiveList) - ui.ListWidget->reload(DiveTripModel::CURRENT); + if (doRecreateDiveList) + recreateDiveList(); ui.ListWidget->setFocus(); WSInfoModel::instance()->updateInfo(); // refresh the yearly stats if the window has an instance @@ -143,6 +142,11 @@ void MainWindow::refreshDisplay(bool recreateDiveList) } } +void MainWindow::recreateDiveList() +{ + ui.ListWidget->reload(DiveTripModel::CURRENT); +} + void MainWindow::current_dive_changed(int divenr) { if (divenr >= 0) { @@ -189,7 +193,7 @@ void MainWindow::on_actionSaveAs_triggered() file_save_as(); } -ProfileWidget2* MainWindow::graphics() const +ProfileWidget2 *MainWindow::graphics() const { return ui.newProfile; } @@ -273,34 +277,6 @@ void MainWindow::updateLastUsedDir(const QString &dir) s.setValue("LastDir", dir); } -void MainWindow::on_actionExportUDDF_triggered() -{ - QFileInfo fi(system_default_filename()); - QString filename = QFileDialog::getSaveFileName(this, tr("Export UDDF File as"), fi.absolutePath(), - tr("UDDF files (*.uddf *.UDDF)")); - if (!filename.isNull() && !filename.isEmpty()) - export_dives_xslt(filename.toUtf8(), false, "uddf-export.xslt"); -} - -void MainWindow::on_actionExport_CSV_triggered() -{ - QFileInfo fi(system_default_filename()); - QString filename = QFileDialog::getSaveFileName(this, tr("Export CSV File as"), fi.absolutePath(), - tr("CSV files (*.csv *.CSV)")); - - if (!filename.isNull() && !filename.isEmpty()) - export_dives_xslt(filename.toUtf8(), false, "xml2csv.xslt"); -} - -void MainWindow::on_actionExportHTMLworldmap_triggered() -{ - QFileInfo fi(system_default_filename()); - QString filename = QFileDialog::getSaveFileName(this, tr("Export World Map"), fi.absolutePath(), - tr("HTML files (*.html)")); - if (!filename.isNull() && !filename.isEmpty()) - export_worldmap_HTML(filename.toUtf8().data()); -} - void MainWindow::on_actionPrint_triggered() { #ifndef NO_PRINTING @@ -335,21 +311,23 @@ void MainWindow::on_actionDivePlanner_triggered() DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN); DivePlannerPointsModel::instance()->clear(); CylindersModel::instance()->clear(); - for_each_dive(i,dive) { - if(dive->selected){ + for_each_dive (i, dive) { + if (dive->selected) { DivePlannerPointsModel::instance()->copyCylindersFrom(dive); CylindersModel::instance()->copyFromDive(dive); break; } } - ui.stackedWidget->setCurrentIndex(PLANNERPROFILE); ui.infoPane->setCurrentIndex(PLANNERWIDGET); } void MainWindow::showProfile() { enableDcShortcuts(); - ui.stackedWidget->setCurrentIndex(PROFILE); + //TODO: I BROKE THIS BY COMMENTING THE LINE BELOW + // and I'm sleepy now, so I think I should not try to fix right away. + // we don't setCurrentIndex anymore, we ->setPlanState() or ->setAddState() on the ProfileView. + //ui.stackedWidget->setCurrentIndex(PROFILE); ui.infoPane->setCurrentIndex(MAINTAB); } @@ -430,8 +408,9 @@ void MainWindow::on_actionAddDive_triggered() ui.InfoWidget->setCurrentIndex(0); ui.InfoWidget->updateDiveInfo(selected_dive); ui.InfoWidget->addDiveStarted(); - ui.stackedWidget->setCurrentIndex(PLANNERPROFILE); // Planner. ui.infoPane->setCurrentIndex(MAINTAB); + + ui.newProfile->setAddState(); DivePlannerPointsModel::instance()->clear(); DivePlannerPointsModel::instance()->createSimpleDive(); ui.ListWidget->reload(DiveTripModel::CURRENT); @@ -439,6 +418,7 @@ void MainWindow::on_actionAddDive_triggered() void MainWindow::on_actionRenumber_triggered() { + RenumberDialog::instance()->renumberOnlySelected(false); RenumberDialog::instance()->show(); } @@ -462,11 +442,11 @@ void MainWindow::on_actionYearlyStatistics_triggered() yearlyStats->setMinimumWidth(600); yearlyStats->setWindowTitle(tr("Yearly Statistics")); yearlyStats->setWindowIcon(QIcon(":subsurface-icon")); - QShortcut* closeKey = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), yearlyStats); + QShortcut *closeKey = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), yearlyStats); connect(closeKey, SIGNAL(activated()), yearlyStats, SLOT(close())); closeKey = new QShortcut(QKeySequence(Qt::Key_Escape), yearlyStats); connect(closeKey, SIGNAL(activated()), yearlyStats, SLOT(close())); - QShortcut* quitKey = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), yearlyStats); + QShortcut *quitKey = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), yearlyStats); connect(quitKey, SIGNAL(activated()), this, SLOT(close())); } /* problem here is that without more MainWindow variables or a separate YearlyStatistics @@ -873,7 +853,7 @@ void MainWindow::addRecentFile(const QStringList &newFiles) } } - foreach(const QString & file, newFiles) { + foreach (const QString &file, newFiles) { int index = files.indexOf(file); if (index >= 0) { @@ -881,7 +861,7 @@ void MainWindow::addRecentFile(const QStringList &newFiles) } } - foreach(const QString & file, newFiles) { + foreach (const QString &file, newFiles) { if (QFile::exists(file)) { files.prepend(file); } @@ -929,7 +909,7 @@ void MainWindow::removeRecentFile(QStringList failedFiles) } } - foreach(QString file, failedFiles) + foreach (QString file, failedFiles) files.removeAll(file); for (int c = 1; c <= 4; c++) { @@ -965,12 +945,7 @@ void MainWindow::recentFileTriggered(bool checked) int MainWindow::file_save_as(void) { QString filename; - const char *default_filename; - - if (existing_filename) - default_filename = existing_filename; - else - default_filename = prefs.default_filename; + const char *default_filename = existing_filename; filename = QFileDialog::getSaveFileName(this, tr("Save File as"), default_filename, tr("Subsurface XML files (*.ssrf *.xml *.XML)")); if (filename.isNull() || filename.isEmpty()) @@ -1128,14 +1103,20 @@ void MainWindow::editCurrentDive() if (defaultDC == "manually added dive") { disableDcShortcuts(); DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::ADD); - ui.stackedWidget->setCurrentIndex(PLANNERPROFILE); // Planner. + //TODO: I BROKE THIS BY COMMENTING THE LINE BELOW + // and I'm sleepy now, so I think I should not try to fix right away. + // we don't setCurrentIndex anymore, we ->setPlanState() or ->setAddState() on the ProfileView. + //ui.stackedWidget->setCurrentIndex(PLANNERPROFILE); // Planner. ui.infoPane->setCurrentIndex(MAINTAB); DivePlannerPointsModel::instance()->loadFromDive(d); ui.InfoWidget->enableEdition(MainTab::MANUALLY_ADDED_DIVE); } else if (defaultDC == "planned dive") { disableDcShortcuts(); DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::PLAN); - ui.stackedWidget->setCurrentIndex(PLANNERPROFILE); // Planner. + //TODO: I BROKE THIS BY COMMENTING THE LINE BELOW + // and I'm sleepy now, so I think I should not try to fix right away. + // we don't setCurrentIndex anymore, we ->setPlanState() or ->setAddState() on the ProfileView. + //ui.stackedWidget->setCurrentIndex(PLANNERPROFILE); // Planner. ui.infoPane->setCurrentIndex(PLANNERWIDGET); DivePlannerPointsModel::instance()->loadFromDive(d); ui.InfoWidget->enableEdition(MainTab::MANUALLY_ADDED_DIVE); @@ -1221,3 +1202,9 @@ void MainWindow::on_profScaled_clicked(bool triggered) } #undef TOOLBOX_PREF_PROFILE + +void MainWindow::on_actionExport_triggered() +{ + DiveLogExportDialog *diveLogExport = new DiveLogExportDialog(this); + diveLogExport->show(); +} diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 60081e957..a658fe3cc 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -42,10 +42,6 @@ public: COLLAPSED, EXPANDED }; - enum StackWidgetIndexes { - PROFILE, - PLANNERPROFILE - }; enum InfoWidgetIndexes { MAINTAB, PLANNERWIDGET @@ -90,9 +86,6 @@ slots: void on_actionSave_triggered(); void on_actionSaveAs_triggered(); void on_actionClose_triggered(); - void on_actionExportUDDF_triggered(); - void on_actionExport_CSV_triggered(); - void on_actionExportHTMLworldmap_triggered(); void on_actionPrint_triggered(); void on_actionPreferences_triggered(); void on_actionQuit_triggered(); @@ -146,13 +139,16 @@ slots: void on_profSAC_clicked(bool triggered); void on_profScaled_clicked(bool triggered); + void on_actionExport_triggered(); + protected: void closeEvent(QCloseEvent *); public slots: void readSettings(); - void refreshDisplay(bool recreateDiveList = true); + void refreshDisplay(bool doRecreateDiveList = true); + void recreateDiveList(); void showProfile(); void editCurrentDive(); @@ -178,6 +174,4 @@ private: UpdateManager *updateManager; }; -MainWindow *mainWindow(); - #endif // MAINWINDOW_H diff --git a/qt-ui/mainwindow.ui b/qt-ui/mainwindow.ui index 072d321fc..1fd0fa775 100644 --- a/qt-ui/mainwindow.ui +++ b/qt-ui/mainwindow.ui @@ -85,12 +85,8 @@ </layout> </widget> </widget> - <widget class="QStackedWidget" name="stackedWidget"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="page_5"> - <layout class="QGridLayout" name="gridLayout"> + <widget class="QWidget" name="ProfileWidget"> + <layout class="QGridLayout" name="gridLayout"> <property name="leftMargin"> <number>0</number> </property> @@ -493,29 +489,6 @@ </spacer> </item> </layout> - </widget> - <widget class="QWidget" name="page_6"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <item> - <widget class="DivePlannerGraphics" name="divePlanner"/> - </item> - </layout> - </widget> </widget> </widget> <widget class="QSplitter" name="listGlobeSplitter"> @@ -563,7 +536,7 @@ <x>0</x> <y>0</y> <width>1418</width> - <height>25</height> + <height>20</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -576,9 +549,7 @@ <addaction name="actionSaveAs"/> <addaction name="separator"/> <addaction name="actionClose"/> - <addaction name="actionExportUDDF"/> - <addaction name="actionExport_CSV"/> - <addaction name="actionExportHTMLworldmap"/> + <addaction name="actionExport"/> <addaction name="actionPrint"/> <addaction name="actionPreferences"/> <addaction name="separator"/> @@ -702,22 +673,6 @@ <string>Ctrl+W</string> </property> </action> - <action name="actionExportUDDF"> - <property name="text"> - <string>Export &UDDF</string> - </property> - <property name="shortcut"> - <string>Ctrl+U</string> - </property> - </action> - <action name="actionExportHTMLworldmap"> - <property name="text"> - <string>Export HTML World Map</string> - </property> - <property name="shortcut"> - <string>Ctrl+H</string> - </property> - </action> <action name="actionPrint"> <property name="text"> <string>&Print</string> @@ -946,9 +901,15 @@ <string>&Check for Updates</string> </property> </action> - <action name="actionExport_CSV"> + <action name="actionExport"> <property name="text"> - <string>Export CSV</string> + <string>Export</string> + </property> + <property name="toolTip"> + <string>Export Dive Logs</string> + </property> + <property name="shortcut"> + <string>Ctrl+E</string> </property> </action> </widget> diff --git a/qt-ui/modeldelegates.cpp b/qt-ui/modeldelegates.cpp index 9073ac158..d06c6621f 100644 --- a/qt-ui/modeldelegates.cpp +++ b/qt-ui/modeldelegates.cpp @@ -171,7 +171,7 @@ bool ComboBoxDelegate::eventFilter(QObject *object, QEvent *event) QKeyEvent *ev = static_cast<QKeyEvent *>(event); if (ev->key() == Qt::Key_Up || ev->key() == Qt::Key_Down) { currCombo.ignoreSelection = true; - if (!currCombo.comboEditor->completer()->popup()->isVisible()){ + if (!currCombo.comboEditor->completer()->popup()->isVisible()) { currCombo.comboEditor->showPopup(); return true; } diff --git a/qt-ui/models.cpp b/qt-ui/models.cpp index 68603e735..2bc690eb9 100644 --- a/qt-ui/models.cpp +++ b/qt-ui/models.cpp @@ -68,7 +68,7 @@ CylindersModel::CylindersModel(QObject *parent) : current(0), rows(0) // enum {REMOVE, TYPE, SIZE, WORKINGPRESS, START, END, O2, HE, DEPTH}; setHeaderDataStrings(QStringList() << "" << tr("Type") << tr("Size") << tr("WorkPress") << tr("StartPress") << tr("EndPress") << trUtf8("O" UTF8_SUBSCRIPT_2 "%") << tr("He%") #ifdef ENABLE_PLANNER - << tr("Switch at") + << tr("Switch at") #endif ); } @@ -253,11 +253,9 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in case O2: if (CHANGED()) { cyl->gasmix.o2 = string_to_fraction(vString.toUtf8().data()); - if (!cyl->gasmix.o2.permille) { - cyl->gasmix.o2.permille = 210; - cyl->gasmix.he.permille = 0; - } - cyl->depth.mm = 1600 * 1000 / cyl->gasmix.o2.permille * 10 - 10000; + pressure_t modppO2; + modppO2.mbar = 1600; + cyl->depth = gas_mod(&cyl->gasmix, modppO2); changed = true; } break; @@ -368,11 +366,10 @@ void CylindersModel::remove(const QModelIndex &index) cylinder_t *cyl = ¤t->cylinder[index.row()]; if ((DivePlannerPointsModel::instance()->currentMode() != DivePlannerPointsModel::NOTHING && DivePlannerPointsModel::instance()->tankInUse(cyl->gasmix.o2.permille, cyl->gasmix.he.permille)) || - (DivePlannerPointsModel::instance()->currentMode() == DivePlannerPointsModel::NOTHING && cyl->used)) - { + (DivePlannerPointsModel::instance()->currentMode() == DivePlannerPointsModel::NOTHING && cyl->used)) { QMessageBox::warning(MainWindow::instance(), TITLE_OR_TEXT( - tr("Cylinder cannot be removed"), - tr("This gas in use. Only cylinders that are not used in the dive can be removed.")), + tr("Cylinder cannot be removed"), + tr("This gas in use. Only cylinders that are not used in the dive can be removed.")), QMessageBox::Ok); return; } @@ -1060,7 +1057,7 @@ static int nitrox_sort_value(struct dive *dive) QVariant DiveItem::data(int column, int role) const { QVariant retVal; - struct dive *dive = get_dive_by_diveid(diveId); + struct dive *dive = get_dive_by_uniq_id(diveId); switch (role) { case Qt::TextAlignmentRole: @@ -1203,11 +1200,11 @@ bool DiveItem::setData(const QModelIndex &index, const QVariant &value, int role int i; struct dive *d; - for_each_dive(i, d) { + for_each_dive (i, d) { if (d->number == v) return false; } - d = get_dive_by_diveid(diveId); + d = get_dive_by_uniq_id(diveId); d->number = value.toInt(); mark_divelist_changed(true); return true; @@ -1215,7 +1212,7 @@ bool DiveItem::setData(const QModelIndex &index, const QVariant &value, int role QString DiveItem::displayDate() const { - struct dive *dive = get_dive_by_diveid(diveId); + struct dive *dive = get_dive_by_uniq_id(diveId); return get_dive_date_string(dive->when); } @@ -1223,7 +1220,7 @@ QString DiveItem::displayDepth() const { QString fract, str; const int scale = 1000; - struct dive *dive = get_dive_by_diveid(diveId); + struct dive *dive = get_dive_by_uniq_id(diveId); if (get_units()->length == units::METERS) { fract = QString::number((unsigned)(dive->maxdepth.mm % scale) / 100); str = QString("%1.%2").arg((unsigned)(dive->maxdepth.mm / scale)).arg(fract, 1, QChar('0')); @@ -1237,7 +1234,7 @@ QString DiveItem::displayDepth() const QString DiveItem::displayDuration() const { int hrs, mins, secs; - struct dive *dive = get_dive_by_diveid(diveId); + struct dive *dive = get_dive_by_uniq_id(diveId); secs = dive->duration.seconds % 60; mins = dive->duration.seconds / 60; hrs = mins / 60; @@ -1255,7 +1252,7 @@ QString DiveItem::displayDuration() const QString DiveItem::displayTemperature() const { QString str; - struct dive *dive = get_dive_by_diveid(diveId); + struct dive *dive = get_dive_by_uniq_id(diveId); if (!dive->watertemp.mkelvin) return str; if (get_units()->temperature == units::CELSIUS) @@ -1268,7 +1265,7 @@ QString DiveItem::displayTemperature() const QString DiveItem::displaySac() const { QString str; - struct dive *dive = get_dive_by_diveid(diveId); + struct dive *dive = get_dive_by_uniq_id(diveId); if (get_units()->volume == units::LITER) str = QString::number(dive->sac / 1000.0, 'f', 1).append(tr(" l/min")); else @@ -1284,7 +1281,7 @@ QString DiveItem::displayWeight() const int DiveItem::weight() const { - struct dive *dive = get_dive_by_diveid(diveId); + struct dive *dive = get_dive_by_uniq_id(diveId); weight_t tw = { total_weight(dive) }; return tw.grams; } @@ -1904,7 +1901,7 @@ QVariant ProfilePrintModel::data(const QModelIndex &index, int role) const switch (role) { case Qt::DisplayRole: { - struct dive *dive = get_dive_by_diveid(diveId); + struct dive *dive = get_dive_by_uniq_id(diveId); struct DiveItem di; di.diveId = diveId; @@ -2060,7 +2057,7 @@ LanguageModel::LanguageModel(QObject *parent) : QAbstractListModel(parent) QSettings s; QDir d(getSubsurfaceDataPath("translations")); QStringList result = d.entryList(); - Q_FOREACH(const QString & s, result) { + Q_FOREACH (const QString &s, result) { if (s.startsWith("subsurface_") && s.endsWith(".qm")) { languages.push_back((s == "subsurface_source.qm") ? "English" : s); } diff --git a/qt-ui/preferences.cpp b/qt-ui/preferences.cpp index 47f8541db..768275d26 100644 --- a/qt-ui/preferences.cpp +++ b/qt-ui/preferences.cpp @@ -236,7 +236,7 @@ void PreferencesDialog::syncSettings() // Animation s.beginGroup("Animations"); - s.setValue("animation_speed",ui.velocitySlider->value()); + s.setValue("animation_speed", ui.velocitySlider->value()); s.endGroup(); loadSettings(); diff --git a/qt-ui/printlayout.cpp b/qt-ui/printlayout.cpp index c30ff9cd1..159b51822 100644 --- a/qt-ui/printlayout.cpp +++ b/qt-ui/printlayout.cpp @@ -98,7 +98,7 @@ int PrintLayout::estimateTotalDives() const { int total = 0, i = 0; struct dive *dive; - for_each_dive(i, dive) { + for_each_dive (i, dive) { if (!dive->selected && printOptions->print_selected) continue; total++; @@ -168,7 +168,7 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn) yOffsetTable = scaledH - tableH; // plot the dives at specific rows and columns on the page - for_each_dive(i, dive) { + for_each_dive (i, dive) { if (!dive->selected && printOptions->print_selected) continue; if (col == divesPerColumn) { @@ -183,7 +183,7 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn) // draw a profile painter.translate((scaledW + padW) * col, (scaledH + padH) * row + yOffsetProfile); - profile->plotDives(QList<struct dive*>() << dive); + profile->plotDives(QList<struct dive *>() << dive); profile->render(&painter, QRect(0, 0, scaledW, scaledH - tableH - padPT)); painter.setTransform(origTransform); @@ -202,7 +202,7 @@ void PrintLayout::printProfileDives(int divesPerRow, int divesPerColumn) profile->setFrameStyle(profileFrameStyle); profile->setPrintMode(false); profile->resize(originalSize); - profile->plotDives(QList<struct dive*>() << current_dive); + profile->plotDives(QList<struct dive *>() << current_dive); } /* we create a table that has a fixed height, but can stretch to fit certain width */ @@ -309,7 +309,7 @@ void PrintLayout::printTable() addTablePrintHeadingRow(&model, row); // add one heading row row++; progress = 0; - for_each_dive(i, dive) { + for_each_dive (i, dive) { if (!dive->selected && printOptions->print_selected) continue; addTablePrintDataRow(&model, row, dive); diff --git a/qt-ui/profile/animationfunctions.cpp b/qt-ui/profile/animationfunctions.cpp index 05e437cf0..bd08a22ee 100644 --- a/qt-ui/profile/animationfunctions.cpp +++ b/qt-ui/profile/animationfunctions.cpp @@ -4,8 +4,7 @@ #include <QPropertyAnimation> #include <QPointF> -namespace Animations -{ +namespace Animations { void hide(QObject *obj) { @@ -26,15 +25,14 @@ namespace Animations void moveTo(QObject *obj, qreal x, qreal y) { - if (prefs.animation != 0){ + if (prefs.animation != 0) { QPropertyAnimation *animation = new QPropertyAnimation(obj, "pos"); animation->setDuration(prefs.animation); animation->setStartValue(obj->property("pos").toPointF()); animation->setEndValue(QPointF(x, y)); animation->start(QAbstractAnimation::DeleteWhenStopped); - } - else{ - obj->setProperty("pos", QPointF(x,y)); + } else { + obj->setProperty("pos", QPointF(x, y)); } } diff --git a/qt-ui/profile/animationfunctions.h b/qt-ui/profile/animationfunctions.h index e0338393e..9269e6dd3 100644 --- a/qt-ui/profile/animationfunctions.h +++ b/qt-ui/profile/animationfunctions.h @@ -6,8 +6,7 @@ class QObject; -namespace Animations -{ +namespace Animations { void hide(QObject *obj); void moveTo(QObject *obj, qreal x, qreal y); void moveTo(QObject *obj, const QPointF &pos); diff --git a/qt-ui/profile/divecartesianaxis.cpp b/qt-ui/profile/divecartesianaxis.cpp index c1e93faa7..353f9880c 100644 --- a/qt-ui/profile/divecartesianaxis.cpp +++ b/qt-ui/profile/divecartesianaxis.cpp @@ -97,7 +97,7 @@ void DiveCartesianAxis::setTextVisible(bool arg1) return; } textVisibility = arg1; - Q_FOREACH(DiveTextItem * item, labels) { + Q_FOREACH (DiveTextItem *item, labels) { item->setVisible(textVisibility); } } @@ -108,7 +108,7 @@ void DiveCartesianAxis::setLinesVisible(bool arg1) return; } lineVisibility = arg1; - Q_FOREACH(DiveLineItem * item, lines) { + Q_FOREACH (DiveLineItem *item, lines) { item->setVisible(lineVisibility); } } @@ -161,8 +161,8 @@ void DiveCartesianAxis::updateTicks(color_indice_t color) for (int i = 0, count = labels.size(); i < count; i++, currValueText += interval) { qreal childPos = (orientation == TopToBottom || orientation == LeftToRight) ? - begin + i * stepSize : - begin - i * stepSize; + begin + i * stepSize : + begin - i * stepSize; labels[i]->setText(textForValue(currValueText)); if (orientation == LeftToRight || orientation == RightToLeft) { @@ -174,8 +174,8 @@ void DiveCartesianAxis::updateTicks(color_indice_t color) for (int i = 0, count = lines.size(); i < count; i++, currValueLine += interval) { qreal childPos = (orientation == TopToBottom || orientation == LeftToRight) ? - begin + i * stepSize : - begin - i * stepSize; + begin + i * stepSize : + begin - i * stepSize; if (orientation == LeftToRight || orientation == RightToLeft) { lines[i]->animateMoveTo(childPos, m.y1()); @@ -237,9 +237,9 @@ void DiveCartesianAxis::updateTicks(color_indice_t color) } } - Q_FOREACH(DiveTextItem * item, labels) + Q_FOREACH (DiveTextItem *item, labels) item->setVisible(textVisibility); - Q_FOREACH(DiveLineItem * item, lines) + Q_FOREACH (DiveLineItem *item, lines) item->setVisible(lineVisibility); } @@ -272,8 +272,8 @@ qreal DiveCartesianAxis::valueAt(const QPointF &p) const relativePosition -= pos(); // normalize p based on the axis' offset on screen double retValue = (orientation == LeftToRight || orientation == RightToLeft) ? - max * (relativePosition.x() - m.x1()) / (m.x2() - m.x1()) : - max * (relativePosition.y() - m.y1()) / (m.y2() - m.y1()); + max * (relativePosition.x() - m.x1()) / (m.x2() - m.x1()) : + max * (relativePosition.y() - m.y1()) / (m.y2() - m.y1()); return retValue; } @@ -289,8 +289,8 @@ qreal DiveCartesianAxis::posAtValue(qreal value) double realSize = orientation == LeftToRight || orientation == RightToLeft ? - m.x2() - m.x1() : - m.y2() - m.y1(); + m.x2() - m.x1() : + m.y2() - m.y1(); // Inverted axis, just invert the percentage. if (orientation == RightToLeft || orientation == BottomToTop) @@ -298,10 +298,10 @@ qreal DiveCartesianAxis::posAtValue(qreal value) double retValue = realSize * percent; double adjusted = - orientation == LeftToRight ? retValue + m.x1() + p.x() : - orientation == RightToLeft ? retValue + m.x1() + p.x() : - orientation == TopToBottom ? retValue + m.y1() + p.y() : - /* entation == BottomToTop */ retValue + m.y1() + p.y(); + orientation == LeftToRight ? retValue + m.x1() + p.x() : + orientation == RightToLeft ? retValue + m.x1() + p.x() : + orientation == TopToBottom ? retValue + m.y1() + p.y() : + /* entation == BottomToTop */ retValue + m.y1() + p.y(); return adjusted; } @@ -411,17 +411,17 @@ QString TemperatureAxis::textForValue(double value) PartialGasPressureAxis::PartialGasPressureAxis() { - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(preferencesChanged())); + connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); } void PartialGasPressureAxis::setModel(DivePlotDataModel *m) { model = m; - connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(preferencesChanged())); - preferencesChanged(); + connect(model, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(settingsChanged())); + settingsChanged(); } -void PartialGasPressureAxis::preferencesChanged() +void PartialGasPressureAxis::settingsChanged() { bool showPhe = prefs.pp_graphs.phe; bool showPn2 = prefs.pp_graphs.pn2; diff --git a/qt-ui/profile/divecartesianaxis.h b/qt-ui/profile/divecartesianaxis.h index e5b9b7b0e..34089e614 100644 --- a/qt-ui/profile/divecartesianaxis.h +++ b/qt-ui/profile/divecartesianaxis.h @@ -110,7 +110,7 @@ public: void setModel(DivePlotDataModel *model); public slots: - void preferencesChanged(); + void settingsChanged(); private: DivePlotDataModel *model; diff --git a/qt-ui/profile/diveplotdatamodel.cpp b/qt-ui/profile/diveplotdatamodel.cpp index 990564fbb..2fe636a4b 100644 --- a/qt-ui/profile/diveplotdatamodel.cpp +++ b/qt-ui/profile/diveplotdatamodel.cpp @@ -178,7 +178,7 @@ void DivePlotDataModel::emitDataChanged() void DivePlotDataModel::calculateDecompression() { - struct dive *d = get_dive_by_diveid(id()); + struct dive *d = get_dive_by_uniq_id(id()); struct divecomputer *dc = select_dc(d); init_decompression(d); calculate_deco_information(d, dc, &pInfo, false); diff --git a/qt-ui/profile/diveprofileitem.cpp b/qt-ui/profile/diveprofileitem.cpp index 1615be87f..2a6d5ac2f 100644 --- a/qt-ui/profile/diveprofileitem.cpp +++ b/qt-ui/profile/diveprofileitem.cpp @@ -18,10 +18,10 @@ AbstractProfilePolygonItem::AbstractProfilePolygonItem() : QObject(), QGraphicsPolygonItem(), hAxis(NULL), vAxis(NULL), dataModel(NULL), hDataColumn(-1), vDataColumn(-1) { - connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(preferencesChanged())); + connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); } -void AbstractProfilePolygonItem::preferencesChanged() +void AbstractProfilePolygonItem::settingsChanged() { } @@ -156,10 +156,8 @@ void DiveProfileItem::modelDataChanged(const QModelIndex &topLeft, const QModelI if (!entry->in_deco) { /* not in deco implies this is a safety stop, no ceiling */ p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(0))); - } else if (entry->stopdepth < entry->depth) { - p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(entry->stopdepth))); } else { - p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(entry->depth))); + p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(qMin(entry->stopdepth, entry->depth)))); } } setPolygon(p); @@ -194,7 +192,7 @@ void DiveProfileItem::modelDataChanged(const QModelIndex &topLeft, const QModelI } } -void DiveProfileItem::preferencesChanged() +void DiveProfileItem::settingsChanged() { //TODO: Only modelDataChanged() here if we need to rebuild the graph ( for instance, // if the prefs.dcceiling are enabled, but prefs.redceiling is disabled @@ -298,7 +296,7 @@ void DiveHeartrateItem::paint(QPainter *painter, const QStyleOptionGraphicsItem painter->drawPolyline(polygon()); } -void DiveHeartrateItem::preferencesChanged() +void DiveHeartrateItem::settingsChanged() { QSettings s; s.beginGroup("TecDetails"); @@ -427,7 +425,7 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo int last_pressure[MAX_CYLINDERS] = { 0, }; int last_time[MAX_CYLINDERS] = { 0, }; struct plot_data *entry; - struct dive *dive = get_dive_by_diveid(dataModel->id()); + struct dive *dive = get_dive_by_uniq_id(dataModel->id()); cyl = -1; for (int i = 0, count = dataModel->rowCount(); i < count; i++) { @@ -489,9 +487,9 @@ void DiveGasPressureItem::paint(QPainter *painter, const QStyleOptionGraphicsIte QPen pen; pen.setCosmetic(true); pen.setWidth(2); - struct dive *d = get_dive_by_diveid(dataModel->id()); + struct dive *d = get_dive_by_uniq_id(dataModel->id()); struct plot_data *entry = dataModel->data().entry; - Q_FOREACH(const QPolygonF & poly, polygons) { + Q_FOREACH (const QPolygonF &poly, polygons) { for (int i = 1, count = poly.count(); i < count; i++, entry++) { pen.setBrush(getSacColor(entry->sac, d->sac)); painter->setPen(pen); @@ -505,7 +503,7 @@ DiveCalculatedCeiling::DiveCalculatedCeiling() : is3mIncrement(false), gradientF gradientFactor->setY(0); gradientFactor->setBrush(getColor(PRESSURE_TEXT)); gradientFactor->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); - preferencesChanged(); + settingsChanged(); } void DiveCalculatedCeiling::modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) @@ -544,10 +542,10 @@ void DiveCalculatedCeiling::paint(QPainter *painter, const QStyleOptionGraphicsI DiveCalculatedTissue::DiveCalculatedTissue() { - preferencesChanged(); + settingsChanged(); } -void DiveCalculatedTissue::preferencesChanged() +void DiveCalculatedTissue::settingsChanged() { setVisible(prefs.calcalltissues && prefs.calcceiling); } @@ -562,11 +560,7 @@ void DiveReportedCeiling::modelDataChanged(const QModelIndex &topLeft, const QMo plot_data *entry = dataModel->data().entry; for (int i = 0, count = dataModel->rowCount(); i < count; i++, entry++) { if (entry->in_deco && entry->stopdepth) { - if (entry->stopdepth < entry->depth) { - p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(entry->stopdepth))); - } else { - p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(entry->depth))); - } + p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(qMin(entry->stopdepth, entry->depth)))); } else { p.append(QPointF(hAxis->posAtValue(entry->sec), vAxis->posAtValue(0))); } @@ -585,7 +579,7 @@ void DiveReportedCeiling::modelDataChanged(const QModelIndex &topLeft, const QMo setBrush(pat); } -void DiveCalculatedCeiling::preferencesChanged() +void DiveCalculatedCeiling::settingsChanged() { if (dataModel && is3mIncrement != prefs.calcceiling3m) { // recalculate that part. @@ -595,7 +589,7 @@ void DiveCalculatedCeiling::preferencesChanged() setVisible(prefs.calcceiling); } -void DiveReportedCeiling::preferencesChanged() +void DiveReportedCeiling::settingsChanged() { setVisible(prefs.dcceiling); } @@ -688,9 +682,8 @@ void PartialPressureGasItem::paint(QPainter *painter, const QStyleOptionGraphics QPolygonF poly; painter->setPen(QPen(alertColor, pWidth)); - Q_FOREACH(const QPolygonF & poly, alertPolygons) + Q_FOREACH (const QPolygonF &poly, alertPolygons) painter->drawPolyline(poly); - } void PartialPressureGasItem::setThreshouldSettingsKey(const QString &threshouldSettingsKey) @@ -702,7 +695,7 @@ PartialPressureGasItem::PartialPressureGasItem() { } -void PartialPressureGasItem::preferencesChanged() +void PartialPressureGasItem::settingsChanged() { QSettings s; s.beginGroup("TecDetails"); diff --git a/qt-ui/profile/diveprofileitem.h b/qt-ui/profile/diveprofileitem.h index c7fa59841..de0c6f0c9 100644 --- a/qt-ui/profile/diveprofileitem.h +++ b/qt-ui/profile/diveprofileitem.h @@ -46,7 +46,7 @@ public: } public slots: - virtual void preferencesChanged(); + virtual void settingsChanged(); virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); virtual void modelDataRemoved(const QModelIndex &parent, int from, int to); @@ -75,7 +75,7 @@ public: DiveProfileItem(); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void preferencesChanged(); + virtual void settingsChanged(); void plot_depth_sample(struct plot_data *entry, QFlags<Qt::AlignmentFlag> flags, const QColor &color); private: @@ -100,7 +100,7 @@ public: DiveHeartrateItem(); virtual void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); - virtual void preferencesChanged(); + virtual void settingsChanged(); void setVisibilitySettingsKey(const QString &setVisibilitySettingsKey); bool isVisible(); @@ -130,7 +130,7 @@ public: DiveCalculatedCeiling(); virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual void preferencesChanged(); + virtual void settingsChanged(); private: bool is3mIncrement; @@ -143,14 +143,14 @@ class DiveReportedCeiling : public AbstractProfilePolygonItem { public: virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - virtual void preferencesChanged(); + virtual void settingsChanged(); }; class DiveCalculatedTissue : public DiveCalculatedCeiling { Q_OBJECT public: DiveCalculatedTissue(); - virtual void preferencesChanged(); + virtual void settingsChanged(); }; class MeanDepthLine : public DiveLineItem { @@ -176,7 +176,7 @@ public: PartialPressureGasItem(); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); virtual void modelDataChanged(const QModelIndex &topLeft = QModelIndex(), const QModelIndex &bottomRight = QModelIndex()); - virtual void preferencesChanged(); + virtual void settingsChanged(); void setThreshouldSettingsKey(const QString &threshouldSettingsKey); void setVisibilitySettingsKey(const QString &setVisibilitySettingsKey); void setColors(const QColor &normalColor, const QColor &alertColor); diff --git a/qt-ui/profile/divetooltipitem.cpp b/qt-ui/profile/divetooltipitem.cpp index 0e68685b9..032daf6ee 100644 --- a/qt-ui/profile/divetooltipitem.cpp +++ b/qt-ui/profile/divetooltipitem.cpp @@ -1,5 +1,6 @@ #include "divetooltipitem.h" #include "divecartesianaxis.h" +#include "profilewidget2.h" #include "profile.h" #include "dive.h" #include "membuffer.h" @@ -21,7 +22,7 @@ void ToolTipItem::addToolTip(const QString &toolTip, const QIcon &icon) { QGraphicsPixmapItem *iconItem = 0; double yValue = title->boundingRect().height() + SPACING; - Q_FOREACH(ToolTip t, toolTips) { + Q_FOREACH (ToolTip t, toolTips) { yValue += t.second->boundingRect().height(); } if (!icon.isNull()) { @@ -39,7 +40,7 @@ void ToolTipItem::addToolTip(const QString &toolTip, const QIcon &icon) void ToolTipItem::clear() { - Q_FOREACH(ToolTip t, toolTips) { + Q_FOREACH (ToolTip t, toolTips) { delete t.first; delete t.second; } @@ -96,7 +97,7 @@ void ToolTipItem::expand() return; double width = 0, height = title->boundingRect().height() + SPACING; - Q_FOREACH(ToolTip t, toolTips) { + Q_FOREACH (ToolTip t, toolTips) { if (t.second->boundingRect().width() > width) width = t.second->boundingRect().width(); height += t.second->boundingRect().height(); @@ -180,6 +181,9 @@ void ToolTipItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { persistPos(); QGraphicsPathItem::mouseReleaseEvent(event); + Q_FOREACH (QGraphicsItem *item, oldSelection) { + item->setSelected(true); + } } void ToolTipItem::persistPos() @@ -226,8 +230,15 @@ void ToolTipItem::refresh(const QPointF &pos) free_buffer(&mb); QList<QGraphicsItem *> items = scene()->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder, scene()->views().first()->transform()); - Q_FOREACH(QGraphicsItem * item, items) { + Q_FOREACH (QGraphicsItem *item, items) { if (!item->toolTip().isEmpty()) addToolTip(item->toolTip()); } } + +void ToolTipItem::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + oldSelection = scene()->selectedItems(); + scene()->clearSelection(); + QGraphicsItem::mousePressEvent(event); +} diff --git a/qt-ui/profile/divetooltipitem.h b/qt-ui/profile/divetooltipitem.h index 1f84d0664..c22287b06 100644 --- a/qt-ui/profile/divetooltipitem.h +++ b/qt-ui/profile/divetooltipitem.h @@ -45,6 +45,7 @@ public: bool isExpanded() const; void persistPos(); void readPos(); + void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void setTimeAxis(DiveCartesianAxis *axis); void setPlotInfo(const plot_info &plot); @@ -64,6 +65,8 @@ private: DiveCartesianAxis *timeAxis; plot_info pInfo; int lastTime; + + QList<QGraphicsItem*> oldSelection; }; #endif // DIVETOOLTIPITEM_H diff --git a/qt-ui/profile/profilewidget2.cpp b/qt-ui/profile/profilewidget2.cpp index d2d01a384..2de64e71f 100644 --- a/qt-ui/profile/profilewidget2.cpp +++ b/qt-ui/profile/profilewidget2.cpp @@ -21,7 +21,6 @@ #include <QMenu> #include <QContextMenuEvent> #include <QDebug> -#include <QSettings> #include <QScrollBar> #include <QtCore/qmath.h> #include <QMessageBox> @@ -100,6 +99,23 @@ ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent), setEmptyState(); connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); + QAction *action = NULL; +#define ADD_ACTION(SHORTCUT, Slot) \ + action = new QAction(this); \ + action->setShortcut(SHORTCUT); \ + action->setShortcutContext(Qt::WindowShortcut); \ + addAction(action); \ + connect(action, SIGNAL(triggered(bool)), this, SLOT(Slot)); \ + actionsForKeys[SHORTCUT] = action; + + ADD_ACTION(Qt::Key_Escape, keyEscAction()); + ADD_ACTION(Qt::Key_Delete, keyDeleteAction()); + ADD_ACTION(Qt::Key_Up, keyUpAction()); + ADD_ACTION(Qt::Key_Down, keyDownAction()); + ADD_ACTION(Qt::Key_Left, keyLeftAction()); + ADD_ACTION(Qt::Key_Right, keyRightAction()); +#undef ADD_ACTION + #ifndef QT_NO_DEBUG QTableView *diveDepthTableView = new QTableView(); diveDepthTableView->setModel(dataModel); @@ -107,6 +123,9 @@ ProfileWidget2::ProfileWidget2(QWidget *parent) : QGraphicsView(parent), #endif } +#define SUBSURFACE_OBJ_DATA 1 +#define SUBSURFACE_OBJ_DC_TEXT 0x42 + void ProfileWidget2::addItemsToScene() { scene()->addItem(background); @@ -120,6 +139,11 @@ void ProfileWidget2::addItemsToScene() scene()->addItem(temperatureItem); scene()->addItem(gasPressureItem); scene()->addItem(meanDepth); + // I cannot seem to figure out if an object that I find with itemAt() on the scene + // is the object I am looking for - my guess is there's a simple way in Qt to do that + // but nothing I tried worked. + // so instead this adds a special magic key/value pair to the object to mark it + diveComputerText->setData(SUBSURFACE_OBJ_DATA, SUBSURFACE_OBJ_DC_TEXT); scene()->addItem(diveComputerText); scene()->addItem(diveCeiling); scene()->addItem(reportedCeiling); @@ -131,7 +155,7 @@ void ProfileWidget2::addItemsToScene() scene()->addItem(rulerItem); scene()->addItem(rulerItem->sourceNode()); scene()->addItem(rulerItem->destNode()); - Q_FOREACH(DiveCalculatedTissue * tissue, allTissues) { + Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) { scene()->addItem(tissue); } } @@ -196,7 +220,7 @@ void ProfileWidget2::setupItemOnScene() setupItem(temperatureItem, timeAxis, temperatureAxis, dataModel, DivePlotDataModel::TEMPERATURE, DivePlotDataModel::TIME, 1); setupItem(heartBeatItem, timeAxis, heartBeatAxis, dataModel, DivePlotDataModel::HEARTBEAT, DivePlotDataModel::TIME, 1); heartBeatItem->setVisibilitySettingsKey("hrgraph"); - heartBeatItem->preferencesChanged(); + heartBeatItem->settingsChanged(); setupItem(diveProfileItem, timeAxis, profileYAxis, dataModel, DivePlotDataModel::DEPTH, DivePlotDataModel::TIME, 0); #define CREATE_PP_GAS(ITEM, VERTICAL_COLUMN, COLOR, COLOR_ALERT, THRESHOULD_SETTINGS, VISIBILITY_SETTINGS) \ @@ -204,7 +228,7 @@ void ProfileWidget2::setupItemOnScene() ITEM->setThreshouldSettingsKey(THRESHOULD_SETTINGS); \ ITEM->setVisibilitySettingsKey(VISIBILITY_SETTINGS); \ ITEM->setColors(getColor(COLOR, isGrayscale), getColor(COLOR_ALERT, isGrayscale)); \ - ITEM->preferencesChanged(); \ + ITEM->settingsChanged(); \ ITEM->setZValue(99); CREATE_PP_GAS(pn2GasItem, PN2, PN2, PN2_ALERT, "pn2threshold", "pn2graph"); @@ -227,7 +251,7 @@ void ProfileWidget2::replot() { int diveId = dataModel->id(); dataModel->clear(); - plotDives(QList<dive *>() << get_dive_by_diveid(diveId)); + plotDives(QList<dive *>() << get_dive_by_uniq_id(diveId)); } void ProfileWidget2::setupItemSizes() @@ -336,6 +360,19 @@ void ProfileWidget2::plotDives(QList<dive *> dives) if (!d) return; + //TODO: This is a temporary hack to help me understand the Planner. + // It seems that each time the 'createTemporaryPlan' runs, a new + // dive is created, and thus, we can plot that. hm... + if (currentState == ADD) { + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + plannerModel->createTemporaryPlan(); + if (!plannerModel->getDiveplan().dp) { + plannerModel->deleteTemporaryPlan(); + return; + } + } + //END + int animSpeedBackup = -1; if (firstCall && MainWindow::instance()->filesFromCommandLine()) { animSpeedBackup = prefs.animation; @@ -352,12 +389,7 @@ void ProfileWidget2::plotDives(QList<dive *> dives) // reset some item visibility on printMode changes toolTipItem->setVisible(!printMode); - QSettings s; - s.beginGroup("TecDetails"); - const bool rulerVisible = s.value("rulergraph", false).toBool() && !printMode; - rulerItem->setVisible(rulerVisible); - rulerItem->sourceNode()->setVisible(rulerVisible); - rulerItem->destNode()->setVisible(rulerVisible); + rulerItem->setVisible(prefs.rulergraph && !printMode); // No need to do this again if we are already showing the same dive // computer of the same dive, so we check the unique id of the dive @@ -368,7 +400,8 @@ void ProfileWidget2::plotDives(QList<dive *> dives) if (d->id == dataModel->id() && dc_number == dataModel->dcShown()) return; - setProfileState(); + if (currentState == EMPTY) + setProfileState(); // next get the dive computer structure - if there are no samples // let's create a fake profile that's somewhat reasonable for the @@ -463,14 +496,24 @@ void ProfileWidget2::plotDives(QList<dive *> dives) event = event->next; } // Only set visible the events that should be visible - Q_FOREACH(DiveEventItem * event, eventItems) { + Q_FOREACH (DiveEventItem *event, eventItems) { event->setVisible(!event->shouldBeHidden()); // qDebug() << event->getEvent()->name << "@" << event->getEvent()->time.seconds << "is hidden:" << event->isHidden(); } - diveComputerText->setText(currentdc->model); + QString dcText = currentdc->model; + int nr; + if ((nr = number_of_computers(current_dive)) > 1) + dcText += tr(" (#%1 of %2)").arg(dc_number + 1).arg(nr); + diveComputerText->setText(dcText); if (MainWindow::instance()->filesFromCommandLine() && animSpeedBackup != -1) { prefs.animation = animSpeedBackup; } + + if (currentState == ADD) { // TODO: figure a way to move this from here. + repositionDiveHandlers(); + DivePlannerPointsModel *model = DivePlannerPointsModel::instance(); + model->deleteTemporaryPlan(); + } } void ProfileWidget2::settingsChanged() @@ -492,16 +535,6 @@ void ProfileWidget2::settingsChanged() needReplot = true; } - if (currentState == PROFILE) { - rulerItem->setVisible(prefs.rulergraph); - rulerItem->destNode()->setVisible(prefs.rulergraph); - rulerItem->sourceNode()->setVisible(prefs.rulergraph); - needReplot = true; - } else { - rulerItem->setVisible(false); - rulerItem->destNode()->setVisible(false); - rulerItem->sourceNode()->setVisible(false); - } if (needReplot) replot(); } @@ -543,6 +576,30 @@ void ProfileWidget2::wheelEvent(QWheelEvent *event) toolTipItem->setPos(mapToScene(toolTipPos)); } +void ProfileWidget2::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (currentState == PLAN || currentState == ADD) { + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + QPointF mappedPos = mapToScene(event->pos()); + if (isPointOutOfBoundaries(mappedPos)) + return; + + int minutes = rint(timeAxis->valueAt(mappedPos) / 60); + int milimeters = rint(profileYAxis->valueAt(mappedPos) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); + plannerModel->addStop(milimeters, minutes * 60, -1, 0, 0, true); + } +} + +bool ProfileWidget2::isPointOutOfBoundaries(const QPointF &point) const +{ + double xpos = timeAxis->valueAt(point); + double ypos = profileYAxis->valueAt(point); + return (xpos > timeAxis->maximum() || + xpos < timeAxis->minimum() || + ypos > profileYAxis->maximum() || + ypos < profileYAxis->minimum()); +} + void ProfileWidget2::scrollViewTo(const QPoint &pos) { /* since we cannot use translate() directly on the scene we hack on @@ -585,6 +642,8 @@ void ProfileWidget2::setEmptyState() if (currentState == EMPTY) return; + disconnectTemporaryConnections(); + setBackgroundBrush(getColor(::BACKGROUND, isGrayscale)); dataModel->clear(); currentState = EMPTY; MainWindow::instance()->setToolButtonsEnabled(false); @@ -604,15 +663,13 @@ void ProfileWidget2::setEmptyState() diveCeiling->setVisible(false); reportedCeiling->setVisible(false); rulerItem->setVisible(false); - rulerItem->destNode()->setVisible(false); - rulerItem->sourceNode()->setVisible(false); pn2GasItem->setVisible(false); po2GasItem->setVisible(false); pheGasItem->setVisible(false); - Q_FOREACH(DiveCalculatedTissue * tissue, allTissues) { + Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) { tissue->setVisible(false); } - Q_FOREACH(DiveEventItem * event, eventItems) { + Q_FOREACH (DiveEventItem *event, eventItems) { event->setVisible(false); } } @@ -623,6 +680,10 @@ void ProfileWidget2::setProfileState() if (currentState == PROFILE) return; + disconnectTemporaryConnections(); + //TODO: Move the DC handling to another method. + MainWindow::instance()->enableDcShortcuts(); + currentState = PROFILE; MainWindow::instance()->setToolButtonsEnabled(true); toolTipItem->readPos(); @@ -670,16 +731,50 @@ void ProfileWidget2::setProfileState() reportedCeiling->setVisible(prefs.dcceiling); if (prefs.calcalltissues) { - Q_FOREACH(DiveCalculatedTissue * tissue, allTissues) { + Q_FOREACH (DiveCalculatedTissue *tissue, allTissues) { tissue->setVisible(true); } } - QSettings s; - s.beginGroup("TecDetails"); - bool rulerVisible = s.value("rulergraph", false).toBool(); - rulerItem->setVisible(rulerVisible); - rulerItem->destNode()->setVisible(rulerVisible); - rulerItem->sourceNode()->setVisible(rulerVisible); + rulerItem->setVisible(prefs.rulergraph); +} + +void ProfileWidget2::setAddState() +{ + if (currentState == ADD) + return; + + setProfileState(); + disconnectTemporaryConnections(); + //TODO: Move this method to another place, shouldn't be on mainwindow. + MainWindow::instance()->disableDcShortcuts(); + actionsForKeys[Qt::Key_Left]->setShortcut(Qt::Key_Left); + actionsForKeys[Qt::Key_Right]->setShortcut(Qt::Key_Right); + actionsForKeys[Qt::Key_Up]->setShortcut(Qt::Key_Up); + actionsForKeys[Qt::Key_Down]->setShortcut(Qt::Key_Down); + actionsForKeys[Qt::Key_Escape]->setShortcut(Qt::Key_Escape); + actionsForKeys[Qt::Key_Delete]->setShortcut(Qt::Key_Delete); + + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + connect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(replot())); + connect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(replot())); + connect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + this, SLOT(pointInserted(const QModelIndex &, int, int))); + connect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + this, SLOT(pointsRemoved(const QModelIndex &, int, int))); + /* show the same stuff that the profile shows. */ + currentState = ADD; /* enable the add state. */ + setBackgroundBrush(QColor(Qt::blue).light()); +} + +void ProfileWidget2::setPlanState() +{ + if (currentState == PLAN) + return; + setProfileState(); + disconnectTemporaryConnections(); + /* show the same stuff that the profile shows. */ + currentState = PLAN; /* enable the add state. */ + setBackgroundBrush(QColor(Qt::green).light()); } extern struct ev_select *ev_namelist; @@ -688,9 +783,36 @@ extern int evn_used; void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) { - if (selected_dive == -1) + if (currentState == ADD || currentState == PLAN) { + QGraphicsView::contextMenuEvent(event); return; + } QMenu m; + bool isDCName = false; + if (selected_dive == -1) + return; + // figure out if we are ontop of the dive computer name in the profile + QGraphicsItem *sceneItem = itemAt(mapFromGlobal(event->globalPos())); + if (sceneItem) { + QGraphicsItem *parentItem = sceneItem; + while (parentItem) { + if (parentItem->data(SUBSURFACE_OBJ_DATA) == SUBSURFACE_OBJ_DC_TEXT) { + isDCName = true; + break; + } + parentItem = parentItem->parentItem(); + } + if (isDCName) { + if (dc_number == 0) + return; + // create menu to show when right clicking on dive computer name + m.addAction(tr("Make first divecomputer"), this, SLOT(makeFirstDC())); + m.exec(event->globalPos()); + // don't show the regular profile context menu + return; + } + } + // create the profile context menu QMenu *gasChange = m.addMenu(tr("Add Gas Change")); GasSelectionModel *model = GasSelectionModel::instance(); model->repopulate(); @@ -704,7 +826,6 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) } QAction *action = m.addAction(tr("Add Bookmark"), this, SLOT(addBookmark())); action->setData(event->globalPos()); - QGraphicsItem *sceneItem = itemAt(mapFromGlobal(event->globalPos())); if (DiveEventItem *item = dynamic_cast<DiveEventItem *>(sceneItem)) { action = new QAction(&m); action->setText(tr("Remove Event")); @@ -738,6 +859,18 @@ void ProfileWidget2::contextMenuEvent(QContextMenuEvent *event) m.exec(event->globalPos()); } +void ProfileWidget2::makeFirstDC() +{ + make_first_dc(); + mark_divelist_changed(true); + // this is now the first DC, so we need to redraw the profile and refresh the dive list + // (and no, it's not just enough to rewrite the text - the first DC is special so values in the + // dive list may change). + // As a side benefit, this returns focus to the dive list. + dc_number = 0; + MainWindow::instance()->refreshDisplay(); +} + void ProfileWidget2::hideEvents() { QAction *action = qobject_cast<QAction *>(sender()); @@ -749,14 +882,18 @@ void ProfileWidget2::hideEvents() QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { if (event->name) { for (int i = 0; i < evn_used; i++) { - if (!strcmp(event->name, ev_namelist[i].ev_name)) { + if (same_string(event->name, ev_namelist[i].ev_name)) { ev_namelist[i].plot_ev = false; break; } } + Q_FOREACH (DiveEventItem *evItem, eventItems) { + if (same_string(evItem->getEvent()->name, event->name)) + evItem->hide(); + } + } else { + item->hide(); } - item->hide(); - replot(); } } @@ -765,7 +902,8 @@ void ProfileWidget2::unhideEvents() for (int i = 0; i < evn_used; i++) { ev_namelist[i].plot_ev = true; } - replot(); + Q_FOREACH (DiveEventItem *item, eventItems) + item->show(); } void ProfileWidget2::removeEvent() @@ -775,16 +913,10 @@ void ProfileWidget2::removeEvent() struct event *event = item->getEvent(); if (QMessageBox::question(MainWindow::instance(), TITLE_OR_TEXT( - tr("Remove the selected event?"), - tr("%1 @ %2:%3").arg(event->name).arg(event->time.seconds / 60).arg(event->time.seconds % 60, 2, 10, QChar('0'))), + tr("Remove the selected event?"), + tr("%1 @ %2:%3").arg(event->name).arg(event->time.seconds / 60).arg(event->time.seconds % 60, 2, 10, QChar('0'))), QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) { - struct event **ep = ¤t_dc->events; - while (ep && *ep != event) - ep = &(*ep)->next; - if (ep) { - *ep = event->next; - free(event); - } + remove_event(event); mark_divelist_changed(true); replot(); } @@ -808,7 +940,7 @@ void ProfileWidget2::changeGas() int diveId = dataModel->id(); int o2, he; int seconds = timeAxis->valueAt(scenePos); - struct dive *d = get_dive_by_diveid(diveId); + struct dive *d = get_dive_by_uniq_id(diveId); validate_gas(gas.toUtf8().constData(), &o2, &he); add_gas_switch_event(d, get_dive_dc(d, diveComputer), seconds, get_gasidx(d, o2, he)); @@ -846,3 +978,248 @@ void ProfileWidget2::editName() } replot(); } + +void ProfileWidget2::disconnectTemporaryConnections() +{ + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + disconnect(plannerModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(replot())); + disconnect(plannerModel, SIGNAL(cylinderModelEdited()), this, SLOT(replot())); + + disconnect(plannerModel, SIGNAL(rowsInserted(const QModelIndex &, int, int)), + this, SLOT(pointInserted(const QModelIndex &, int, int))); + disconnect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + this, SLOT(pointsRemoved(const QModelIndex &, int, int))); + + + Q_FOREACH (QAction *action, actionsForKeys.values()) { + action->setShortcut(QKeySequence()); + } +} + +void ProfileWidget2::pointInserted(const QModelIndex &parent, int start, int end) +{ + DiveHandler *item = new DiveHandler(); + scene()->addItem(item); + handles << item; + + connect(item, SIGNAL(moved()), this, SLOT(recreatePlannedDive())); + QGraphicsSimpleTextItem *gasChooseBtn = new QGraphicsSimpleTextItem(); + scene()->addItem(gasChooseBtn); + gasChooseBtn->setZValue(10); + gasChooseBtn->setFlag(QGraphicsItem::ItemIgnoresTransformations); + gases << gasChooseBtn; + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + if (plannerModel->recalcQ()) + replot(); +} + +void ProfileWidget2::pointsRemoved(const QModelIndex &, int start, int end) +{ // start and end are inclusive. + int num = (end - start) + 1; + for (int i = num; i != 0; i--) { + delete handles.back(); + handles.pop_back(); + delete gases.back(); + gases.pop_back(); + } + scene()->clearSelection(); + replot(); +} + +void ProfileWidget2::repositionDiveHandlers() +{ + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + // Re-position the user generated dive handlers + int last = 0; + for (int i = 0; i < plannerModel->rowCount(); i++) { + struct divedatapoint datapoint = plannerModel->at(i); + if (datapoint.time == 0) // those are the magic entries for tanks + continue; + DiveHandler *h = handles.at(i); + h->setPos(timeAxis->posAtValue(datapoint.time), profileYAxis->posAtValue(datapoint.depth)); + QPointF p1 = (last == i) ? QPointF(timeAxis->posAtValue(0), profileYAxis->posAtValue(0)) : handles[last]->pos(); + QPointF p2 = handles[i]->pos(); + QLineF line(p1, p2); + QPointF pos = line.pointAt(0.5); + gases[i]->setPos(pos); + gases[i]->setText(dpGasToStr(plannerModel->at(i))); + last = i; + } +} + +int ProfileWidget2::fixHandlerIndex(DiveHandler *activeHandler) +{ + int index = handles.indexOf(activeHandler); + if (index > 0 && index < handles.count() - 1) { + DiveHandler *before = handles[index - 1]; + if (before->pos().x() > activeHandler->pos().x()) { + handles.swap(index, index - 1); + return index - 1; + } + DiveHandler *after = handles[index + 1]; + if (after->pos().x() < activeHandler->pos().x()) { + handles.swap(index, index + 1); + return index + 1; + } + } + return index; +} + +void ProfileWidget2::recreatePlannedDive() +{ + DiveHandler *activeHandler = qobject_cast<DiveHandler *>(sender()); + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + int index = fixHandlerIndex(activeHandler); + int mintime = 0, maxtime = (timeAxis->maximum() + 10) * 60; + if (index > 0) + mintime = plannerModel->at(index - 1).time; + if (index < plannerModel->size() - 1) + maxtime = plannerModel->at(index + 1).time; + + int minutes = rint(timeAxis->valueAt(activeHandler->pos()) / 60); + if (minutes * 60 <= mintime || minutes * 60 >= maxtime) + return; + + divedatapoint data = plannerModel->at(index); + data.depth = rint(profileYAxis->valueAt(activeHandler->pos()) / M_OR_FT(1, 1)) * M_OR_FT(1, 1); + data.time = rint(timeAxis->valueAt(activeHandler->pos())); + + plannerModel->editStop(index, data); +} + +void ProfileWidget2::keyDownAction() +{ + if (currentState != ADD && currentState != PLAN) + return; + + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { + if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { + int row = handles.indexOf(handler); + divedatapoint dp = plannerModel->at(row); + if (dp.depth >= profileYAxis->maximum()) + continue; + + dp.depth += M_OR_FT(1, 5); + plannerModel->editStop(row, dp); + } + } +} + +void ProfileWidget2::keyUpAction() +{ + if (currentState != ADD && currentState != PLAN) + return; + + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { + if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { + int row = handles.indexOf(handler); + divedatapoint dp = plannerModel->at(row); + + if (dp.depth <= 0) + continue; + + dp.depth -= M_OR_FT(1, 5); + plannerModel->editStop(row, dp); + } + } +} + +void ProfileWidget2::keyLeftAction() +{ + if (currentState != ADD && currentState != PLAN) + return; + + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { + if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { + int row = handles.indexOf(handler); + divedatapoint dp = plannerModel->at(row); + + if (dp.time / 60 <= 0) + continue; + + // don't overlap positions. + // maybe this is a good place for a 'goto'? + double xpos = timeAxis->posAtValue((dp.time - 60) / 60); + bool nextStep = false; + Q_FOREACH (DiveHandler *h, handles) { + if (IS_FP_SAME(h->pos().x(), xpos)) { + nextStep = true; + break; + } + } + if (nextStep) + continue; + + dp.time -= 60; + plannerModel->editStop(row, dp); + } + } +} + +void ProfileWidget2::keyRightAction() +{ + if (currentState != ADD && currentState != PLAN) + return; + + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { + if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { + int row = handles.indexOf(handler); + divedatapoint dp = plannerModel->at(row); + if (dp.time / 60 >= timeAxis->maximum()) + continue; + + // don't overlap positions. + // maybe this is a good place for a 'goto'? + double xpos = timeAxis->posAtValue((dp.time + 60) / 60); + bool nextStep = false; + Q_FOREACH (DiveHandler *h, handles) { + if (IS_FP_SAME(h->pos().x(), xpos)) { + nextStep = true; + break; + } + } + if (nextStep) + continue; + + dp.time += 60; + plannerModel->editStop(row, dp); + } + } +} + +void ProfileWidget2::keyDeleteAction() +{ + if (currentState != ADD && currentState != PLAN) + return; + + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + int selCount = scene()->selectedItems().count(); + if (selCount) { + QVector<int> selectedIndexes; + Q_FOREACH (QGraphicsItem *i, scene()->selectedItems()) { + if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler *>(i)) { + selectedIndexes.push_back(handles.indexOf(handler)); + } + } + plannerModel->removeSelectedPoints(selectedIndexes); + } +} + +void ProfileWidget2::keyEscAction() +{ + if (currentState != ADD && currentState != PLAN) + return; + + if (scene()->selectedItems().count()) { + scene()->clearSelection(); + return; + } + + DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance(); + if (plannerModel->isPlanner()) + plannerModel->cancelPlan(); +} diff --git a/qt-ui/profile/profilewidget2.h b/qt-ui/profile/profilewidget2.h index d00cb26c1..3c3d86d01 100644 --- a/qt-ui/profile/profilewidget2.h +++ b/qt-ui/profile/profilewidget2.h @@ -40,6 +40,9 @@ class DiveCalculatedTissue; class PartialPressureGasItem; class PartialGasPressureAxis; class AbstractProfilePolygonItem; +class DiveHandler; +class QGraphicsSimpleTextItem; +class QModelIndex; class ProfileWidget2 : public QGraphicsView { Q_OBJECT @@ -64,28 +67,47 @@ public: ProfileWidget2(QWidget *parent = 0); void plotDives(QList<dive *> dives); - void replot(); virtual bool eventFilter(QObject *, QEvent *); void setupItem(AbstractProfilePolygonItem *item, DiveCartesianAxis *hAxis, DiveCartesianAxis *vAxis, DivePlotDataModel *model, int vData, int hData, int zValue); void setPrintMode(bool mode, bool grayscale = false); + bool isPointOutOfBoundaries(const QPointF &point) const; + State currentState; public slots: // Necessary to call from QAction's signals. void settingsChanged(); void setEmptyState(); void setProfileState(); + void setPlanState(); + void setAddState(); void changeGas(); void addBookmark(); void hideEvents(); void unhideEvents(); void removeEvent(); void editName(); + void makeFirstDC(); + void pointInserted(const QModelIndex &parent, int start, int end); + void pointsRemoved(const QModelIndex &, int start, int end); + void replot(); + + /* this is called for every move on the handlers. maybe we can speed up this a bit? */ + void recreatePlannedDive(); + + /* key press handlers */ + void keyEscAction(); + void keyDeleteAction(); + void keyUpAction(); + void keyDownAction(); + void keyLeftAction(); + void keyRightAction(); protected: virtual void resizeEvent(QResizeEvent *event); virtual void wheelEvent(QWheelEvent *event); virtual void mouseMoveEvent(QMouseEvent *event); virtual void contextMenuEvent(QContextMenuEvent *event); + virtual void mouseDoubleClickEvent(QMouseEvent *event); private: /*methods*/ void fixBackgroundPos(); @@ -94,10 +116,10 @@ private: /*methods*/ void setupItemSizes(); void addItemsToScene(); void setupItemOnScene(); + void disconnectTemporaryConnections(); private: DivePlotDataModel *dataModel; - State currentState; int zoomLevel; qreal zoomFactor; DivePixmapItem *background; @@ -130,6 +152,14 @@ private: RulerItem2 *rulerItem; bool isGrayscale; bool printMode; + + //specifics for ADD and PLAN + QList<DiveHandler *> handles; + QList<QGraphicsSimpleTextItem *> gases; + void repositionDiveHandlers(); + int fixHandlerIndex(DiveHandler *activeHandler); + friend class DiveHandler; + QHash<Qt::Key, QAction *> actionsForKeys; }; #endif // PROFILEWIDGET2_H diff --git a/qt-ui/profile/ruleritem.cpp b/qt-ui/profile/ruleritem.cpp index 768d912e9..0f2a24a80 100644 --- a/qt-ui/profile/ruleritem.cpp +++ b/qt-ui/profile/ruleritem.cpp @@ -1,5 +1,7 @@ #include "ruleritem.h" #include "divetextitem.h" +#include "profilewidget2.h" +#include "../preferences.h" #include <QFont> #include <QFontMetrics> @@ -24,7 +26,7 @@ RulerNodeItem2::RulerNodeItem2() : entry(NULL), ruler(NULL) setFlag(ItemIgnoresTransformations); } -void RulerNodeItem2::setPlotInfo(plot_info& info) +void RulerNodeItem2::setPlotInfo(plot_info &info) { pInfo = info; entry = pInfo.entry; @@ -79,6 +81,15 @@ RulerItem2::RulerItem2() : source(new RulerNodeItem2()), textItemBack->setPen(QColor(Qt::white)); textItemBack->setFlag(QGraphicsItem::ItemIgnoresTransformations); setPen(QPen(QColor(Qt::black), 0.0)); + connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); +} + +void RulerItem2::settingsChanged() +{ + ProfileWidget2 *profWidget = NULL; + if (scene() && scene()->views().count()) + profWidget = qobject_cast<ProfileWidget2 *>(scene()->views().first()); + setVisible(profWidget->currentState == ProfileWidget2::PROFILE ? prefs.rulergraph : false); } void RulerItem2::recalculate() @@ -157,3 +168,10 @@ void RulerItem2::setAxis(DiveCartesianAxis *time, DiveCartesianAxis *depth) source->timeAxis = time; recalculate(); } + +void RulerItem2::setVisible(bool visible) +{ + QGraphicsLineItem::setVisible(visible); + source->setVisible(visible); + dest->setVisible(visible); +} diff --git a/qt-ui/profile/ruleritem.h b/qt-ui/profile/ruleritem.h index 7bfc63eee..3eda33225 100644 --- a/qt-ui/profile/ruleritem.h +++ b/qt-ui/profile/ruleritem.h @@ -17,7 +17,7 @@ class RulerNodeItem2 : public QObject, public QGraphicsEllipseItem { public: explicit RulerNodeItem2(); void setRuler(RulerItem2 *r); - void setPlotInfo(struct plot_info& info); + void setPlotInfo(struct plot_info &info); void recalculate(); protected: @@ -31,7 +31,8 @@ private: DiveCartesianAxis *depthAxis; }; -class RulerItem2 : public QGraphicsLineItem { +class RulerItem2 : public QObject, public QGraphicsLineItem { + Q_OBJECT public: explicit RulerItem2(); void recalculate(); @@ -40,6 +41,11 @@ public: RulerNodeItem2 *sourceNode() const; RulerNodeItem2 *destNode() const; void setAxis(DiveCartesianAxis *time, DiveCartesianAxis *depth); + void setVisible(bool visible); + +public +slots: + void settingsChanged(); private: struct plot_info pInfo; diff --git a/qt-ui/simplewidgets.cpp b/qt-ui/simplewidgets.cpp index 8932baf15..99e0ba362 100644 --- a/qt-ui/simplewidgets.cpp +++ b/qt-ui/simplewidgets.cpp @@ -16,8 +16,9 @@ #include <QDateTime> #include <QShortcut> #include "exif.h" -#include "../dive.h" -#include "../file.h" +#include "dive.h" +#include "file.h" +#include "display.h" #include "mainwindow.h" #include "helpers.h" @@ -117,15 +118,24 @@ RenumberDialog *RenumberDialog::instance() return self; } +void RenumberDialog::renumberOnlySelected(bool selected) +{ + if (selected && amount_selected == 1) + ui.groupBox->setTitle(tr("New number")); + else + ui.groupBox->setTitle(tr("New starting number")); + selectedOnly = selected; +} + void RenumberDialog::buttonClicked(QAbstractButton *button) { if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) { qDebug() << "Renumbering."; - renumber_dives(ui.spinBox->value()); + renumber_dives(ui.spinBox->value(), selectedOnly); } } -RenumberDialog::RenumberDialog(QWidget *parent) : QDialog(parent) +RenumberDialog::RenumberDialog(QWidget *parent) : QDialog(parent), selectedOnly(false) { ui.setupUi(this); connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton *)), this, SLOT(buttonClicked(QAbstractButton *))); @@ -161,10 +171,10 @@ void ShiftTimesDialog::buttonClicked(QAbstractButton *button) } } -void ShiftTimesDialog::showEvent(QShowEvent * event) +void ShiftTimesDialog::showEvent(QShowEvent *event) { ui.timeEdit->setTime(QTime(0, 0, 0, 0)); - when = get_times();//get time of first selected dive + when = get_times(); //get time of first selected dive ui.currentTime->setText(get_dive_date_string(when)); ui.shiftedTime->setText(get_dive_date_string(when)); } @@ -177,7 +187,7 @@ void ShiftTimesDialog::changeTime() if (ui.backwards->isChecked()) amount *= -1; - ui.shiftedTime->setText (get_dive_date_string(amount+when)); + ui.shiftedTime->setText(get_dive_date_string(amount + when)); } ShiftTimesDialog::ShiftTimesDialog(QWidget *parent) : QDialog(parent) diff --git a/qt-ui/simplewidgets.h b/qt-ui/simplewidgets.h index d43d2bbcc..cecb52815 100644 --- a/qt-ui/simplewidgets.h +++ b/qt-ui/simplewidgets.h @@ -40,6 +40,7 @@ class RenumberDialog : public QDialog { Q_OBJECT public: static RenumberDialog *instance(); + void renumberOnlySelected(bool selected = true); private slots: void buttonClicked(QAbstractButton *button); @@ -47,17 +48,18 @@ slots: private: explicit RenumberDialog(QWidget *parent); Ui::RenumberDialog ui; + bool selectedOnly; }; class ShiftTimesDialog : public QDialog { Q_OBJECT public: static ShiftTimesDialog *instance(); - void showEvent ( QShowEvent * event ); + void showEvent(QShowEvent *event); private slots: void buttonClicked(QAbstractButton *button); - void changeTime (); + void changeTime(); private: explicit ShiftTimesDialog(QWidget *parent); diff --git a/qt-ui/subsurfacewebservices.cpp b/qt-ui/subsurfacewebservices.cpp index 5170b3a40..c430deec6 100644 --- a/qt-ui/subsurfacewebservices.cpp +++ b/qt-ui/subsurfacewebservices.cpp @@ -49,7 +49,7 @@ static bool merge_locations_into_dives(void) sort_table(&gps_location_table); - for_each_gps_location(i, gpsfix) { + for_each_gps_location (i, gpsfix) { if (is_automatic_fix(gpsfix)) { dive = find_dive_including(gpsfix->when); if (dive && !dive_has_gps_location(dive)) { @@ -133,7 +133,9 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, } /* walk the dive list in chronological order */ - for (int i = 0; i < dive_table.nr; i++) { + int i; + struct dive *dive; + for_each_dive (i, dive) { FILE *f; char filename[PATH_MAX]; int streamsize; @@ -145,9 +147,6 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, * Get the i'th dive in XML format so we can process it. * We need to save to a file before we can reload it back into memory... */ - struct dive *dive = get_dive(i); - if (!dive) - continue; if (selected && !dive->selected) continue; f = tmpfile(); @@ -527,8 +526,8 @@ static DiveListResult parseDiveLogsDeDiveList(const QByteArray &xmlData) if (reader.readNextStartElement() && reader.name() != "DiveDateReader") { result.errorCondition = invalidXmlError; result.errorDetails = - DivelogsDeWebServices::tr("Expected XML tag 'DiveDateReader', got instead '%1") - .arg(reader.name().toString()); + DivelogsDeWebServices::tr("Expected XML tag 'DiveDateReader', got instead '%1") + .arg(reader.name().toString()); goto out; } @@ -581,8 +580,8 @@ out: // if there was an XML error, overwrite the result or other error conditions result.errorCondition = invalidXmlError; result.errorDetails = DivelogsDeWebServices::tr("Malformed XML response. Line %1: %2") - .arg(reader.lineNumber()) - .arg(reader.errorString()); + .arg(reader.lineNumber()) + .arg(reader.errorString()); } return result; } @@ -602,11 +601,11 @@ void DivelogsDeWebServices::downloadDives() exec(); } -void DivelogsDeWebServices::prepareDivesForUpload() +void DivelogsDeWebServices::prepareDivesForUpload(bool selected) { /* generate a random filename and create/open that file with zip_open */ QString filename = QDir::tempPath() + "/import-" + QString::number(qrand() % 99999999) + ".dld"; - if (prepare_dives_for_divelogs(filename, true)) { + if (prepare_dives_for_divelogs(filename, selected)) { QFile f(filename); if (f.open(QIODevice::ReadOnly)) { uploadDives((QIODevice *)&f); diff --git a/qt-ui/subsurfacewebservices.h b/qt-ui/subsurfacewebservices.h index 4419b1c6b..a9a67de46 100644 --- a/qt-ui/subsurfacewebservices.h +++ b/qt-ui/subsurfacewebservices.h @@ -71,7 +71,7 @@ class DivelogsDeWebServices : public WebServices { public: static DivelogsDeWebServices *instance(); void downloadDives(); - void prepareDivesForUpload(); + void prepareDivesForUpload(bool selected); private slots: diff --git a/qt-ui/tagwidget.cpp b/qt-ui/tagwidget.cpp index dfeeac537..8c45dceec 100644 --- a/qt-ui/tagwidget.cpp +++ b/qt-ui/tagwidget.cpp @@ -4,8 +4,9 @@ #include <QAbstractItemView> #include <QSettings> #include <QFont> +#include "mainwindow.h" -TagWidget::TagWidget(QWidget *parent) : GroupedLineEdit(parent), m_completer(NULL) +TagWidget::TagWidget(QWidget *parent) : GroupedLineEdit(parent), m_completer(NULL), lastFinishedTag(false) { connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(reparse())); connect(this, SIGNAL(textChanged()), this, SLOT(reparse())); @@ -137,13 +138,13 @@ void TagWidget::reparse() } } -void TagWidget::completionSelected(const QString& completion) +void TagWidget::completionSelected(const QString &completion) { completionHighlighted(completion); emit textChanged(); } -void TagWidget::completionHighlighted(const QString& completion) +void TagWidget::completionHighlighted(const QString &completion) { QPair<int, int> pos = getCursorTagPosition(); setText(text().remove(pos.first, pos.second - pos.first).insert(pos.first, completion)); @@ -157,7 +158,7 @@ void TagWidget::setCursorPosition(int position) blockSignals(false); } -void TagWidget::setText(const QString& text) +void TagWidget::setText(const QString &text) { blockSignals(true); GroupedLineEdit::setText(text); @@ -176,6 +177,7 @@ void TagWidget::keyPressEvent(QKeyEvent *e) { QPair<int, int> pos; QAbstractItemView *popup; + bool finishedTag = false; switch (e->key()) { case Qt::Key_Escape: pos = getCursorTagPosition(); @@ -183,7 +185,7 @@ void TagWidget::keyPressEvent(QKeyEvent *e) setText(text().remove(pos.first, pos.second - pos.first)); setCursorPosition(pos.first); } - popup= m_completer->popup(); + popup = m_completer->popup(); if (popup) popup->hide(); return; @@ -199,13 +201,17 @@ void TagWidget::keyPressEvent(QKeyEvent *e) if (popup) popup->hide(); } + finishedTag = true; } - if (e->key() == Qt::Key_Tab || e->key() == Qt::Key_Return) { // let's pretend this is a comma instead + if (e->key() == Qt::Key_Tab && lastFinishedTag) { // if we already end in comma, go to next/prev field + MainWindow::instance()->information()->nextInputField(e); // by sending the key event to the MainTab widget + } else if (e->key() == Qt::Key_Tab || e->key() == Qt::Key_Return) { // otherwise let's pretend this is a comma instead QKeyEvent fakeEvent(e->type(), Qt::Key_Comma, e->modifiers(), QString(",")); GroupedLineEdit::keyPressEvent(&fakeEvent); } else { GroupedLineEdit::keyPressEvent(e); } + lastFinishedTag = finishedTag; } void TagWidget::wheelEvent(QWheelEvent *event) diff --git a/qt-ui/tagwidget.h b/qt-ui/tagwidget.h index 62fa36f30..08984f712 100644 --- a/qt-ui/tagwidget.h +++ b/qt-ui/tagwidget.h @@ -12,21 +12,22 @@ public: void setCompleter(QCompleter *completer); QPair<int, int> getCursorTagPosition(); void highlight(); - void setText(const QString& text); + void setText(const QString &text); void clear(); void setCursorPosition(int position); void wheelEvent(QWheelEvent *event); public slots: void reparse(); - void completionSelected(const QString& text); - void completionHighlighted(const QString& text); + void completionSelected(const QString &text); + void completionHighlighted(const QString &text); protected: void keyPressEvent(QKeyEvent *e); private: QCompleter *m_completer; + bool lastFinishedTag; }; #endif // TAGWIDGET_H diff --git a/qt-ui/updatemanager.cpp b/qt-ui/updatemanager.cpp index bcf58088d..75f454795 100644 --- a/qt-ui/updatemanager.cpp +++ b/qt-ui/updatemanager.cpp @@ -4,11 +4,10 @@ #include "subsurfacewebservices.h" #include "ssrf-version.h" -UpdateManager::UpdateManager(QObject *parent) : - QObject(parent) +UpdateManager::UpdateManager(QObject *parent) : QObject(parent) { manager = SubsurfaceWebServices::manager(); - connect (manager, SIGNAL(finished(QNetworkReply*)), SLOT(requestReceived(QNetworkReply*))); + connect(manager, SIGNAL(finished(QNetworkReply *)), SLOT(requestReceived(QNetworkReply *))); } void UpdateManager::checkForUpdates() diff --git a/qt-ui/updatemanager.h b/qt-ui/updatemanager.h index 18b47cfde..561c53d0b 100644 --- a/qt-ui/updatemanager.h +++ b/qt-ui/updatemanager.h @@ -6,16 +6,17 @@ class QNetworkAccessManager; class QNetworkReply; -class UpdateManager : public QObject -{ +class UpdateManager : public QObject { Q_OBJECT public: explicit UpdateManager(QObject *parent = 0); void checkForUpdates(); + private: QNetworkAccessManager *manager; -public slots: - void requestReceived(QNetworkReply* reply); +public +slots: + void requestReceived(QNetworkReply *reply); }; #endif // UPDATEMANAGER_H diff --git a/qt-ui/usermanual.cpp b/qt-ui/usermanual.cpp index 0dd39af33..60c94382f 100644 --- a/qt-ui/usermanual.cpp +++ b/qt-ui/usermanual.cpp @@ -11,9 +11,9 @@ UserManual::UserManual(QWidget *parent) : QMainWindow(parent), { ui->setupUi(this); - QShortcut* closeKey = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this); + QShortcut *closeKey = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_W), this); connect(closeKey, SIGNAL(activated()), this, SLOT(close())); - QShortcut* quitKey = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this); + QShortcut *quitKey = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q), this); connect(quitKey, SIGNAL(activated()), parent, SLOT(close())); QAction *actionShowSearch = new QAction(this); diff --git a/qt-ui/usermanual.h b/qt-ui/usermanual.h index 7692a1143..de8770eba 100644 --- a/qt-ui/usermanual.h +++ b/qt-ui/usermanual.h @@ -4,8 +4,7 @@ #include <QMainWindow> #include <QWebPage> -namespace Ui -{ +namespace Ui { class UserManual; } |