2017-04-27 18:26:05 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2013-04-14 03:44:02 +00:00
|
|
|
/*
|
|
|
|
* maintab.cpp
|
|
|
|
*
|
|
|
|
* classes for the "notebook" area of the main window of Subsurface
|
|
|
|
*
|
|
|
|
*/
|
2017-04-04 17:21:30 +00:00
|
|
|
#include "desktop-widgets/tab-widgets/maintab.h"
|
2016-04-05 05:02:03 +00:00
|
|
|
#include "desktop-widgets/mainwindow.h"
|
2017-07-15 20:37:02 +00:00
|
|
|
#include "desktop-widgets/mapwidget.h"
|
2018-06-03 20:15:19 +00:00
|
|
|
#include "core/qthelper.h"
|
2016-04-05 05:02:03 +00:00
|
|
|
#include "core/statistics.h"
|
|
|
|
#include "desktop-widgets/modeldelegates.h"
|
|
|
|
#include "qt-models/diveplannermodel.h"
|
|
|
|
#include "desktop-widgets/divelistview.h"
|
|
|
|
#include "core/display.h"
|
2015-09-03 18:56:37 +00:00
|
|
|
#include "profile-widget/profilewidget2.h"
|
2016-04-05 05:02:03 +00:00
|
|
|
#include "desktop-widgets/diveplanner.h"
|
|
|
|
#include "core/divesitehelpers.h"
|
|
|
|
#include "qt-models/cylindermodel.h"
|
|
|
|
#include "qt-models/weightmodel.h"
|
|
|
|
#include "qt-models/divecomputerextradatamodel.h"
|
|
|
|
#include "qt-models/divelocationmodel.h"
|
2017-11-26 21:21:58 +00:00
|
|
|
#include "qt-models/filtermodels.h"
|
2016-04-05 05:02:03 +00:00
|
|
|
#include "core/divesite.h"
|
2018-05-11 15:25:41 +00:00
|
|
|
#include "core/subsurface-string.h"
|
2018-06-17 06:48:54 +00:00
|
|
|
#include "core/gettextfromc.h"
|
2016-04-05 05:02:03 +00:00
|
|
|
#include "desktop-widgets/locationinformation.h"
|
2018-07-23 21:41:23 +00:00
|
|
|
#include "desktop-widgets/command.h"
|
2018-10-21 16:00:02 +00:00
|
|
|
#include "desktop-widgets/simplewidgets.h"
|
2015-06-01 19:58:23 +00:00
|
|
|
|
2017-04-04 17:21:30 +00:00
|
|
|
#include "TabDiveExtraInfo.h"
|
|
|
|
#include "TabDiveInformation.h"
|
|
|
|
#include "TabDivePhotos.h"
|
|
|
|
#include "TabDiveStatistics.h"
|
2019-03-09 21:32:16 +00:00
|
|
|
#include "TabDiveSite.h"
|
2017-04-04 17:21:30 +00:00
|
|
|
|
2013-08-13 13:49:59 +00:00
|
|
|
#include <QCompleter>
|
2013-11-28 11:17:30 +00:00
|
|
|
#include <QSettings>
|
2013-12-12 01:08:56 +00:00
|
|
|
#include <QScrollBar>
|
2014-06-03 22:29:28 +00:00
|
|
|
#include <QShortcut>
|
2014-06-04 01:01:00 +00:00
|
|
|
#include <QMessageBox>
|
2014-06-27 12:17:33 +00:00
|
|
|
#include <QDesktopServices>
|
2015-05-11 17:38:50 +00:00
|
|
|
#include <QStringList>
|
2013-04-07 22:20:43 +00:00
|
|
|
|
|
|
|
MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
|
2014-02-28 04:09:57 +00:00
|
|
|
weightModel(new WeightModel(this)),
|
2017-02-21 13:37:18 +00:00
|
|
|
cylindersModel(new CylindersModel(this)),
|
2014-06-02 22:50:42 +00:00
|
|
|
editMode(NONE),
|
2014-11-08 13:11:06 +00:00
|
|
|
copyPaste(false),
|
2018-03-15 21:41:59 +00:00
|
|
|
lastSelectedDive(true),
|
2017-11-30 19:33:43 +00:00
|
|
|
lastTabSelectedDive(0),
|
2017-12-19 22:05:42 +00:00
|
|
|
lastTabSelectedDiveTrip(0),
|
|
|
|
currentTrip(0)
|
2013-04-07 22:20:43 +00:00
|
|
|
{
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.setupUi(this);
|
2017-04-04 17:21:30 +00:00
|
|
|
|
2017-04-04 18:01:47 +00:00
|
|
|
extraWidgets << new TabDiveInformation();
|
2017-04-13 18:23:07 +00:00
|
|
|
ui.tabWidget->addTab(extraWidgets.last(), tr("Information"));
|
2017-04-04 18:01:47 +00:00
|
|
|
extraWidgets << new TabDiveStatistics();
|
2017-04-13 18:23:07 +00:00
|
|
|
ui.tabWidget->addTab(extraWidgets.last(), tr("Statistics"));
|
2017-04-04 18:01:47 +00:00
|
|
|
extraWidgets << new TabDivePhotos();
|
2018-07-13 18:46:45 +00:00
|
|
|
ui.tabWidget->addTab(extraWidgets.last(), tr("Media"));
|
2017-04-21 16:33:38 +00:00
|
|
|
extraWidgets << new TabDiveExtraInfo();
|
|
|
|
ui.tabWidget->addTab(extraWidgets.last(), tr("Extra Info"));
|
2019-03-09 21:32:16 +00:00
|
|
|
extraWidgets << new TabDiveSite();
|
|
|
|
ui.tabWidget->addTab(extraWidgets.last(), tr("Dive sites"));
|
2017-04-04 17:21:30 +00:00
|
|
|
|
2015-10-29 23:57:43 +00:00
|
|
|
ui.dateEdit->setDisplayFormat(prefs.date_format);
|
2018-05-04 03:58:47 +00:00
|
|
|
ui.timeEdit->setDisplayFormat(prefs.time_format);
|
2014-02-09 18:49:15 +00:00
|
|
|
|
2014-07-02 18:50:28 +00:00
|
|
|
memset(&displayed_dive, 0, sizeof(displayed_dive));
|
2014-07-30 15:52:11 +00:00
|
|
|
memset(&displayedTrip, 0, sizeof(displayedTrip));
|
2014-02-09 18:49:15 +00:00
|
|
|
|
2017-04-26 15:30:08 +00:00
|
|
|
// This makes sure we only delete the models
|
|
|
|
// after the destructor of the tables,
|
|
|
|
// this is needed to save the column sizes.
|
|
|
|
cylindersModel->setParent(ui.cylinders);
|
|
|
|
weightModel->setParent(ui.weights);
|
|
|
|
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.cylinders->setModel(cylindersModel);
|
|
|
|
ui.weights->setModel(weightModel);
|
2013-12-03 20:44:48 +00:00
|
|
|
closeMessage();
|
2013-09-26 20:02:27 +00:00
|
|
|
|
2019-01-27 21:08:13 +00:00
|
|
|
connect(&diveListNotifier, &DiveListNotifier::divesEdited, this, &MainTab::divesEdited);
|
2019-03-16 10:51:42 +00:00
|
|
|
connect(ui.editDiveSiteButton, &QToolButton::clicked, MainWindow::instance(), &MainWindow::startDiveSiteEdit);
|
2017-07-15 20:37:02 +00:00
|
|
|
connect(ui.location, &DiveLocationLineEdit::entered, MapWidget::instance(), &MapWidget::centerOnIndex);
|
|
|
|
connect(ui.location, &DiveLocationLineEdit::currentChanged, MapWidget::instance(), &MapWidget::centerOnIndex);
|
2015-02-11 15:32:29 +00:00
|
|
|
|
2014-11-23 15:41:25 +00:00
|
|
|
QAction *action = new QAction(tr("Apply changes"), this);
|
2013-12-02 17:33:00 +00:00
|
|
|
connect(action, SIGNAL(triggered(bool)), this, SLOT(acceptChanges()));
|
2013-12-03 20:44:48 +00:00
|
|
|
addMessageAction(action);
|
2013-12-02 17:33:00 +00:00
|
|
|
|
2014-11-23 15:41:25 +00:00
|
|
|
action = new QAction(tr("Discard changes"), this);
|
2013-12-02 17:33:00 +00:00
|
|
|
connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges()));
|
2015-02-11 15:58:23 +00:00
|
|
|
addMessageAction(action);
|
2014-06-03 22:29:28 +00:00
|
|
|
|
|
|
|
QShortcut *closeKey = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
|
|
|
connect(closeKey, SIGNAL(activated()), this, SLOT(escDetected()));
|
|
|
|
|
2013-09-26 20:02:27 +00:00
|
|
|
if (qApp->style()->objectName() == "oxygen")
|
2013-09-26 19:51:11 +00:00
|
|
|
setDocumentMode(true);
|
2013-09-26 20:02:27 +00:00
|
|
|
else
|
|
|
|
setDocumentMode(false);
|
|
|
|
|
2013-05-20 00:38:20 +00:00
|
|
|
// we start out with the fields read-only; once things are
|
|
|
|
// filled from a dive, they are made writeable
|
2013-09-19 00:56:53 +00:00
|
|
|
setEnabled(false);
|
2013-05-19 14:45:01 +00:00
|
|
|
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.cylinders->setTitle(tr("Cylinders"));
|
2014-11-25 15:47:24 +00:00
|
|
|
ui.cylinders->setBtnToolTip(tr("Add cylinder"));
|
2013-10-03 18:54:25 +00:00
|
|
|
connect(ui.cylinders, SIGNAL(addButtonClicked()), this, SLOT(addCylinder_clicked()));
|
|
|
|
|
|
|
|
ui.weights->setTitle(tr("Weights"));
|
2014-11-25 15:47:24 +00:00
|
|
|
ui.weights->setBtnToolTip(tr("Add weight system"));
|
2013-10-03 18:54:25 +00:00
|
|
|
connect(ui.weights, SIGNAL(addButtonClicked()), this, SLOT(addWeight_clicked()));
|
|
|
|
|
2015-01-01 16:00:46 +00:00
|
|
|
// This needs to be the same order as enum dive_comp_type in dive.h!
|
2018-05-17 08:04:41 +00:00
|
|
|
QStringList types = QStringList();
|
|
|
|
for (int i = 0; i < NUM_DIVEMODE; i++)
|
2018-06-17 15:55:47 +00:00
|
|
|
types.append(gettextFromC::tr(divemode_text_ui[i]));
|
2018-05-17 08:04:41 +00:00
|
|
|
ui.DiveType->insertItems(0, types);
|
2015-01-08 13:42:07 +00:00
|
|
|
connect(ui.DiveType, SIGNAL(currentIndexChanged(int)), this, SLOT(divetype_Changed(int)));
|
2015-01-01 16:00:46 +00:00
|
|
|
|
2013-10-03 18:54:25 +00:00
|
|
|
connect(ui.cylinders->view(), SIGNAL(clicked(QModelIndex)), this, SLOT(editCylinderWidget(QModelIndex)));
|
2013-10-03 23:04:51 +00:00
|
|
|
connect(ui.weights->view(), SIGNAL(clicked(QModelIndex)), this, SLOT(editWeightWidget(QModelIndex)));
|
2013-10-03 18:54:25 +00:00
|
|
|
|
2014-01-15 17:52:42 +00:00
|
|
|
ui.cylinders->view()->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate(this));
|
2014-11-17 14:03:37 +00:00
|
|
|
ui.cylinders->view()->setItemDelegateForColumn(CylindersModel::USE, new TankUseDelegate(this));
|
2014-01-15 17:52:42 +00:00
|
|
|
ui.weights->view()->setItemDelegateForColumn(WeightModel::TYPE, new WSInfoDelegate(this));
|
2014-03-22 14:13:58 +00:00
|
|
|
ui.cylinders->view()->setColumnHidden(CylindersModel::DEPTH, true);
|
2014-02-11 17:46:14 +00:00
|
|
|
completers.buddy = new QCompleter(&buddyModel, ui.buddy);
|
|
|
|
completers.divemaster = new QCompleter(&diveMasterModel, ui.divemaster);
|
|
|
|
completers.suit = new QCompleter(&suitModel, ui.suit);
|
|
|
|
completers.tags = new QCompleter(&tagModel, ui.tagWidget);
|
2014-01-06 22:00:10 +00:00
|
|
|
completers.buddy->setCaseSensitivity(Qt::CaseInsensitive);
|
|
|
|
completers.divemaster->setCaseSensitivity(Qt::CaseInsensitive);
|
|
|
|
completers.suit->setCaseSensitivity(Qt::CaseInsensitive);
|
2013-11-15 00:39:02 +00:00
|
|
|
completers.tags->setCaseSensitivity(Qt::CaseInsensitive);
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.buddy->setCompleter(completers.buddy);
|
|
|
|
ui.divemaster->setCompleter(completers.divemaster);
|
|
|
|
ui.suit->setCompleter(completers.suit);
|
2013-11-02 01:20:02 +00:00
|
|
|
ui.tagWidget->setCompleter(completers.tags);
|
2015-06-04 01:08:57 +00:00
|
|
|
ui.diveNotesMessage->hide();
|
2017-02-04 21:12:50 +00:00
|
|
|
ui.depth->hide();
|
|
|
|
ui.depthLabel->hide();
|
|
|
|
ui.duration->hide();
|
|
|
|
ui.durationLabel->hide();
|
2013-09-26 21:14:09 +00:00
|
|
|
setMinimumHeight(0);
|
|
|
|
setMinimumWidth(0);
|
2013-09-27 15:52:01 +00:00
|
|
|
|
|
|
|
// Current display of things on Gnome3 looks like shit, so
|
|
|
|
// let`s fix that.
|
|
|
|
if (isGnome3Session()) {
|
|
|
|
QPalette p;
|
|
|
|
p.setColor(QPalette::Window, QColor(Qt::white));
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.scrollArea->viewport()->setPalette(p);
|
|
|
|
ui.scrollArea_2->viewport()->setPalette(p);
|
2013-12-04 20:24:37 +00:00
|
|
|
|
|
|
|
// GroupBoxes in Gnome3 looks like I'v drawn them...
|
2019-04-01 21:15:23 +00:00
|
|
|
static const QString gnomeCss = QStringLiteral(
|
2013-12-04 20:24:37 +00:00
|
|
|
"QGroupBox {"
|
2019-04-01 21:15:23 +00:00
|
|
|
"background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
|
|
|
|
"stop: 0 #E0E0E0, stop: 1 #FFFFFF);"
|
|
|
|
"border: 2px solid gray;"
|
|
|
|
"border-radius: 5px;"
|
|
|
|
"margin-top: 1ex;"
|
2013-12-04 20:24:37 +00:00
|
|
|
"}"
|
|
|
|
"QGroupBox::title {"
|
2019-04-01 21:15:23 +00:00
|
|
|
"subcontrol-origin: margin;"
|
|
|
|
"subcontrol-position: top center;"
|
|
|
|
"padding: 0 3px;"
|
|
|
|
"background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
|
|
|
|
"stop: 0 #E0E0E0, stop: 1 #FFFFFF);"
|
2013-12-04 20:24:37 +00:00
|
|
|
"}");
|
2014-05-22 18:40:22 +00:00
|
|
|
Q_FOREACH (QGroupBox *box, findChildren<QGroupBox *>()) {
|
2013-12-04 20:24:37 +00:00
|
|
|
box->setStyleSheet(gnomeCss);
|
|
|
|
}
|
2013-09-27 15:52:01 +00:00
|
|
|
}
|
2014-12-23 18:16:11 +00:00
|
|
|
// QLineEdit and QLabels should have minimal margin on the left and right but not waste vertical space
|
2015-01-02 20:42:02 +00:00
|
|
|
QMargins margins(3, 2, 1, 0);
|
2014-12-23 18:16:11 +00:00
|
|
|
Q_FOREACH (QLabel *label, findChildren<QLabel *>()) {
|
|
|
|
label->setContentsMargins(margins);
|
|
|
|
}
|
2013-11-28 11:17:30 +00:00
|
|
|
ui.cylinders->view()->horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu);
|
2015-10-08 10:52:37 +00:00
|
|
|
ui.weights->view()->horizontalHeader()->setContextMenuPolicy(Qt::ActionsContextMenu);
|
2013-11-28 11:17:30 +00:00
|
|
|
|
|
|
|
QSettings s;
|
|
|
|
s.beginGroup("cylinders_dialog");
|
2014-02-28 04:09:57 +00:00
|
|
|
for (int i = 0; i < CylindersModel::COLUMNS; i++) {
|
2013-11-28 11:17:30 +00:00
|
|
|
if ((i == CylindersModel::REMOVE) || (i == CylindersModel::TYPE))
|
2014-02-28 04:09:57 +00:00
|
|
|
continue;
|
2013-11-28 11:17:30 +00:00
|
|
|
bool checked = s.value(QString("column%1_hidden").arg(i)).toBool();
|
2014-02-12 14:07:32 +00:00
|
|
|
action = new QAction(cylindersModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(), ui.cylinders->view());
|
2013-11-28 11:17:30 +00:00
|
|
|
action->setCheckable(true);
|
|
|
|
action->setData(i);
|
|
|
|
action->setChecked(!checked);
|
|
|
|
connect(action, SIGNAL(triggered(bool)), this, SLOT(toggleTriggeredColumn()));
|
|
|
|
ui.cylinders->view()->setColumnHidden(i, checked);
|
|
|
|
ui.cylinders->view()->horizontalHeader()->addAction(action);
|
|
|
|
}
|
2014-08-06 21:05:54 +00:00
|
|
|
|
2015-09-23 19:03:28 +00:00
|
|
|
connect(ui.diveNotesMessage, &KMessageWidget::showAnimationFinished,
|
|
|
|
ui.location, &DiveLocationLineEdit::fixPopupPosition);
|
|
|
|
|
2015-11-16 04:56:24 +00:00
|
|
|
// enable URL clickability in notes:
|
|
|
|
new TextHyperlinkEventFilter(ui.notes);//destroyed when ui.notes is destroyed
|
|
|
|
|
2015-01-05 07:17:01 +00:00
|
|
|
acceptingEdit = false;
|
2015-10-01 20:54:13 +00:00
|
|
|
|
|
|
|
ui.diveTripLocation->hide();
|
2013-11-28 11:17:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MainTab::~MainTab()
|
|
|
|
{
|
|
|
|
QSettings s;
|
|
|
|
s.beginGroup("cylinders_dialog");
|
2014-02-28 04:09:57 +00:00
|
|
|
for (int i = 0; i < CylindersModel::COLUMNS; i++) {
|
2013-11-28 11:17:30 +00:00
|
|
|
if ((i == CylindersModel::REMOVE) || (i == CylindersModel::TYPE))
|
2014-02-28 04:09:57 +00:00
|
|
|
continue;
|
2013-11-28 11:17:30 +00:00
|
|
|
s.setValue(QString("column%1_hidden").arg(i), ui.cylinders->view()->isColumnHidden(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::toggleTriggeredColumn()
|
|
|
|
{
|
2014-02-28 04:09:57 +00:00
|
|
|
QAction *action = qobject_cast<QAction *>(sender());
|
2013-11-28 11:17:30 +00:00
|
|
|
int col = action->data().toInt();
|
|
|
|
QTableView *view = ui.cylinders->view();
|
|
|
|
|
2014-01-16 04:50:56 +00:00
|
|
|
if (action->isChecked()) {
|
2013-11-28 11:17:30 +00:00
|
|
|
view->showColumn(col);
|
2014-01-16 04:50:56 +00:00
|
|
|
if (view->columnWidth(col) <= 15)
|
2013-11-28 11:17:30 +00:00
|
|
|
view->setColumnWidth(col, 80);
|
2014-02-28 04:09:57 +00:00
|
|
|
} else
|
2013-11-28 11:17:30 +00:00
|
|
|
view->hideColumn(col);
|
2013-06-27 12:33:43 +00:00
|
|
|
}
|
2013-05-22 12:17:18 +00:00
|
|
|
|
2013-09-19 04:33:39 +00:00
|
|
|
void MainTab::addDiveStarted()
|
|
|
|
{
|
2018-09-13 15:33:07 +00:00
|
|
|
ui.tabWidget->setCurrentIndex(0);
|
|
|
|
ui.tabWidget->setTabEnabled(2, false);
|
|
|
|
ui.tabWidget->setTabEnabled(3, false);
|
|
|
|
ui.tabWidget->setTabEnabled(4, false);
|
|
|
|
ui.tabWidget->setTabEnabled(5, false);
|
2013-12-27 16:18:53 +00:00
|
|
|
enableEdition(ADD);
|
2013-09-19 04:33:39 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::addMessageAction(QAction *action)
|
2013-12-03 20:44:48 +00:00
|
|
|
{
|
|
|
|
ui.diveNotesMessage->addAction(action);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::hideMessage()
|
|
|
|
{
|
|
|
|
ui.diveNotesMessage->animatedHide();
|
2014-04-05 16:03:45 +00:00
|
|
|
updateTextLabels(false);
|
2013-12-03 20:44:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::closeMessage()
|
|
|
|
{
|
|
|
|
hideMessage();
|
|
|
|
ui.diveNotesMessage->setCloseButtonVisible(false);
|
2019-01-27 21:08:13 +00:00
|
|
|
}
|
2013-12-03 20:44:48 +00:00
|
|
|
|
|
|
|
void MainTab::displayMessage(QString str)
|
|
|
|
{
|
2014-08-05 05:45:17 +00:00
|
|
|
ui.diveNotesMessage->setCloseButtonVisible(false);
|
2013-12-03 20:44:48 +00:00
|
|
|
ui.diveNotesMessage->setText(str);
|
|
|
|
ui.diveNotesMessage->animatedShow();
|
2014-04-05 16:03:45 +00:00
|
|
|
updateTextLabels();
|
2014-03-11 03:49:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::updateTextLabels(bool showUnits)
|
|
|
|
{
|
2014-04-05 16:03:45 +00:00
|
|
|
if (showUnits) {
|
2014-07-10 23:06:51 +00:00
|
|
|
ui.airTempLabel->setText(tr("Air temp. [%1]").arg(get_temp_unit()));
|
|
|
|
ui.waterTempLabel->setText(tr("Water temp. [%1]").arg(get_temp_unit()));
|
2014-03-11 03:49:08 +00:00
|
|
|
} else {
|
2014-07-10 23:06:51 +00:00
|
|
|
ui.airTempLabel->setText(tr("Air temp."));
|
|
|
|
ui.waterTempLabel->setText(tr("Water temp."));
|
2014-03-11 03:49:08 +00:00
|
|
|
}
|
2013-12-03 20:44:48 +00:00
|
|
|
}
|
|
|
|
|
2013-11-01 15:48:34 +00:00
|
|
|
void MainTab::enableEdition(EditMode newEditMode)
|
2013-08-13 11:34:04 +00:00
|
|
|
{
|
2015-03-26 00:23:43 +00:00
|
|
|
const bool isTripEdit = MainWindow::instance() &&
|
2018-10-12 14:13:42 +00:00
|
|
|
MainWindow::instance()->diveList->selectedTrips().count() == 1;
|
2015-03-26 00:23:43 +00:00
|
|
|
|
2014-07-03 21:45:01 +00:00
|
|
|
if (((newEditMode == DIVE || newEditMode == NONE) && current_dive == NULL) || editMode != NONE)
|
2013-08-13 11:34:04 +00:00
|
|
|
return;
|
2014-07-03 04:33:03 +00:00
|
|
|
modified = false;
|
2014-11-05 14:34:29 +00:00
|
|
|
copyPaste = false;
|
2013-12-27 16:18:53 +00:00
|
|
|
if ((newEditMode == DIVE || newEditMode == NONE) &&
|
2015-03-26 00:23:43 +00:00
|
|
|
!isTripEdit &&
|
2014-01-03 12:49:17 +00:00
|
|
|
current_dive->dc.model &&
|
2013-12-27 16:18:53 +00:00
|
|
|
strcmp(current_dive->dc.model, "manually added dive") == 0) {
|
|
|
|
// editCurrentDive will call enableEdition with newEditMode == MANUALLY_ADDED_DIVE
|
|
|
|
// so exit this function here after editCurrentDive() returns
|
2014-07-03 21:45:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME : can we get rid of this recursive crap?
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->editCurrentDive();
|
2013-12-27 16:18:53 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-09-23 20:11:43 +00:00
|
|
|
|
|
|
|
ui.editDiveSiteButton->setEnabled(false);
|
2018-10-12 14:13:42 +00:00
|
|
|
MainWindow::instance()->diveList->setEnabled(false);
|
2014-08-04 15:58:21 +00:00
|
|
|
MainWindow::instance()->setEnabledToolbar(false);
|
2018-05-03 17:19:54 +00:00
|
|
|
MainWindow::instance()->enterEditState();
|
2018-09-13 15:33:07 +00:00
|
|
|
ui.tabWidget->setTabEnabled(2, false);
|
|
|
|
ui.tabWidget->setTabEnabled(3, false);
|
|
|
|
ui.tabWidget->setTabEnabled(5, false);
|
2014-07-03 21:45:01 +00:00
|
|
|
|
2015-03-26 00:23:43 +00:00
|
|
|
if (isTripEdit) {
|
2013-09-19 00:56:53 +00:00
|
|
|
// we are editing trip location and notes
|
2013-12-03 20:44:48 +00:00
|
|
|
displayMessage(tr("This trip is being edited."));
|
2014-07-30 15:52:11 +00:00
|
|
|
currentTrip = current_dive->divetrip;
|
2014-06-19 16:52:34 +00:00
|
|
|
ui.dateEdit->setEnabled(false);
|
2013-09-19 00:56:53 +00:00
|
|
|
editMode = TRIP;
|
|
|
|
} else {
|
2014-08-23 14:49:28 +00:00
|
|
|
ui.dateEdit->setEnabled(true);
|
2013-11-05 06:57:24 +00:00
|
|
|
if (amount_selected > 1) {
|
2013-12-03 20:44:48 +00:00
|
|
|
displayMessage(tr("Multiple dives are being edited."));
|
2013-11-05 06:57:24 +00:00
|
|
|
} else {
|
2013-12-03 20:44:48 +00:00
|
|
|
displayMessage(tr("This dive is being edited."));
|
2013-11-05 06:57:24 +00:00
|
|
|
}
|
2013-11-01 15:48:34 +00:00
|
|
|
editMode = newEditMode != NONE ? newEditMode : DIVE;
|
2013-09-19 00:56:53 +00:00
|
|
|
}
|
2013-08-13 11:34:04 +00:00
|
|
|
}
|
|
|
|
|
2019-02-10 16:37:06 +00:00
|
|
|
static void profileFromDive(struct dive *d)
|
|
|
|
{
|
|
|
|
DivePlannerPointsModel::instance()->loadFromDive(d);
|
|
|
|
MainWindow::instance()->graphics->setReplot(true);
|
|
|
|
MainWindow::instance()->graphics->plotDive(current_dive, true);
|
|
|
|
}
|
|
|
|
|
2019-01-27 21:08:13 +00:00
|
|
|
// This function gets called if a field gets updated by an undo command.
|
|
|
|
// Refresh the corresponding UI field.
|
|
|
|
void MainTab::divesEdited(const QVector<dive *> &, DiveField field)
|
|
|
|
{
|
|
|
|
// If there is no current dive, no point in updating anything
|
|
|
|
if (!current_dive)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch(field) {
|
2019-02-10 16:37:06 +00:00
|
|
|
case DiveField::DURATION:
|
|
|
|
ui.duration->setText(render_seconds_to_string(current_dive->duration.seconds));
|
|
|
|
profileFromDive(current_dive);
|
|
|
|
break;
|
|
|
|
case DiveField::DEPTH:
|
|
|
|
ui.depth->setText(get_depth_string(current_dive->maxdepth, true));
|
|
|
|
profileFromDive(current_dive);
|
|
|
|
break;
|
2019-01-30 21:13:24 +00:00
|
|
|
case DiveField::AIR_TEMP:
|
|
|
|
ui.airtemp->setText(get_temperature_string(current_dive->airtemp, true));
|
|
|
|
break;
|
|
|
|
case DiveField::WATER_TEMP:
|
|
|
|
ui.watertemp->setText(get_temperature_string(current_dive->watertemp, true));
|
|
|
|
break;
|
2019-01-28 21:35:07 +00:00
|
|
|
case DiveField::RATING:
|
|
|
|
ui.rating->setCurrentStars(current_dive->rating);
|
|
|
|
break;
|
|
|
|
case DiveField::VISIBILITY:
|
|
|
|
ui.visibility->setCurrentStars(current_dive->visibility);
|
|
|
|
break;
|
2019-01-28 20:42:59 +00:00
|
|
|
case DiveField::SUIT:
|
|
|
|
ui.suit->setText(QString(current_dive->suit));
|
|
|
|
break;
|
2019-01-27 21:08:13 +00:00
|
|
|
case DiveField::NOTES:
|
|
|
|
updateNotes(current_dive);
|
|
|
|
break;
|
2019-01-28 17:35:27 +00:00
|
|
|
case DiveField::MODE:
|
|
|
|
updateMode(current_dive);
|
|
|
|
break;
|
2019-03-19 21:05:52 +00:00
|
|
|
case DiveField::DATETIME:
|
|
|
|
updateDateTime(current_dive);
|
|
|
|
MainWindow::instance()->graphics->dateTimeChanged();
|
|
|
|
DivePlannerPointsModel::instance()->getDiveplan().when = current_dive->when;
|
|
|
|
break;
|
2019-03-20 20:46:58 +00:00
|
|
|
case DiveField::DIVESITE:
|
|
|
|
updateDiveSite(current_dive);
|
|
|
|
emit diveSiteChanged();
|
|
|
|
break;
|
2019-02-07 18:59:34 +00:00
|
|
|
case DiveField::TAGS:
|
|
|
|
ui.tagWidget->setText(get_taglist_string(current_dive->tag_list));
|
|
|
|
break;
|
2019-02-07 20:00:09 +00:00
|
|
|
case DiveField::BUDDY:
|
|
|
|
ui.buddy->setText(current_dive->buddy);
|
|
|
|
break;
|
2019-02-07 20:23:00 +00:00
|
|
|
case DiveField::DIVEMASTER:
|
|
|
|
ui.divemaster->setText(current_dive->divemaster);
|
|
|
|
break;
|
2019-01-27 21:08:13 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-13 13:17:59 +00:00
|
|
|
void MainTab::clearEquipment()
|
|
|
|
{
|
2013-10-10 08:16:32 +00:00
|
|
|
cylindersModel->clear();
|
|
|
|
weightModel->clear();
|
2013-04-13 13:17:59 +00:00
|
|
|
}
|
|
|
|
|
2014-05-16 06:12:46 +00:00
|
|
|
void MainTab::nextInputField(QKeyEvent *event)
|
|
|
|
{
|
|
|
|
keyPressEvent(event);
|
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
#define UPDATE_TEXT(d, field) \
|
2014-07-03 05:15:08 +00:00
|
|
|
if (clear || !d.field) \
|
2014-07-21 23:34:15 +00:00
|
|
|
ui.field->setText(QString()); \
|
2014-02-28 04:09:57 +00:00
|
|
|
else \
|
2014-07-02 21:15:17 +00:00
|
|
|
ui.field->setText(d.field)
|
2013-05-06 17:16:16 +00:00
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
#define UPDATE_TEMP(d, field) \
|
2014-07-02 21:15:17 +00:00
|
|
|
if (clear || d.field.mkelvin == 0) \
|
2014-02-28 04:09:57 +00:00
|
|
|
ui.field->setText(""); \
|
|
|
|
else \
|
2014-07-02 21:15:17 +00:00
|
|
|
ui.field->setText(get_temperature_string(d.field, true))
|
2013-09-20 23:41:42 +00:00
|
|
|
|
2013-11-10 21:23:18 +00:00
|
|
|
bool MainTab::isEditing()
|
|
|
|
{
|
|
|
|
return editMode != NONE;
|
|
|
|
}
|
|
|
|
|
2017-02-26 20:05:23 +00:00
|
|
|
void MainTab::updateDepthDuration()
|
|
|
|
{
|
|
|
|
ui.depth->setVisible(true);
|
|
|
|
ui.depthLabel->setVisible(true);
|
|
|
|
ui.duration->setVisible(true);
|
|
|
|
ui.durationLabel->setVisible(true);
|
2018-02-04 19:07:32 +00:00
|
|
|
ui.duration->setText(render_seconds_to_string(displayed_dive.duration.seconds));
|
2017-02-26 20:05:23 +00:00
|
|
|
ui.depth->setText(get_depth_string(displayed_dive.maxdepth, true));
|
|
|
|
}
|
|
|
|
|
2019-01-27 21:08:13 +00:00
|
|
|
void MainTab::updateNotes(const struct dive *d)
|
|
|
|
{
|
|
|
|
QString tmp(d->notes);
|
|
|
|
if (tmp.indexOf("<div") != -1) {
|
|
|
|
tmp.replace(QString("\n"), QString("<br>"));
|
|
|
|
ui.notes->setHtml(tmp);
|
|
|
|
} else {
|
|
|
|
ui.notes->setPlainText(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-28 17:35:27 +00:00
|
|
|
void MainTab::updateMode(struct dive *d)
|
|
|
|
{
|
|
|
|
ui.DiveType->setCurrentIndex(get_dive_dc(d, dc_number)->divemode);
|
|
|
|
MainWindow::instance()->graphics->recalcCeiling();
|
|
|
|
}
|
|
|
|
|
2019-03-19 21:05:52 +00:00
|
|
|
void MainTab::updateDateTime(struct dive *d)
|
|
|
|
{
|
|
|
|
// Subsurface always uses "local time" as in "whatever was the local time at the location"
|
|
|
|
// so all time stamps have no time zone information and are in UTC
|
|
|
|
QDateTime localTime = QDateTime::fromMSecsSinceEpoch(1000*d->when, Qt::UTC);
|
|
|
|
localTime.setTimeSpec(Qt::UTC);
|
|
|
|
ui.dateEdit->setDate(localTime.date());
|
|
|
|
ui.timeEdit->setTime(localTime.time());
|
|
|
|
}
|
|
|
|
|
2019-03-20 20:46:58 +00:00
|
|
|
void MainTab::updateDiveSite(struct dive *d)
|
|
|
|
{
|
|
|
|
struct dive_site *ds = d->dive_site;
|
|
|
|
if (ds) {
|
|
|
|
ui.location->setCurrentDiveSite(ds);
|
|
|
|
ui.locationTags->setText(constructLocationTags(&ds->taxonomy, true));
|
|
|
|
|
|
|
|
if (ui.locationTags->text().isEmpty() && has_location(&ds->location))
|
|
|
|
ui.locationTags->setText(printGPSCoords(&ds->location));
|
|
|
|
ui.editDiveSiteButton->setEnabled(true);
|
|
|
|
} else {
|
|
|
|
ui.location->clear();
|
|
|
|
ui.locationTags->clear();
|
|
|
|
ui.editDiveSiteButton->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-02 21:15:17 +00:00
|
|
|
void MainTab::updateDiveInfo(bool clear)
|
2013-05-06 16:23:14 +00:00
|
|
|
{
|
2015-09-21 17:01:58 +00:00
|
|
|
ui.location->refreshDiveSiteCache();
|
2015-07-16 17:42:56 +00:00
|
|
|
EditMode rememberEM = editMode;
|
2014-05-26 22:17:34 +00:00
|
|
|
// don't execute this while adding / planning a dive
|
2018-10-12 13:07:40 +00:00
|
|
|
if (editMode == ADD || editMode == MANUALLY_ADDED_DIVE || MainWindow::instance()->graphics->isPlanner())
|
2013-11-12 07:33:27 +00:00
|
|
|
return;
|
2015-05-17 21:50:22 +00:00
|
|
|
if (!isEnabled() && !clear )
|
2013-09-19 00:56:53 +00:00
|
|
|
setEnabled(true);
|
2014-07-02 21:15:17 +00:00
|
|
|
if (isEnabled() && clear)
|
2013-09-22 15:19:05 +00:00
|
|
|
setEnabled(false);
|
2014-07-03 05:15:08 +00:00
|
|
|
editMode = IGNORE; // don't trigger on changes to the widgets
|
|
|
|
|
2017-04-04 17:21:30 +00:00
|
|
|
for (auto widget : extraWidgets) {
|
|
|
|
widget->updateData();
|
|
|
|
}
|
2014-07-21 23:34:15 +00:00
|
|
|
|
|
|
|
ui.notes->setText(QString());
|
2019-01-27 21:08:13 +00:00
|
|
|
if (!clear)
|
|
|
|
updateNotes(&displayed_dive);
|
2014-07-02 21:15:17 +00:00
|
|
|
UPDATE_TEXT(displayed_dive, suit);
|
|
|
|
UPDATE_TEXT(displayed_dive, divemaster);
|
|
|
|
UPDATE_TEXT(displayed_dive, buddy);
|
|
|
|
UPDATE_TEMP(displayed_dive, airtemp);
|
|
|
|
UPDATE_TEMP(displayed_dive, watertemp);
|
2019-01-28 17:35:27 +00:00
|
|
|
updateMode(&displayed_dive);
|
2014-07-03 05:15:08 +00:00
|
|
|
|
2014-07-02 21:15:17 +00:00
|
|
|
if (!clear) {
|
2019-03-20 20:46:58 +00:00
|
|
|
updateDiveSite(&displayed_dive);
|
2019-03-19 21:05:52 +00:00
|
|
|
updateDateTime(&displayed_dive);
|
2018-10-12 14:13:42 +00:00
|
|
|
if (MainWindow::instance() && MainWindow::instance()->diveList->selectedTrips().count() == 1) {
|
2017-11-30 19:33:43 +00:00
|
|
|
// Remember the tab selected for last dive
|
|
|
|
if (lastSelectedDive)
|
|
|
|
lastTabSelectedDive = ui.tabWidget->currentIndex();
|
2017-11-30 18:36:05 +00:00
|
|
|
ui.tabWidget->setTabText(0, tr("Trip notes"));
|
2017-11-30 19:33:43 +00:00
|
|
|
ui.tabWidget->setTabEnabled(1, false);
|
|
|
|
ui.tabWidget->setTabEnabled(2, false);
|
|
|
|
ui.tabWidget->setTabEnabled(5, false);
|
|
|
|
// Recover the tab selected for last dive trip
|
|
|
|
if (lastSelectedDive)
|
|
|
|
ui.tabWidget->setCurrentIndex(lastTabSelectedDiveTrip);
|
|
|
|
lastSelectedDive = false;
|
2018-10-12 14:13:42 +00:00
|
|
|
currentTrip = *MainWindow::instance()->diveList->selectedTrips().begin();
|
2013-06-14 16:17:46 +00:00
|
|
|
// only use trip relevant fields
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.divemaster->setVisible(false);
|
|
|
|
ui.DivemasterLabel->setVisible(false);
|
|
|
|
ui.buddy->setVisible(false);
|
|
|
|
ui.BuddyLabel->setVisible(false);
|
|
|
|
ui.suit->setVisible(false);
|
|
|
|
ui.SuitLabel->setVisible(false);
|
|
|
|
ui.rating->setVisible(false);
|
|
|
|
ui.RatingLabel->setVisible(false);
|
|
|
|
ui.visibility->setVisible(false);
|
|
|
|
ui.visibilityLabel->setVisible(false);
|
2013-11-04 19:28:03 +00:00
|
|
|
ui.tagWidget->setVisible(false);
|
|
|
|
ui.TagLabel->setVisible(false);
|
2013-11-30 10:13:40 +00:00
|
|
|
ui.airTempLabel->setVisible(false);
|
2013-11-07 03:38:35 +00:00
|
|
|
ui.airtemp->setVisible(false);
|
2015-01-01 16:00:46 +00:00
|
|
|
ui.DiveType->setVisible(false);
|
|
|
|
ui.TypeLabel->setVisible(false);
|
2013-11-30 10:13:40 +00:00
|
|
|
ui.waterTempLabel->setVisible(false);
|
2013-11-07 03:38:35 +00:00
|
|
|
ui.watertemp->setVisible(false);
|
2016-01-17 10:53:50 +00:00
|
|
|
ui.dateEdit->setReadOnly(true);
|
2017-11-16 06:35:57 +00:00
|
|
|
ui.timeLabel->setVisible(false);
|
2016-01-17 10:53:51 +00:00
|
|
|
ui.timeEdit->setVisible(false);
|
2015-10-01 20:41:38 +00:00
|
|
|
ui.diveTripLocation->show();
|
|
|
|
ui.location->hide();
|
|
|
|
ui.editDiveSiteButton->hide();
|
2013-06-14 16:17:46 +00:00
|
|
|
// rename the remaining fields and fill data from selected trip
|
2014-07-10 23:06:42 +00:00
|
|
|
ui.LocationLabel->setText(tr("Trip location"));
|
2015-10-01 21:11:03 +00:00
|
|
|
ui.diveTripLocation->setText(currentTrip->location);
|
2015-07-01 23:38:22 +00:00
|
|
|
ui.locationTags->clear();
|
2015-09-25 17:51:10 +00:00
|
|
|
//TODO: Fix this.
|
|
|
|
//ui.location->setText(currentTrip->location);
|
2014-07-10 23:06:42 +00:00
|
|
|
ui.NotesLabel->setText(tr("Trip notes"));
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.notes->setText(currentTrip->notes);
|
2013-12-28 01:26:22 +00:00
|
|
|
clearEquipment();
|
|
|
|
ui.equipmentTab->setEnabled(false);
|
2017-02-04 21:44:10 +00:00
|
|
|
ui.depth->setVisible(false);
|
|
|
|
ui.depthLabel->setVisible(false);
|
|
|
|
ui.duration->setVisible(false);
|
|
|
|
ui.durationLabel->setVisible(false);
|
2013-06-14 16:17:46 +00:00
|
|
|
} else {
|
2017-11-30 19:33:43 +00:00
|
|
|
// Remember the tab selected for last dive trip
|
|
|
|
if (!lastSelectedDive)
|
|
|
|
lastTabSelectedDiveTrip = ui.tabWidget->currentIndex();
|
2017-11-30 18:36:05 +00:00
|
|
|
ui.tabWidget->setTabText(0, tr("Notes"));
|
2017-11-30 19:33:43 +00:00
|
|
|
ui.tabWidget->setTabEnabled(1, true);
|
|
|
|
ui.tabWidget->setTabEnabled(2, true);
|
2018-09-13 15:33:07 +00:00
|
|
|
ui.tabWidget->setTabEnabled(3, true);
|
|
|
|
ui.tabWidget->setTabEnabled(4, true);
|
2017-11-30 19:33:43 +00:00
|
|
|
ui.tabWidget->setTabEnabled(5, true);
|
|
|
|
// Recover the tab selected for last dive
|
|
|
|
if (!lastSelectedDive)
|
|
|
|
ui.tabWidget->setCurrentIndex(lastTabSelectedDive);
|
|
|
|
lastSelectedDive = true;
|
2014-07-30 15:52:11 +00:00
|
|
|
currentTrip = NULL;
|
2013-06-14 16:17:46 +00:00
|
|
|
// make all the fields visible writeable
|
2015-10-01 20:41:38 +00:00
|
|
|
ui.diveTripLocation->hide();
|
|
|
|
ui.location->show();
|
|
|
|
ui.editDiveSiteButton->show();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.divemaster->setVisible(true);
|
|
|
|
ui.buddy->setVisible(true);
|
|
|
|
ui.suit->setVisible(true);
|
|
|
|
ui.SuitLabel->setVisible(true);
|
|
|
|
ui.rating->setVisible(true);
|
|
|
|
ui.RatingLabel->setVisible(true);
|
|
|
|
ui.visibility->setVisible(true);
|
|
|
|
ui.visibilityLabel->setVisible(true);
|
|
|
|
ui.BuddyLabel->setVisible(true);
|
|
|
|
ui.DivemasterLabel->setVisible(true);
|
2013-11-04 19:28:03 +00:00
|
|
|
ui.TagLabel->setVisible(true);
|
|
|
|
ui.tagWidget->setVisible(true);
|
2013-11-30 10:13:40 +00:00
|
|
|
ui.airTempLabel->setVisible(true);
|
2013-11-07 03:38:35 +00:00
|
|
|
ui.airtemp->setVisible(true);
|
2015-01-01 16:00:46 +00:00
|
|
|
ui.TypeLabel->setVisible(true);
|
|
|
|
ui.DiveType->setVisible(true);
|
2013-11-30 10:13:40 +00:00
|
|
|
ui.waterTempLabel->setVisible(true);
|
2013-11-07 03:38:35 +00:00
|
|
|
ui.watertemp->setVisible(true);
|
2016-01-17 10:53:50 +00:00
|
|
|
ui.dateEdit->setReadOnly(false);
|
2017-11-16 06:35:57 +00:00
|
|
|
ui.timeLabel->setVisible(true);
|
2016-01-17 10:53:51 +00:00
|
|
|
ui.timeEdit->setVisible(true);
|
2013-06-14 16:17:46 +00:00
|
|
|
/* and fill them from the dive */
|
2014-07-02 21:15:17 +00:00
|
|
|
ui.rating->setCurrentStars(displayed_dive.rating);
|
|
|
|
ui.visibility->setCurrentStars(displayed_dive.visibility);
|
2013-06-14 16:17:46 +00:00
|
|
|
// reset labels in case we last displayed trip notes
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.LocationLabel->setText(tr("Location"));
|
|
|
|
ui.NotesLabel->setText(tr("Notes"));
|
2013-12-28 01:26:22 +00:00
|
|
|
ui.equipmentTab->setEnabled(true);
|
2014-07-03 05:38:08 +00:00
|
|
|
cylindersModel->updateDive();
|
|
|
|
weightModel->updateDive();
|
2018-04-09 08:09:34 +00:00
|
|
|
ui.tagWidget->setText(get_taglist_string(displayed_dive.tag_list));
|
2017-11-28 19:55:50 +00:00
|
|
|
if (current_dive) {
|
|
|
|
bool isManual = same_string(current_dive->dc.model, "manually added dive");
|
|
|
|
ui.depth->setVisible(isManual);
|
|
|
|
ui.depthLabel->setVisible(isManual);
|
|
|
|
ui.duration->setVisible(isManual);
|
|
|
|
ui.durationLabel->setVisible(isManual);
|
|
|
|
}
|
2013-06-14 16:17:46 +00:00
|
|
|
}
|
2018-02-04 19:07:32 +00:00
|
|
|
ui.duration->setText(render_seconds_to_string(displayed_dive.duration.seconds));
|
2017-02-04 21:44:10 +00:00
|
|
|
ui.depth->setText(get_depth_string(displayed_dive.maxdepth, true));
|
2015-06-25 18:42:28 +00:00
|
|
|
|
2013-12-09 21:37:49 +00:00
|
|
|
volume_t gases[MAX_CYLINDERS] = {};
|
2014-07-02 21:15:17 +00:00
|
|
|
get_gas_used(&displayed_dive, gases);
|
2013-11-20 06:50:02 +00:00
|
|
|
int mean[MAX_CYLINDERS], duration[MAX_CYLINDERS];
|
2014-07-02 21:15:17 +00:00
|
|
|
per_cylinder_mean_depth(&displayed_dive, select_dc(&displayed_dive), mean, duration);
|
2017-04-04 17:21:30 +00:00
|
|
|
|
2014-06-29 18:01:56 +00:00
|
|
|
volume_t o2_tot = {}, he_tot = {};
|
|
|
|
selected_dives_gas_parts(&o2_tot, &he_tot);
|
2014-07-06 02:34:43 +00:00
|
|
|
|
2015-06-25 18:42:28 +00:00
|
|
|
if(ui.locationTags->text().isEmpty())
|
|
|
|
ui.locationTags->hide();
|
|
|
|
else
|
|
|
|
ui.locationTags->show();
|
2017-10-06 14:51:02 +00:00
|
|
|
ui.editDiveSiteButton->setEnabled(!ui.location->text().isEmpty());
|
2015-10-08 06:38:26 +00:00
|
|
|
/* unset the special value text for date and time, just in case someone dove at midnight */
|
|
|
|
ui.dateEdit->setSpecialValueText(QString(""));
|
|
|
|
ui.timeEdit->setSpecialValueText(QString(""));
|
2013-05-08 19:08:00 +00:00
|
|
|
} else {
|
2013-05-20 00:38:20 +00:00
|
|
|
/* clear the fields */
|
2017-04-04 17:21:30 +00:00
|
|
|
clearTabs();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.rating->setCurrentStars(0);
|
|
|
|
ui.visibility->setCurrentStars(0);
|
2015-02-12 20:46:21 +00:00
|
|
|
ui.location->clear();
|
2015-10-08 06:38:26 +00:00
|
|
|
/* set date and time to minimums which triggers showing the special value text */
|
|
|
|
ui.dateEdit->setSpecialValueText(QString("-"));
|
|
|
|
ui.dateEdit->setMinimumDate(QDate(1, 1, 1));
|
|
|
|
ui.dateEdit->setDate(QDate(1, 1, 1));
|
|
|
|
ui.timeEdit->setSpecialValueText(QString("-"));
|
|
|
|
ui.timeEdit->setMinimumTime(QTime(0, 0, 0, 0));
|
|
|
|
ui.timeEdit->setTime(QTime(0, 0, 0, 0));
|
2018-01-01 07:49:40 +00:00
|
|
|
ui.tagWidget->clear();
|
2013-05-08 19:08:00 +00:00
|
|
|
}
|
2015-07-16 17:42:56 +00:00
|
|
|
editMode = rememberEM;
|
2014-08-05 20:40:50 +00:00
|
|
|
ui.cylinders->view()->hideColumn(CylindersModel::DEPTH);
|
2015-01-10 23:01:15 +00:00
|
|
|
if (get_dive_dc(&displayed_dive, dc_number)->divemode == CCR)
|
2014-11-17 14:03:37 +00:00
|
|
|
ui.cylinders->view()->showColumn(CylindersModel::USE);
|
|
|
|
else
|
|
|
|
ui.cylinders->view()->hideColumn(CylindersModel::USE);
|
2015-06-04 01:44:16 +00:00
|
|
|
|
2018-10-31 10:17:26 +00:00
|
|
|
if (verbose && displayed_dive.dive_site)
|
2018-10-26 15:03:54 +00:00
|
|
|
qDebug() << "Set the current dive site:" << displayed_dive.dive_site->uuid;
|
2018-10-08 19:16:40 +00:00
|
|
|
emit diveSiteChanged();
|
2013-05-06 16:23:14 +00:00
|
|
|
}
|
|
|
|
|
2013-05-22 12:40:26 +00:00
|
|
|
void MainTab::addCylinder_clicked()
|
2013-04-13 13:17:59 +00:00
|
|
|
{
|
2014-01-16 04:50:56 +00:00
|
|
|
if (editMode == NONE)
|
2013-09-25 18:05:48 +00:00
|
|
|
enableEdition();
|
2013-05-22 17:52:38 +00:00
|
|
|
cylindersModel->add();
|
2013-04-13 13:17:59 +00:00
|
|
|
}
|
|
|
|
|
2013-05-22 12:40:26 +00:00
|
|
|
void MainTab::addWeight_clicked()
|
2013-05-01 21:30:34 +00:00
|
|
|
{
|
2014-01-16 04:50:56 +00:00
|
|
|
if (editMode == NONE)
|
2013-09-25 18:05:48 +00:00
|
|
|
enableEdition();
|
2013-05-22 17:52:38 +00:00
|
|
|
weightModel->add();
|
2013-05-01 21:30:34 +00:00
|
|
|
}
|
|
|
|
|
2013-04-13 13:17:59 +00:00
|
|
|
void MainTab::reload()
|
|
|
|
{
|
2014-02-11 17:46:14 +00:00
|
|
|
suitModel.updateModel();
|
|
|
|
buddyModel.updateModel();
|
|
|
|
diveMasterModel.updateModel();
|
|
|
|
tagModel.updateModel();
|
2015-07-01 22:31:35 +00:00
|
|
|
LocationInformationModel::instance()->update();
|
2013-04-07 22:20:43 +00:00
|
|
|
}
|
2013-05-18 23:42:59 +00:00
|
|
|
|
2014-05-07 20:00:33 +00:00
|
|
|
// tricky little macro to edit all the selected dives
|
2018-07-21 20:24:24 +00:00
|
|
|
// loop ove all DIVES and do WHAT.
|
|
|
|
#define MODIFY_DIVES(DIVES, WHAT) \
|
2014-05-07 20:00:33 +00:00
|
|
|
do { \
|
2018-07-21 20:24:24 +00:00
|
|
|
for (dive *mydive: DIVES) { \
|
2014-05-07 20:00:33 +00:00
|
|
|
WHAT; \
|
2018-07-21 20:24:24 +00:00
|
|
|
} \
|
2014-06-03 01:13:50 +00:00
|
|
|
mark_divelist_changed(true); \
|
2014-05-07 20:00:33 +00:00
|
|
|
} while (0)
|
|
|
|
|
2014-11-05 14:34:29 +00:00
|
|
|
#define EDIT_TEXT(what) \
|
|
|
|
if (same_string(mydive->what, cd->what) || copyPaste) { \
|
|
|
|
free(mydive->what); \
|
|
|
|
mydive->what = copy_string(displayed_dive.what); \
|
2014-05-07 20:00:33 +00:00
|
|
|
}
|
|
|
|
|
2015-08-26 00:08:05 +00:00
|
|
|
MainTab::EditMode MainTab::getEditMode() const
|
|
|
|
{
|
|
|
|
return editMode;
|
|
|
|
}
|
|
|
|
|
2014-11-05 14:34:29 +00:00
|
|
|
#define EDIT_VALUE(what) \
|
|
|
|
if (mydive->what == cd->what || copyPaste) { \
|
|
|
|
mydive->what = displayed_dive.what; \
|
2014-05-07 20:00:33 +00:00
|
|
|
}
|
|
|
|
|
2015-08-29 23:00:22 +00:00
|
|
|
void MainTab::refreshDisplayedDiveSite()
|
|
|
|
{
|
2018-10-12 07:25:00 +00:00
|
|
|
struct dive_site *ds = get_dive_site_for_dive(&displayed_dive);
|
2018-10-13 06:57:46 +00:00
|
|
|
if (ds)
|
2018-10-25 06:02:06 +00:00
|
|
|
ui.location->setCurrentDiveSite(ds);
|
2015-08-29 23:00:22 +00:00
|
|
|
}
|
|
|
|
|
2018-07-21 20:24:24 +00:00
|
|
|
// Get the list of selected dives, but put the current dive at the last position of the vector
|
|
|
|
static QVector<dive *> getSelectedDivesCurrentLast()
|
|
|
|
{
|
|
|
|
QVector<dive *> res;
|
|
|
|
struct dive *d;
|
|
|
|
int i;
|
|
|
|
for_each_dive (i, d) {
|
|
|
|
if (d->selected && d != current_dive)
|
|
|
|
res.append(d);
|
|
|
|
}
|
|
|
|
res.append(current_dive);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-02-10 16:37:06 +00:00
|
|
|
// When editing depth and duration, we only edit a single dive. Therefore, return the current dive as a list
|
|
|
|
static QVector<dive *> getCurrentAsList()
|
|
|
|
{
|
|
|
|
return current_dive ? QVector<dive *> { current_dive }
|
|
|
|
: QVector<dive *> { };
|
|
|
|
}
|
|
|
|
|
2013-09-19 00:56:53 +00:00
|
|
|
void MainTab::acceptChanges()
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2014-07-03 21:45:01 +00:00
|
|
|
int i, addedId = -1;
|
2014-06-03 01:13:50 +00:00
|
|
|
struct dive *d;
|
2014-11-03 17:47:24 +00:00
|
|
|
bool do_replot = false;
|
2015-01-04 18:06:33 +00:00
|
|
|
|
2019-02-05 07:01:04 +00:00
|
|
|
if (ui.location->hasFocus())
|
|
|
|
setFocus();
|
2015-07-13 18:38:46 +00:00
|
|
|
|
2015-01-04 18:06:33 +00:00
|
|
|
acceptingEdit = true;
|
2013-09-19 01:38:38 +00:00
|
|
|
tabBar()->setTabIcon(0, QIcon()); // Notes
|
|
|
|
tabBar()->setTabIcon(1, QIcon()); // Equipment
|
2014-08-23 14:49:28 +00:00
|
|
|
ui.dateEdit->setEnabled(true);
|
2013-12-03 20:44:48 +00:00
|
|
|
hideMessage();
|
2013-12-28 01:26:22 +00:00
|
|
|
ui.equipmentTab->setEnabled(true);
|
2014-07-03 21:45:01 +00:00
|
|
|
if (editMode == ADD) {
|
2019-03-03 16:10:09 +00:00
|
|
|
// Handle dive site
|
|
|
|
struct dive_site *pickedDs = ui.location->currDiveSite();
|
|
|
|
QString newDiveSiteName;
|
|
|
|
if (pickedDs == RECENTLY_ADDED_DIVESITE) {
|
|
|
|
newDiveSiteName = ui.location->text();
|
|
|
|
displayed_dive.dive_site = nullptr;
|
|
|
|
} else {
|
|
|
|
displayed_dive.dive_site = pickedDs;
|
|
|
|
}
|
|
|
|
|
2018-07-21 20:24:24 +00:00
|
|
|
copyTagsToDisplayedDive();
|
2015-07-13 18:14:46 +00:00
|
|
|
|
2019-03-03 16:10:09 +00:00
|
|
|
Command::addDive(&displayed_dive, newDiveSiteName, autogroup, true);
|
2018-07-19 20:35:25 +00:00
|
|
|
|
|
|
|
editMode = NONE;
|
|
|
|
MainWindow::instance()->exitEditState();
|
|
|
|
cylindersModel->changed = false;
|
|
|
|
weightModel->changed = false;
|
|
|
|
MainWindow::instance()->setEnabledToolbar(true);
|
|
|
|
acceptingEdit = false;
|
|
|
|
ui.editDiveSiteButton->setEnabled(!ui.location->text().isEmpty());
|
|
|
|
emit addDiveFinished();
|
|
|
|
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::NOTHING);
|
2018-10-12 14:13:42 +00:00
|
|
|
MainWindow::instance()->diveList->setFocus();
|
2018-07-19 20:35:25 +00:00
|
|
|
resetPallete();
|
|
|
|
displayed_dive.divetrip = nullptr; // Should not be necessary, just in case!
|
|
|
|
return;
|
2018-10-12 14:13:42 +00:00
|
|
|
} else if (MainWindow::instance() && MainWindow::instance()->diveList->selectedTrips().count() == 1) {
|
2014-07-03 21:45:01 +00:00
|
|
|
/* now figure out if things have changed */
|
2015-01-04 00:06:00 +00:00
|
|
|
if (displayedTrip.notes && !same_string(displayedTrip.notes, currentTrip->notes)) {
|
2014-11-11 19:41:47 +00:00
|
|
|
currentTrip->notes = copy_string(displayedTrip.notes);
|
2014-06-03 01:13:50 +00:00
|
|
|
mark_divelist_changed(true);
|
|
|
|
}
|
2015-01-04 00:06:00 +00:00
|
|
|
if (displayedTrip.location && !same_string(displayedTrip.location, currentTrip->location)) {
|
2014-11-11 19:41:47 +00:00
|
|
|
currentTrip->location = copy_string(displayedTrip.location);
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2014-06-03 01:13:50 +00:00
|
|
|
}
|
2014-07-30 15:52:11 +00:00
|
|
|
currentTrip = NULL;
|
2014-06-19 16:52:34 +00:00
|
|
|
ui.dateEdit->setEnabled(true);
|
2013-05-19 16:00:57 +00:00
|
|
|
} else {
|
2018-07-21 20:24:24 +00:00
|
|
|
// Get list of selected dives, but put the current dive last;
|
|
|
|
// this is required in case the invocation wants to compare things
|
|
|
|
// to the original value in current_dive like it should
|
|
|
|
QVector<dive *> selectedDives = getSelectedDivesCurrentLast();
|
2014-07-31 21:41:30 +00:00
|
|
|
if (editMode == MANUALLY_ADDED_DIVE) {
|
|
|
|
// preserve any changes to the profile
|
|
|
|
free(current_dive->dc.sample);
|
|
|
|
copy_samples(&displayed_dive.dc, ¤t_dive->dc);
|
2015-06-07 13:29:17 +00:00
|
|
|
addedId = displayed_dive.id;
|
2014-07-31 21:41:30 +00:00
|
|
|
}
|
2014-06-03 01:13:50 +00:00
|
|
|
// now check if something has changed and if yes, edit the selected dives that
|
|
|
|
// were identical with the master dive shown (and mark the divelist as changed)
|
2019-03-20 20:46:58 +00:00
|
|
|
struct dive *cd = current_dive;
|
2014-07-09 16:35:27 +00:00
|
|
|
|
2015-05-11 17:38:50 +00:00
|
|
|
// three text fields are somewhat special and are represented as tags
|
|
|
|
// in the UI - they need somewhat smarter handling
|
2018-07-21 20:24:24 +00:00
|
|
|
saveTaggedStrings(selectedDives);
|
2014-07-03 21:45:01 +00:00
|
|
|
|
2019-01-27 22:40:19 +00:00
|
|
|
if (cylindersModel->changed) {
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2018-07-21 20:24:24 +00:00
|
|
|
MODIFY_DIVES(selectedDives,
|
2013-09-25 17:59:11 +00:00
|
|
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
2014-06-03 01:13:50 +00:00
|
|
|
if (mydive != cd) {
|
2014-11-05 14:34:29 +00:00
|
|
|
if (same_string(mydive->cylinder[i].type.description, cd->cylinder[i].type.description) || copyPaste) {
|
|
|
|
// if we started out with the same cylinder description (for multi-edit) or if we do copt & paste
|
|
|
|
// make sure that we have the same cylinder type and copy the gasmix, but DON'T copy the start
|
|
|
|
// and end pressures (those are per dive after all)
|
2014-11-04 22:18:27 +00:00
|
|
|
if (!same_string(mydive->cylinder[i].type.description, displayed_dive.cylinder[i].type.description)) {
|
|
|
|
free((void*)mydive->cylinder[i].type.description);
|
|
|
|
mydive->cylinder[i].type.description = copy_string(displayed_dive.cylinder[i].type.description);
|
|
|
|
}
|
|
|
|
mydive->cylinder[i].type.size = displayed_dive.cylinder[i].type.size;
|
|
|
|
mydive->cylinder[i].type.workingpressure = displayed_dive.cylinder[i].type.workingpressure;
|
|
|
|
mydive->cylinder[i].gasmix = displayed_dive.cylinder[i].gasmix;
|
2014-11-17 10:45:14 +00:00
|
|
|
mydive->cylinder[i].cylinder_use = displayed_dive.cylinder[i].cylinder_use;
|
|
|
|
mydive->cylinder[i].depth = displayed_dive.cylinder[i].depth;
|
2014-11-04 22:18:27 +00:00
|
|
|
}
|
2014-06-03 01:13:50 +00:00
|
|
|
}
|
2013-09-25 17:57:41 +00:00
|
|
|
}
|
2014-06-03 01:13:50 +00:00
|
|
|
);
|
2014-11-04 22:18:27 +00:00
|
|
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
|
|
|
// copy the cylinder but make sure we have our own copy of the strings
|
|
|
|
free((void*)cd->cylinder[i].type.description);
|
2014-07-16 03:29:14 +00:00
|
|
|
cd->cylinder[i] = displayed_dive.cylinder[i];
|
2014-11-04 22:18:27 +00:00
|
|
|
cd->cylinder[i].type.description = copy_string(displayed_dive.cylinder[i].type.description);
|
|
|
|
}
|
2015-04-23 22:24:02 +00:00
|
|
|
/* if cylinders changed we may have changed gas change events
|
2017-11-27 15:59:58 +00:00
|
|
|
* and sensor idx in samples as well
|
2015-04-23 22:24:02 +00:00
|
|
|
* - so far this is ONLY supported for a single selected dive */
|
|
|
|
struct divecomputer *tdc = ¤t_dive->dc;
|
|
|
|
struct divecomputer *sdc = &displayed_dive.dc;
|
|
|
|
while(tdc && sdc) {
|
|
|
|
free_events(tdc->events);
|
|
|
|
copy_events(sdc, tdc);
|
2017-11-27 15:59:58 +00:00
|
|
|
free(tdc->sample);
|
|
|
|
copy_samples(sdc, tdc);
|
2015-04-23 22:24:02 +00:00
|
|
|
tdc = tdc->next;
|
|
|
|
sdc = sdc->next;
|
|
|
|
}
|
2014-11-03 17:47:24 +00:00
|
|
|
do_replot = true;
|
2013-09-25 17:57:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (weightModel->changed) {
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2018-07-21 20:24:24 +00:00
|
|
|
MODIFY_DIVES(selectedDives,
|
2013-10-01 13:52:23 +00:00
|
|
|
for (int i = 0; i < MAX_WEIGHTSYSTEMS; i++) {
|
2014-11-17 10:41:02 +00:00
|
|
|
if (mydive != cd && (copyPaste || same_string(mydive->weightsystem[i].description, cd->weightsystem[i].description))) {
|
2014-07-02 18:50:28 +00:00
|
|
|
mydive->weightsystem[i] = displayed_dive.weightsystem[i];
|
2014-11-17 10:41:02 +00:00
|
|
|
mydive->weightsystem[i].description = copy_string(displayed_dive.weightsystem[i].description);
|
|
|
|
}
|
2013-09-25 17:57:41 +00:00
|
|
|
}
|
2014-06-03 01:13:50 +00:00
|
|
|
);
|
2014-11-17 10:41:02 +00:00
|
|
|
for (int i = 0; i < MAX_WEIGHTSYSTEMS; i++) {
|
2014-07-16 03:29:14 +00:00
|
|
|
cd->weightsystem[i] = displayed_dive.weightsystem[i];
|
2014-11-17 10:41:02 +00:00
|
|
|
cd->weightsystem[i].description = copy_string(displayed_dive.weightsystem[i].description);
|
|
|
|
}
|
2014-06-03 01:13:50 +00:00
|
|
|
}
|
2015-07-13 18:14:46 +00:00
|
|
|
|
2014-06-03 01:13:50 +00:00
|
|
|
// 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
|
|
|
|
for_each_dive (i, d) {
|
2016-04-03 22:31:59 +00:00
|
|
|
if (d->selected) {
|
2014-06-03 01:13:50 +00:00
|
|
|
fixup_dive(d);
|
2016-04-03 22:31:59 +00:00
|
|
|
invalidate_dive_cache(d);
|
|
|
|
}
|
2013-09-25 17:57:41 +00:00
|
|
|
}
|
2013-05-19 14:45:01 +00:00
|
|
|
}
|
2018-07-19 20:35:25 +00:00
|
|
|
if (editMode == MANUALLY_ADDED_DIVE) {
|
2015-09-11 17:54:05 +00:00
|
|
|
// we just added or edited the dive, let fixup_dive() make
|
2017-03-06 12:27:39 +00:00
|
|
|
// sure we get the max. depth right
|
2015-09-11 17:54:05 +00:00
|
|
|
current_dive->maxdepth.mm = current_dc->maxdepth.mm = 0;
|
2013-09-19 04:33:39 +00:00
|
|
|
fixup_dive(current_dive);
|
2014-08-18 19:12:05 +00:00
|
|
|
set_dive_nr_for_current_dive();
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->showProfile();
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2013-11-09 00:09:46 +00:00
|
|
|
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::NOTHING);
|
2013-09-19 04:33:39 +00:00
|
|
|
}
|
2018-10-12 14:13:42 +00:00
|
|
|
int scrolledBy = MainWindow::instance()->diveList->verticalScrollBar()->sliderPosition();
|
2013-09-25 17:36:59 +00:00
|
|
|
resetPallete();
|
2018-07-19 20:35:25 +00:00
|
|
|
if (editMode == MANUALLY_ADDED_DIVE) {
|
2018-11-04 16:54:38 +00:00
|
|
|
MainWindow::instance()->diveList->reload();
|
2014-07-03 21:45:01 +00:00
|
|
|
int newDiveNr = get_divenr(get_dive_by_uniq_id(addedId));
|
2018-10-12 14:13:42 +00:00
|
|
|
MainWindow::instance()->diveList->unselectDives();
|
|
|
|
MainWindow::instance()->diveList->selectDive(newDiveNr, true);
|
2013-12-03 23:25:20 +00:00
|
|
|
editMode = NONE;
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->refreshDisplay();
|
2018-10-12 13:07:40 +00:00
|
|
|
MainWindow::instance()->graphics->replot();
|
2013-12-10 05:17:15 +00:00
|
|
|
} else {
|
2013-12-03 23:25:20 +00:00
|
|
|
editMode = NONE;
|
2014-11-03 17:47:24 +00:00
|
|
|
if (do_replot)
|
2018-10-12 13:07:40 +00:00
|
|
|
MainWindow::instance()->graphics->replot();
|
2018-10-12 14:13:42 +00:00
|
|
|
MainWindow::instance()->diveList->rememberSelection();
|
2014-08-07 17:23:08 +00:00
|
|
|
MainWindow::instance()->refreshDisplay();
|
2018-10-12 14:13:42 +00:00
|
|
|
MainWindow::instance()->diveList->restoreSelection();
|
2013-12-03 22:34:05 +00:00
|
|
|
}
|
2014-02-19 17:43:34 +00:00
|
|
|
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::NOTHING);
|
2018-10-12 14:13:42 +00:00
|
|
|
MainWindow::instance()->diveList->verticalScrollBar()->setSliderPosition(scrolledBy);
|
|
|
|
MainWindow::instance()->diveList->setFocus();
|
2018-05-03 17:19:54 +00:00
|
|
|
MainWindow::instance()->exitEditState();
|
2014-07-16 03:33:48 +00:00
|
|
|
cylindersModel->changed = false;
|
|
|
|
weightModel->changed = false;
|
2014-08-04 15:58:21 +00:00
|
|
|
MainWindow::instance()->setEnabledToolbar(true);
|
2015-01-04 18:06:33 +00:00
|
|
|
acceptingEdit = false;
|
2017-10-06 14:51:02 +00:00
|
|
|
ui.editDiveSiteButton->setEnabled(!ui.location->text().isEmpty());
|
2013-09-25 17:36:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::resetPallete()
|
|
|
|
{
|
2013-08-16 18:38:18 +00:00
|
|
|
QPalette p;
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.buddy->setPalette(p);
|
|
|
|
ui.notes->setPalette(p);
|
|
|
|
ui.location->setPalette(p);
|
|
|
|
ui.divemaster->setPalette(p);
|
|
|
|
ui.suit->setPalette(p);
|
|
|
|
ui.airtemp->setPalette(p);
|
2015-01-01 16:00:46 +00:00
|
|
|
ui.DiveType->setPalette(p);
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.watertemp->setPalette(p);
|
2014-06-19 16:52:34 +00:00
|
|
|
ui.dateEdit->setPalette(p);
|
2014-06-26 17:54:16 +00:00
|
|
|
ui.timeEdit->setPalette(p);
|
2013-11-02 01:20:02 +00:00
|
|
|
ui.tagWidget->setPalette(p);
|
2015-10-01 21:11:03 +00:00
|
|
|
ui.diveTripLocation->setPalette(p);
|
2017-02-26 04:06:47 +00:00
|
|
|
ui.duration->setPalette(p);
|
|
|
|
ui.depth->setPalette(p);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2013-09-19 00:56:53 +00:00
|
|
|
void MainTab::rejectChanges()
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2013-11-12 05:41:29 +00:00
|
|
|
EditMode lastMode = editMode;
|
2014-07-03 04:33:03 +00:00
|
|
|
|
|
|
|
if (lastMode != NONE && current_dive &&
|
|
|
|
(modified ||
|
|
|
|
memcmp(¤t_dive->cylinder[0], &displayed_dive.cylinder[0], sizeof(cylinder_t) * MAX_CYLINDERS) ||
|
2018-05-10 15:12:06 +00:00
|
|
|
memcmp(¤t_dive->weightsystem[0], &displayed_dive.weightsystem[0], sizeof(weightsystem_t) * MAX_WEIGHTSYSTEMS))) {
|
2014-07-11 08:21:38 +00:00
|
|
|
if (QMessageBox::warning(MainWindow::instance(), TITLE_OR_TEXT(tr("Discard the changes?"),
|
2014-06-04 01:01:00 +00:00
|
|
|
tr("You are about to discard your changes.")),
|
|
|
|
QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Discard) != QMessageBox::Discard) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2014-08-23 14:49:28 +00:00
|
|
|
ui.dateEdit->setEnabled(true);
|
2014-05-28 03:31:18 +00:00
|
|
|
editMode = NONE;
|
2013-09-19 01:38:38 +00:00
|
|
|
tabBar()->setTabIcon(0, QIcon()); // Notes
|
|
|
|
tabBar()->setTabIcon(1, QIcon()); // Equipment
|
2013-12-03 20:44:48 +00:00
|
|
|
hideMessage();
|
2013-09-25 17:36:59 +00:00
|
|
|
resetPallete();
|
2014-07-06 19:36:25 +00:00
|
|
|
// no harm done to call cancelPlan even if we were not in ADD or PLAN mode...
|
|
|
|
DivePlannerPointsModel::instance()->cancelPlan();
|
2014-07-16 22:44:06 +00:00
|
|
|
if(lastMode == ADD)
|
2018-10-12 14:13:42 +00:00
|
|
|
MainWindow::instance()->diveList->restoreSelection();
|
2014-07-06 19:36:25 +00:00
|
|
|
|
|
|
|
// now make sure that the correct dive is displayed
|
Undo: select dives after add, remove, merge, split dive commands
Select the proper dives after the add, remove, split and merge
dives commands on undo *and* redo. Generally, select the added
dives. For undo of add, remember the pre-addition selection.
For redo of remove, select the closest dive to the first removed
dive.
The biggest part of the commit is the signal-interface between
the dive commands and the dive-list model and dive-list view.
This is done in two steps:
1) To the DiveTripModel in batches of trips. The dive trip model
transforms the dives into indices.
2) To the DiveListView. The DiveListView has to translate the
DiveTripModel indexes to actual indexes via its QSortFilterProxy-
model.
For code-reuse, derive all divelist-changing commands from a new base-class,
which has a flag that describes whether the divelist changed. The helper
functions which add and remove dives are made members of the base class and
set the flag is a selected dive is added or removed.
To properly detect when the current dive was deleted it
became necessary to turn the current dive from an index
to a pointer, because indices are not stable.
Unfortunately, in some cases an index was expected and these
places now have to transform the dive into an index. These
should be converted in due course.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-03 09:35:43 +00:00
|
|
|
if (current_dive)
|
2014-07-06 19:36:25 +00:00
|
|
|
copy_dive(current_dive, &displayed_dive);
|
|
|
|
else
|
|
|
|
clear_dive(&displayed_dive);
|
Undo: select dives after add, remove, merge, split dive commands
Select the proper dives after the add, remove, split and merge
dives commands on undo *and* redo. Generally, select the added
dives. For undo of add, remember the pre-addition selection.
For redo of remove, select the closest dive to the first removed
dive.
The biggest part of the commit is the signal-interface between
the dive commands and the dive-list model and dive-list view.
This is done in two steps:
1) To the DiveTripModel in batches of trips. The dive trip model
transforms the dives into indices.
2) To the DiveListView. The DiveListView has to translate the
DiveTripModel indexes to actual indexes via its QSortFilterProxy-
model.
For code-reuse, derive all divelist-changing commands from a new base-class,
which has a flag that describes whether the divelist changed. The helper
functions which add and remove dives are made members of the base class and
set the flag is a selected dive is added or removed.
To properly detect when the current dive was deleted it
became necessary to turn the current dive from an index
to a pointer, because indices are not stable.
Unfortunately, in some cases an index was expected and these
places now have to transform the dive into an index. These
should be converted in due course.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-03 09:35:43 +00:00
|
|
|
updateDiveInfo(!current_dive);
|
2017-04-04 17:21:30 +00:00
|
|
|
|
|
|
|
for (auto widget : extraWidgets) {
|
|
|
|
widget->updateData();
|
|
|
|
}
|
2014-05-02 04:26:18 +00:00
|
|
|
// the user could have edited the location and then canceled the edit
|
|
|
|
// let's get the correct location back in view
|
2018-10-26 15:03:54 +00:00
|
|
|
MapWidget::instance()->centerOnDiveSite(displayed_dive.dive_site);
|
2014-07-06 19:36:25 +00:00
|
|
|
// show the profile and dive info
|
2018-10-12 13:07:40 +00:00
|
|
|
MainWindow::instance()->graphics->replot();
|
2014-08-04 15:58:21 +00:00
|
|
|
MainWindow::instance()->setEnabledToolbar(true);
|
2018-05-03 17:19:54 +00:00
|
|
|
MainWindow::instance()->exitEditState();
|
2014-07-16 03:33:48 +00:00
|
|
|
cylindersModel->changed = false;
|
|
|
|
weightModel->changed = false;
|
2014-07-06 19:36:25 +00:00
|
|
|
cylindersModel->updateDive();
|
|
|
|
weightModel->updateDive();
|
2017-10-06 14:51:02 +00:00
|
|
|
ui.editDiveSiteButton->setEnabled(!ui.location->text().isEmpty());
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
2013-08-16 18:52:40 +00:00
|
|
|
|
2014-07-03 04:33:03 +00:00
|
|
|
void MainTab::markChangedWidget(QWidget *w)
|
2014-02-28 04:09:57 +00:00
|
|
|
{
|
2013-08-16 18:38:18 +00:00
|
|
|
QPalette p;
|
2013-12-24 11:49:38 +00:00
|
|
|
qreal h, s, l, a;
|
2014-07-03 05:15:08 +00:00
|
|
|
enableEdition();
|
2013-12-24 11:49:38 +00:00
|
|
|
qApp->palette().color(QPalette::Text).getHslF(&h, &s, &l, &a);
|
2014-02-28 04:09:57 +00:00
|
|
|
p.setBrush(QPalette::Base, (l <= 0.3) ? QColor(Qt::yellow).lighter() : (l <= 0.6) ? QColor(Qt::yellow).light() : /* else */ QColor(Qt::yellow).darker(300));
|
2013-08-16 18:52:40 +00:00
|
|
|
w->setPalette(p);
|
2015-03-09 18:12:48 +00:00
|
|
|
modified = true;
|
2013-08-16 18:52:40 +00:00
|
|
|
}
|
2013-05-18 23:42:59 +00:00
|
|
|
|
2019-02-07 20:00:09 +00:00
|
|
|
static QStringList stringToList(const QString &s)
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2019-02-07 20:00:09 +00:00
|
|
|
QStringList res = s.split(",", QString::SkipEmptyParts);
|
|
|
|
for (QString &str: res)
|
|
|
|
str = str.trimmed();
|
|
|
|
return res;
|
|
|
|
}
|
2015-02-01 19:25:27 +00:00
|
|
|
|
2019-02-07 20:00:09 +00:00
|
|
|
void MainTab::on_buddy_editingFinished()
|
|
|
|
{
|
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2015-02-01 19:25:27 +00:00
|
|
|
return;
|
|
|
|
|
2019-02-07 20:00:09 +00:00
|
|
|
Command::editBuddies(getSelectedDivesCurrentLast(), stringToList(ui.buddy->toPlainText()), current_dive);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2019-02-07 20:23:00 +00:00
|
|
|
void MainTab::on_divemaster_editingFinished()
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2019-02-07 20:23:00 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2015-02-01 19:25:27 +00:00
|
|
|
return;
|
|
|
|
|
2019-02-07 20:23:00 +00:00
|
|
|
Command::editDiveMaster(getSelectedDivesCurrentLast(), stringToList(ui.divemaster->toPlainText()), current_dive);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2019-02-10 16:37:06 +00:00
|
|
|
void MainTab::on_duration_editingFinished()
|
2017-02-04 21:59:20 +00:00
|
|
|
{
|
2019-02-10 16:37:06 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2017-02-04 21:59:20 +00:00
|
|
|
return;
|
2017-02-26 05:00:09 +00:00
|
|
|
|
2019-02-10 16:37:06 +00:00
|
|
|
// Duration editing is special: we only edit the current dive.
|
|
|
|
Command::editDuration(getCurrentAsList(), parseDurationToSeconds(ui.duration->text()), displayed_dive.dc.duration.seconds);
|
2017-02-04 21:59:20 +00:00
|
|
|
}
|
|
|
|
|
2019-02-10 16:37:06 +00:00
|
|
|
void MainTab::on_depth_editingFinished()
|
2017-02-04 21:59:20 +00:00
|
|
|
{
|
2019-02-10 16:37:06 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2017-02-04 21:59:20 +00:00
|
|
|
return;
|
2019-02-10 16:37:06 +00:00
|
|
|
|
|
|
|
// Depth editing is special: we only edit the current dive.
|
|
|
|
Command::editDepth(getCurrentAsList(), parseLengthToMm(ui.depth->text()), current_dive->dc.maxdepth.mm);
|
2017-02-04 21:59:20 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 21:13:24 +00:00
|
|
|
void MainTab::on_airtemp_editingFinished()
|
2013-09-20 23:41:42 +00:00
|
|
|
{
|
2019-01-30 21:13:24 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2019-01-30 21:13:24 +00:00
|
|
|
Command::editAirTemp(getSelectedDivesCurrentLast(),
|
|
|
|
parseTemperatureToMkelvin(ui.airtemp->text()), current_dive->airtemp.mkelvin);
|
2013-09-20 23:41:42 +00:00
|
|
|
}
|
|
|
|
|
2015-01-08 13:42:07 +00:00
|
|
|
void MainTab::divetype_Changed(int index)
|
2015-01-01 16:00:46 +00:00
|
|
|
{
|
2019-01-28 17:35:27 +00:00
|
|
|
if (editMode == IGNORE || !current_dive)
|
2015-01-01 16:00:46 +00:00
|
|
|
return;
|
2019-01-28 17:35:27 +00:00
|
|
|
Command::editMode(getSelectedDivesCurrentLast(), dc_number, (enum divemode_t)index,
|
|
|
|
get_dive_dc(current_dive, dc_number)->divemode);
|
2015-01-01 16:00:46 +00:00
|
|
|
}
|
|
|
|
|
2019-01-30 21:13:24 +00:00
|
|
|
void MainTab::on_watertemp_editingFinished()
|
2013-09-20 23:41:42 +00:00
|
|
|
{
|
2019-01-30 21:13:24 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2019-01-30 21:13:24 +00:00
|
|
|
Command::editWaterTemp(getSelectedDivesCurrentLast(),
|
|
|
|
parseTemperatureToMkelvin(ui.watertemp->text()),
|
|
|
|
current_dive->watertemp.mkelvin);
|
2014-04-13 16:19:15 +00:00
|
|
|
}
|
2014-05-06 20:56:46 +00:00
|
|
|
|
2019-03-19 21:05:52 +00:00
|
|
|
// Editing of the dive time is different. If multiple dives are edited,
|
|
|
|
// all dives are shifted by an offset.
|
|
|
|
static void shiftTime(QDateTime &dateTime)
|
|
|
|
{
|
|
|
|
timestamp_t when = dateTime.toTime_t();
|
|
|
|
if (current_dive && current_dive->when != when) {
|
|
|
|
timestamp_t offset = current_dive->when - when;
|
|
|
|
Command::shiftTime(getSelectedDivesCurrentLast(), (int)offset);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-26 17:57:25 +00:00
|
|
|
void MainTab::on_dateEdit_dateChanged(const QDate &date)
|
2013-09-20 23:41:42 +00:00
|
|
|
{
|
2019-03-19 21:05:52 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2019-03-19 21:05:52 +00:00
|
|
|
QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(1000*current_dive->when, Qt::UTC);
|
2014-06-26 17:57:25 +00:00
|
|
|
dateTime.setTimeSpec(Qt::UTC);
|
|
|
|
dateTime.setDate(date);
|
2019-03-19 21:05:52 +00:00
|
|
|
shiftTime(dateTime);
|
2013-09-20 23:41:42 +00:00
|
|
|
}
|
|
|
|
|
2014-06-26 17:54:16 +00:00
|
|
|
void MainTab::on_timeEdit_timeChanged(const QTime &time)
|
|
|
|
{
|
2019-03-19 21:05:52 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2014-06-26 17:54:16 +00:00
|
|
|
return;
|
2019-03-19 21:05:52 +00:00
|
|
|
QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(1000*current_dive->when, Qt::UTC);
|
2014-06-26 17:57:25 +00:00
|
|
|
dateTime.setTimeSpec(Qt::UTC);
|
2014-06-26 17:54:16 +00:00
|
|
|
dateTime.setTime(time);
|
2019-03-19 21:05:52 +00:00
|
|
|
shiftTime(dateTime);
|
2014-06-26 17:54:16 +00:00
|
|
|
}
|
|
|
|
|
2018-07-21 20:24:24 +00:00
|
|
|
void MainTab::copyTagsToDisplayedDive()
|
|
|
|
{
|
|
|
|
taglist_free(displayed_dive.tag_list);
|
|
|
|
displayed_dive.tag_list = NULL;
|
2019-02-07 18:59:34 +00:00
|
|
|
Q_FOREACH (const QString &tag, ui.tagWidget->getBlockStringList())
|
2018-07-21 20:24:24 +00:00
|
|
|
taglist_add_tag(&displayed_dive.tag_list, qPrintable(tag));
|
|
|
|
taglist_cleanup(&displayed_dive.tag_list);
|
|
|
|
}
|
|
|
|
|
2015-05-11 17:38:50 +00:00
|
|
|
// buddy and divemaster are represented in the UI just like the tags, but the internal
|
|
|
|
// representation is just a string (with commas as delimiters). So we need to do the same
|
|
|
|
// thing we did for tags, just differently
|
2018-07-21 20:24:24 +00:00
|
|
|
void MainTab::saveTaggedStrings(const QVector<dive *> &selectedDives)
|
2015-05-11 17:38:50 +00:00
|
|
|
{
|
|
|
|
QStringList addedList, removedList;
|
|
|
|
struct dive *cd = current_dive;
|
|
|
|
|
2018-10-10 12:07:47 +00:00
|
|
|
if (diffTaggedStrings(cd->buddy, displayed_dive.buddy, addedList, removedList))
|
2018-10-12 07:05:16 +00:00
|
|
|
MODIFY_DIVES(selectedDives,
|
|
|
|
QStringList oldList = QString(mydive->buddy).split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts);
|
|
|
|
QString newString;
|
|
|
|
QString comma;
|
|
|
|
Q_FOREACH (const QString tag, oldList) {
|
|
|
|
if (!removedList.contains(tag, Qt::CaseInsensitive)) {
|
|
|
|
newString += comma + tag;
|
|
|
|
comma = ", ";
|
|
|
|
}
|
2015-05-11 17:38:50 +00:00
|
|
|
}
|
2018-10-12 07:05:16 +00:00
|
|
|
Q_FOREACH (const QString tag, addedList) {
|
|
|
|
if (!oldList.contains(tag, Qt::CaseInsensitive)) {
|
|
|
|
newString += comma + tag;
|
|
|
|
comma = ", ";
|
|
|
|
}
|
2015-05-11 17:38:50 +00:00
|
|
|
}
|
2018-10-12 07:05:16 +00:00
|
|
|
free(mydive->buddy);
|
|
|
|
mydive->buddy = copy_qstring(newString);
|
|
|
|
);
|
2015-05-11 17:38:50 +00:00
|
|
|
addedList.clear();
|
|
|
|
removedList.clear();
|
2018-10-10 12:07:47 +00:00
|
|
|
if (diffTaggedStrings(cd->divemaster, displayed_dive.divemaster, addedList, removedList))
|
2018-10-12 07:05:16 +00:00
|
|
|
MODIFY_DIVES(selectedDives,
|
|
|
|
QStringList oldList = QString(mydive->divemaster).split(QRegExp("\\s*,\\s*"), QString::SkipEmptyParts);
|
|
|
|
QString newString;
|
|
|
|
QString comma;
|
|
|
|
Q_FOREACH (const QString tag, oldList) {
|
|
|
|
if (!removedList.contains(tag, Qt::CaseInsensitive)) {
|
|
|
|
newString += comma + tag;
|
|
|
|
comma = ", ";
|
|
|
|
}
|
2015-05-11 17:38:50 +00:00
|
|
|
}
|
2018-10-12 07:05:16 +00:00
|
|
|
Q_FOREACH (const QString tag, addedList) {
|
|
|
|
if (!oldList.contains(tag, Qt::CaseInsensitive)) {
|
|
|
|
newString += comma + tag;
|
|
|
|
comma = ", ";
|
|
|
|
}
|
2015-05-11 17:38:50 +00:00
|
|
|
}
|
2018-10-12 07:05:16 +00:00
|
|
|
free(mydive->divemaster);
|
|
|
|
mydive->divemaster = copy_qstring(newString);
|
|
|
|
);
|
2015-05-11 17:38:50 +00:00
|
|
|
}
|
|
|
|
|
2018-10-10 12:07:47 +00:00
|
|
|
int MainTab::diffTaggedStrings(QString currentString, QString displayedString, QStringList &addedList, QStringList &removedList)
|
2015-05-11 17:38:50 +00:00
|
|
|
{
|
2019-04-01 20:15:19 +00:00
|
|
|
const QStringList currentList = currentString.split(',', QString::SkipEmptyParts);
|
|
|
|
const QStringList displayedList = displayedString.split(',', QString::SkipEmptyParts);
|
|
|
|
for (const QString &tag: currentList) {
|
2015-05-11 17:38:50 +00:00
|
|
|
if (!displayedList.contains(tag, Qt::CaseInsensitive))
|
|
|
|
removedList << tag.trimmed();
|
|
|
|
}
|
2019-04-01 20:15:19 +00:00
|
|
|
for (const QString &tag: displayedList) {
|
2015-05-11 17:38:50 +00:00
|
|
|
if (!currentList.contains(tag, Qt::CaseInsensitive))
|
|
|
|
addedList << tag.trimmed();
|
|
|
|
}
|
2018-10-10 12:07:47 +00:00
|
|
|
return removedList.length() + addedList.length();
|
2015-05-11 17:38:50 +00:00
|
|
|
}
|
|
|
|
|
2019-02-07 18:59:34 +00:00
|
|
|
void MainTab::on_tagWidget_editingFinished()
|
2013-11-02 01:20:02 +00:00
|
|
|
{
|
2019-02-07 18:59:34 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2015-02-01 19:25:27 +00:00
|
|
|
return;
|
|
|
|
|
2019-02-07 18:59:34 +00:00
|
|
|
Command::editTags(getSelectedDivesCurrentLast(), ui.tagWidget->getBlockStringList(), current_dive);
|
2013-11-02 01:20:02 +00:00
|
|
|
}
|
|
|
|
|
2015-09-23 17:46:29 +00:00
|
|
|
void MainTab::on_location_diveSiteSelected()
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2019-03-20 20:46:58 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2014-05-07 21:51:39 +00:00
|
|
|
return;
|
2015-06-04 01:32:13 +00:00
|
|
|
|
2019-03-20 20:46:58 +00:00
|
|
|
struct dive_site *newDs = ui.location->currDiveSite();
|
|
|
|
if (newDs == RECENTLY_ADDED_DIVESITE)
|
|
|
|
Command::editDiveSiteNew(getSelectedDivesCurrentLast(), ui.location->text(), current_dive->dive_site);
|
|
|
|
else
|
|
|
|
Command::editDiveSite(getSelectedDivesCurrentLast(), newDs, current_dive->dive_site);
|
2015-10-01 20:52:00 +00:00
|
|
|
}
|
|
|
|
|
2015-10-01 21:11:03 +00:00
|
|
|
void MainTab::on_diveTripLocation_textEdited(const QString& text)
|
2015-10-01 20:52:00 +00:00
|
|
|
{
|
2014-07-30 15:52:11 +00:00
|
|
|
if (currentTrip) {
|
|
|
|
free(displayedTrip.location);
|
2018-02-28 22:37:09 +00:00
|
|
|
displayedTrip.location = copy_qstring(text);
|
2015-10-01 20:52:00 +00:00
|
|
|
markChangedWidget(ui.diveTripLocation);
|
2015-06-25 17:24:22 +00:00
|
|
|
}
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2019-01-28 20:42:59 +00:00
|
|
|
void MainTab::on_suit_editingFinished()
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2019-01-28 20:42:59 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true || !current_dive)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2019-01-28 20:42:59 +00:00
|
|
|
|
|
|
|
Command::editSuit(getSelectedDivesCurrentLast(), ui.suit->text(), QString(current_dive->suit));
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::on_notes_textChanged()
|
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2013-08-16 16:31:52 +00:00
|
|
|
return;
|
2014-07-30 15:52:11 +00:00
|
|
|
if (currentTrip) {
|
2018-02-25 12:51:41 +00:00
|
|
|
if (same_string(displayedTrip.notes, qPrintable(ui.notes->toPlainText())))
|
2015-01-30 20:27:16 +00:00
|
|
|
return;
|
2014-07-30 15:52:11 +00:00
|
|
|
free(displayedTrip.notes);
|
2018-02-28 22:37:09 +00:00
|
|
|
displayedTrip.notes = copy_qstring(ui.notes->toPlainText());
|
2019-01-25 17:27:31 +00:00
|
|
|
markChangedWidget(ui.notes);
|
2014-07-30 15:52:11 +00:00
|
|
|
}
|
2019-01-25 17:27:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::on_notes_editingFinished()
|
|
|
|
{
|
|
|
|
if (currentTrip || !current_dive)
|
|
|
|
return; // Trip-note editing is done via on_notes_textChanged()
|
|
|
|
|
|
|
|
QString notes = ui.notes->toHtml().indexOf("<div") != -1 ?
|
|
|
|
ui.notes->toHtml() : ui.notes->toPlainText();
|
|
|
|
|
|
|
|
Command::editNotes(getSelectedDivesCurrentLast(), notes, QString(current_dive->notes));
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::on_rating_valueChanged(int value)
|
|
|
|
{
|
2019-01-28 21:35:07 +00:00
|
|
|
if (acceptingEdit == true || !current_dive)
|
2015-01-04 18:06:33 +00:00
|
|
|
return;
|
2019-01-28 21:35:07 +00:00
|
|
|
|
|
|
|
Command::editRating(getSelectedDivesCurrentLast(), value, current_dive->rating);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
2013-05-20 13:25:16 +00:00
|
|
|
|
|
|
|
void MainTab::on_visibility_valueChanged(int value)
|
|
|
|
{
|
2019-01-28 21:35:07 +00:00
|
|
|
if (acceptingEdit == true || !current_dive)
|
2015-01-04 18:06:33 +00:00
|
|
|
return;
|
2019-01-28 21:35:07 +00:00
|
|
|
|
|
|
|
Command::editVisibility(getSelectedDivesCurrentLast(), value, current_dive->visibility);
|
2013-05-20 13:25:16 +00:00
|
|
|
}
|
2013-06-16 17:36:23 +00:00
|
|
|
|
2018-07-21 20:24:24 +00:00
|
|
|
#undef MODIFY_DIVES
|
2014-05-06 20:56:46 +00:00
|
|
|
#undef EDIT_TEXT
|
|
|
|
#undef EDIT_VALUE
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::editCylinderWidget(const QModelIndex &index)
|
2013-07-17 15:13:04 +00:00
|
|
|
{
|
2014-07-01 17:18:21 +00:00
|
|
|
// we need a local copy or bad things happen when enableEdition() is called
|
|
|
|
QModelIndex editIndex = index;
|
2014-03-15 22:14:59 +00:00
|
|
|
if (cylindersModel->changed && editMode == NONE) {
|
2013-09-25 17:11:38 +00:00
|
|
|
enableEdition();
|
2014-03-15 22:14:59 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-07-01 17:18:21 +00:00
|
|
|
if (editIndex.isValid() && editIndex.column() != CylindersModel::REMOVE) {
|
2014-03-15 22:14:59 +00:00
|
|
|
if (editMode == NONE)
|
|
|
|
enableEdition();
|
2014-07-01 17:18:21 +00:00
|
|
|
ui.cylinders->edit(editIndex);
|
2014-03-15 22:14:59 +00:00
|
|
|
}
|
2013-07-17 15:13:04 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::editWeightWidget(const QModelIndex &index)
|
2013-07-17 15:13:04 +00:00
|
|
|
{
|
2013-09-25 17:11:38 +00:00
|
|
|
if (editMode == NONE)
|
|
|
|
enableEdition();
|
|
|
|
|
2013-09-02 19:21:08 +00:00
|
|
|
if (index.isValid() && index.column() != WeightModel::REMOVE)
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.weights->edit(index);
|
2013-06-16 17:36:23 +00:00
|
|
|
}
|
2013-10-07 18:48:14 +00:00
|
|
|
|
2014-06-03 22:29:28 +00:00
|
|
|
void MainTab::escDetected()
|
|
|
|
{
|
2019-02-05 07:01:04 +00:00
|
|
|
// In edit mode, pressing escape cancels the current changes.
|
|
|
|
// In standard mode, remove focus of any active widget to
|
2014-06-03 22:29:28 +00:00
|
|
|
if (editMode != NONE)
|
|
|
|
rejectChanges();
|
2019-02-05 07:01:04 +00:00
|
|
|
else
|
|
|
|
setFocus();
|
2014-06-03 22:29:28 +00:00
|
|
|
}
|
2014-06-27 12:17:33 +00:00
|
|
|
|
2017-04-04 17:21:30 +00:00
|
|
|
void MainTab::clearTabs() {
|
|
|
|
for (auto widget : extraWidgets) {
|
|
|
|
widget->clear();
|
2015-10-20 19:08:59 +00:00
|
|
|
}
|
2017-04-04 17:21:30 +00:00
|
|
|
clearEquipment();
|
2015-10-20 20:36:59 +00:00
|
|
|
}
|
|
|
|
|
2014-08-17 14:26:09 +00:00
|
|
|
#define SHOW_SELECTIVE(_component) \
|
|
|
|
if (what._component) \
|
|
|
|
ui._component->setText(displayed_dive._component);
|
|
|
|
|
|
|
|
void MainTab::showAndTriggerEditSelective(struct dive_components what)
|
|
|
|
{
|
|
|
|
// take the data in our copyPasteDive and apply it to selected dives
|
|
|
|
enableEdition();
|
2014-11-05 14:34:29 +00:00
|
|
|
copyPaste = true;
|
2014-08-17 14:26:09 +00:00
|
|
|
SHOW_SELECTIVE(buddy);
|
|
|
|
SHOW_SELECTIVE(divemaster);
|
|
|
|
SHOW_SELECTIVE(suit);
|
|
|
|
if (what.notes) {
|
|
|
|
QString tmp(displayed_dive.notes);
|
2018-09-09 20:49:57 +00:00
|
|
|
if (tmp.contains("<div")) {
|
2017-11-28 17:10:37 +00:00
|
|
|
tmp.replace(QString("\n"), QString("<br>"));
|
2014-08-17 14:26:09 +00:00
|
|
|
ui.notes->setHtml(tmp);
|
2017-11-28 17:10:37 +00:00
|
|
|
} else {
|
2014-08-17 14:26:09 +00:00
|
|
|
ui.notes->setPlainText(tmp);
|
2017-11-28 17:10:37 +00:00
|
|
|
}
|
2014-08-17 14:26:09 +00:00
|
|
|
}
|
|
|
|
if (what.rating)
|
|
|
|
ui.rating->setCurrentStars(displayed_dive.rating);
|
|
|
|
if (what.visibility)
|
|
|
|
ui.visibility->setCurrentStars(displayed_dive.visibility);
|
2015-02-13 04:58:03 +00:00
|
|
|
if (what.divesite)
|
2018-10-26 15:03:54 +00:00
|
|
|
ui.location->setCurrentDiveSite(displayed_dive.dive_site);
|
2014-08-17 14:26:09 +00:00
|
|
|
if (what.tags) {
|
2018-04-09 08:09:34 +00:00
|
|
|
ui.tagWidget->setText(get_taglist_string(displayed_dive.tag_list));
|
2014-08-17 14:26:09 +00:00
|
|
|
}
|
|
|
|
if (what.cylinders) {
|
|
|
|
cylindersModel->updateDive();
|
|
|
|
cylindersModel->changed = true;
|
|
|
|
}
|
|
|
|
if (what.weights) {
|
|
|
|
weightModel->updateDive();
|
|
|
|
weightModel->changed = true;
|
|
|
|
}
|
|
|
|
}
|