2013-04-14 03:44:02 +00:00
|
|
|
/*
|
|
|
|
* maintab.cpp
|
|
|
|
*
|
|
|
|
* classes for the "notebook" area of the main window of Subsurface
|
|
|
|
*
|
|
|
|
*/
|
2013-04-07 22:20:43 +00:00
|
|
|
#include "maintab.h"
|
2013-05-19 03:09:36 +00:00
|
|
|
#include "mainwindow.h"
|
2015-01-17 09:43:52 +00:00
|
|
|
#include "helpers.h"
|
|
|
|
#include "statistics.h"
|
2013-05-22 17:11:49 +00:00
|
|
|
#include "modeldelegates.h"
|
2015-01-16 19:43:49 +00:00
|
|
|
|
|
|
|
#if defined(FBSUPPORT)
|
2014-12-28 22:24:02 +00:00
|
|
|
#include "socialnetworks.h"
|
2015-01-16 19:43:49 +00:00
|
|
|
#endif
|
2013-04-13 13:17:59 +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>
|
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)),
|
|
|
|
cylindersModel(CylindersModel::instance()),
|
2014-11-06 19:24:38 +00:00
|
|
|
extraDataModel(new ExtraDataModel(this)),
|
2014-06-02 22:50:42 +00:00
|
|
|
editMode(NONE),
|
2014-07-30 15:52:11 +00:00
|
|
|
divePictureModel(DivePictureModel::instance()),
|
2014-11-08 13:11:06 +00:00
|
|
|
copyPaste(false),
|
|
|
|
currentTrip(0)
|
2013-04-07 22:20:43 +00:00
|
|
|
{
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.setupUi(this);
|
2014-07-16 16:35:22 +00:00
|
|
|
ui.dateEdit->setDisplayFormat(getDateFormat());
|
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
|
|
|
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.cylinders->setModel(cylindersModel);
|
|
|
|
ui.weights->setModel(weightModel);
|
2014-06-02 22:50:42 +00:00
|
|
|
ui.photosView->setModel(divePictureModel);
|
2014-06-27 12:17:33 +00:00
|
|
|
connect(ui.photosView, SIGNAL(photoDoubleClicked(QString)), this, SLOT(photoDoubleClicked(QString)));
|
2014-11-06 19:24:38 +00:00
|
|
|
ui.extraData->setModel(extraDataModel);
|
2013-12-03 20:44:48 +00:00
|
|
|
closeMessage();
|
2013-09-26 20:02:27 +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()));
|
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-12-03 20:44:48 +00:00
|
|
|
addMessageAction(action);
|
2013-12-02 17:33:00 +00:00
|
|
|
|
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.location->installEventFilter(this);
|
|
|
|
ui.coordinates->installEventFilter(this);
|
|
|
|
ui.divemaster->installEventFilter(this);
|
|
|
|
ui.buddy->installEventFilter(this);
|
|
|
|
ui.suit->installEventFilter(this);
|
|
|
|
ui.notes->viewport()->installEventFilter(this);
|
|
|
|
ui.rating->installEventFilter(this);
|
|
|
|
ui.visibility->installEventFilter(this);
|
|
|
|
ui.airtemp->installEventFilter(this);
|
|
|
|
ui.watertemp->installEventFilter(this);
|
2014-06-19 16:52:34 +00:00
|
|
|
ui.dateEdit->installEventFilter(this);
|
2014-06-26 17:54:16 +00:00
|
|
|
ui.timeEdit->installEventFilter(this);
|
2013-11-02 01:20:02 +00:00
|
|
|
ui.tagWidget->installEventFilter(this);
|
2015-01-01 16:00:46 +00:00
|
|
|
ui.DiveType->installEventFilter(this);
|
2013-10-03 18:54:25 +00:00
|
|
|
|
2014-07-15 17:43:20 +00:00
|
|
|
Q_FOREACH (QObject *obj, ui.statisticsTab->children()) {
|
2014-02-28 04:09:57 +00:00
|
|
|
QLabel *label = qobject_cast<QLabel *>(obj);
|
2013-05-10 22:56:05 +00:00
|
|
|
if (label)
|
|
|
|
label->setAlignment(Qt::AlignHCenter);
|
|
|
|
}
|
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!
|
|
|
|
ui.DiveType->insertItems(0, QStringList() << "OC" << "CCR" << "pSCR" << "Freedive");
|
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.location = new QCompleter(&locationModel, ui.location);
|
|
|
|
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.location->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.location->setCompleter(completers.location);
|
|
|
|
ui.suit->setCompleter(completers.suit);
|
2013-11-02 01:20:02 +00:00
|
|
|
ui.tagWidget->setCompleter(completers.tags);
|
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);
|
|
|
|
ui.scrollArea_3->viewport()->setPalette(p);
|
|
|
|
ui.scrollArea_4->viewport()->setPalette(p);
|
2013-12-04 20:24:37 +00:00
|
|
|
|
|
|
|
// GroupBoxes in Gnome3 looks like I'v drawn them...
|
|
|
|
static const QString gnomeCss(
|
|
|
|
"QGroupBox {"
|
|
|
|
" 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;"
|
|
|
|
"}"
|
|
|
|
"QGroupBox::title {"
|
|
|
|
" subcontrol-origin: margin;"
|
|
|
|
" subcontrol-position: top center;"
|
|
|
|
" padding: 0 3px;"
|
|
|
|
" background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,"
|
2013-12-07 16:13:55 +00:00
|
|
|
" 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);
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
QAction *deletePhoto = new QAction(this);
|
|
|
|
deletePhoto->setShortcut(Qt::Key_Delete);
|
|
|
|
deletePhoto->setShortcutContext(Qt::WidgetShortcut);
|
|
|
|
ui.photosView->addAction(deletePhoto);
|
|
|
|
ui.photosView->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
connect(deletePhoto, SIGNAL(triggered(bool)), this, SLOT(removeSelectedPhotos()));
|
2014-12-28 22:24:02 +00:00
|
|
|
|
2015-01-16 19:43:49 +00:00
|
|
|
#if defined(FBSUPPORT)
|
2014-12-28 22:24:02 +00:00
|
|
|
FacebookManager *fb = FacebookManager::instance();
|
|
|
|
connect(fb, &FacebookManager::justLoggedIn, ui.facebookPublish, &QPushButton::show);
|
|
|
|
connect(fb, &FacebookManager::justLoggedOut, ui.facebookPublish, &QPushButton::hide);
|
2014-12-28 23:06:07 +00:00
|
|
|
connect(ui.facebookPublish, &QPushButton::clicked, fb, &FacebookManager::sendDive);
|
2014-12-28 22:24:02 +00:00
|
|
|
ui.facebookPublish->setVisible(fb->loggedIn());
|
2015-01-16 19:43:49 +00:00
|
|
|
#else
|
|
|
|
ui.facebookPublish->setVisible(false);
|
|
|
|
#endif
|
2015-01-05 07:17:01 +00:00
|
|
|
|
|
|
|
acceptingEdit = false;
|
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()
|
|
|
|
{
|
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.diveEquipmentMessage->addAction(action);
|
|
|
|
ui.diveNotesMessage->addAction(action);
|
|
|
|
ui.diveInfoMessage->addAction(action);
|
|
|
|
ui.diveStatisticsMessage->addAction(action);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::hideMessage()
|
|
|
|
{
|
|
|
|
ui.diveNotesMessage->animatedHide();
|
|
|
|
ui.diveEquipmentMessage->animatedHide();
|
|
|
|
ui.diveInfoMessage->animatedHide();
|
|
|
|
ui.diveStatisticsMessage->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);
|
|
|
|
ui.diveEquipmentMessage->setCloseButtonVisible(false);
|
|
|
|
ui.diveInfoMessage->setCloseButtonVisible(false);
|
|
|
|
ui.diveStatisticsMessage->setCloseButtonVisible(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::displayMessage(QString str)
|
|
|
|
{
|
2014-08-05 05:45:17 +00:00
|
|
|
ui.diveNotesMessage->setCloseButtonVisible(false);
|
|
|
|
ui.diveEquipmentMessage->setCloseButtonVisible(false);
|
|
|
|
ui.diveInfoMessage->setCloseButtonVisible(false);
|
|
|
|
ui.diveStatisticsMessage->setCloseButtonVisible(false);
|
2013-12-03 20:44:48 +00:00
|
|
|
ui.diveNotesMessage->setText(str);
|
|
|
|
ui.diveNotesMessage->animatedShow();
|
|
|
|
ui.diveEquipmentMessage->setText(str);
|
|
|
|
ui.diveEquipmentMessage->animatedShow();
|
|
|
|
ui.diveInfoMessage->setText(str);
|
|
|
|
ui.diveInfoMessage->animatedShow();
|
|
|
|
ui.diveStatisticsMessage->setText(str);
|
|
|
|
ui.diveStatisticsMessage->animatedShow();
|
2014-04-05 16:03:45 +00:00
|
|
|
updateTextLabels();
|
2014-11-17 01:28:48 +00:00
|
|
|
ui.tagWidget->fixPopupPosition(ui.diveNotesMessage->bestContentHeight());
|
|
|
|
ui.buddy->fixPopupPosition(ui.diveNotesMessage->bestContentHeight());
|
|
|
|
ui.divemaster->fixPopupPosition(ui.diveNotesMessage->bestContentHeight());
|
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
|
|
|
{
|
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) &&
|
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;
|
|
|
|
}
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->setEnabled(false);
|
2014-08-04 15:58:21 +00:00
|
|
|
MainWindow::instance()->setEnabledToolbar(false);
|
2014-07-03 21:45:01 +00:00
|
|
|
|
|
|
|
// only setup the globe for editing if we are editing exactly one existing dive
|
|
|
|
if (amount_selected == 1 && newEditMode != ADD)
|
2014-05-07 21:01:05 +00:00
|
|
|
MainWindow::instance()->globe()->prepareForGetDiveCoordinates();
|
2014-07-03 21:45:01 +00:00
|
|
|
|
2014-02-12 14:22:54 +00:00
|
|
|
if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
|
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."));
|
2015-01-04 14:42:21 +00:00
|
|
|
memset(&displayedTrip, 0, sizeof(displayedTrip));
|
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
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-04-13 13:17:59 +00:00
|
|
|
void MainTab::clearInfo()
|
|
|
|
{
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.sacText->clear();
|
|
|
|
ui.otuText->clear();
|
2014-09-12 21:58:33 +00:00
|
|
|
ui.maxcnsText->clear();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.oxygenHeliumText->clear();
|
|
|
|
ui.gasUsedText->clear();
|
|
|
|
ui.dateText->clear();
|
|
|
|
ui.diveTimeText->clear();
|
|
|
|
ui.surfaceIntervalText->clear();
|
|
|
|
ui.maximumDepthText->clear();
|
|
|
|
ui.averageDepthText->clear();
|
|
|
|
ui.waterTemperatureText->clear();
|
|
|
|
ui.airTemperatureText->clear();
|
|
|
|
ui.airPressureText->clear();
|
2013-10-10 08:16:32 +00:00
|
|
|
ui.salinityText->clear();
|
2013-11-02 01:20:02 +00:00
|
|
|
ui.tagWidget->clear();
|
2013-04-13 13:17:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::clearStats()
|
|
|
|
{
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.depthLimits->clear();
|
|
|
|
ui.sacLimits->clear();
|
|
|
|
ui.divesAllText->clear();
|
|
|
|
ui.tempLimits->clear();
|
|
|
|
ui.totalTimeAllText->clear();
|
|
|
|
ui.timeLimits->clear();
|
2013-04-13 13:17:59 +00:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-07-02 21:15:17 +00:00
|
|
|
void MainTab::updateDiveInfo(bool clear)
|
2013-05-06 16:23:14 +00:00
|
|
|
{
|
2014-05-26 22:17:34 +00:00
|
|
|
// don't execute this while adding / planning a dive
|
|
|
|
if (editMode == ADD || editMode == MANUALLY_ADDED_DIVE || MainWindow::instance()->graphics()->isPlanner())
|
2013-11-12 07:33:27 +00:00
|
|
|
return;
|
2014-07-02 21:15:17 +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
|
|
|
|
|
2013-06-14 16:17:46 +00:00
|
|
|
// This method updates ALL tabs whenever a new dive or trip is
|
|
|
|
// selected.
|
|
|
|
// If exactly one trip has been selected, we show the location / notes
|
|
|
|
// for the trip in the Info tab, otherwise we show the info of the
|
|
|
|
// selected_dive
|
2013-05-20 05:42:24 +00:00
|
|
|
temperature_t temp;
|
2013-05-19 15:08:29 +00:00
|
|
|
struct dive *prevd;
|
2013-12-28 01:26:22 +00:00
|
|
|
char buf[1024];
|
2013-05-19 15:08:29 +00:00
|
|
|
|
2013-05-20 05:42:24 +00:00
|
|
|
process_selected_dives();
|
2014-07-02 21:15:17 +00:00
|
|
|
process_all_dives(&displayed_dive, &prevd);
|
|
|
|
|
|
|
|
divePictureModel->updateDivePictures();
|
2014-07-21 23:34:15 +00:00
|
|
|
|
|
|
|
ui.notes->setText(QString());
|
|
|
|
if (!clear) {
|
|
|
|
QString tmp(displayed_dive.notes);
|
|
|
|
if (tmp.indexOf("<table") != -1)
|
|
|
|
ui.notes->setHtml(tmp);
|
|
|
|
else
|
|
|
|
ui.notes->setPlainText(tmp);
|
|
|
|
}
|
|
|
|
|
2014-07-02 21:15:17 +00:00
|
|
|
UPDATE_TEXT(displayed_dive, notes);
|
|
|
|
UPDATE_TEXT(displayed_dive, location);
|
|
|
|
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);
|
2015-01-10 23:01:15 +00:00
|
|
|
ui.DiveType->setCurrentIndex(displayed_dive.dc.divemode);
|
2014-07-03 05:15:08 +00:00
|
|
|
|
2014-07-02 21:15:17 +00:00
|
|
|
if (!clear) {
|
2015-01-19 05:17:01 +00:00
|
|
|
updateGpsCoordinates();
|
2014-07-29 17:58:35 +00:00
|
|
|
// 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
|
2014-07-17 03:23:15 +00:00
|
|
|
QDateTime localTime = QDateTime::fromTime_t(displayed_dive.when - gettimezoneoffset(displayed_dive.when));
|
2014-07-29 17:58:35 +00:00
|
|
|
localTime.setTimeSpec(Qt::UTC);
|
2014-06-26 23:05:48 +00:00
|
|
|
ui.dateEdit->setDate(localTime.date());
|
|
|
|
ui.timeEdit->setTime(localTime.time());
|
2014-02-12 14:22:54 +00:00
|
|
|
if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
|
2014-07-10 23:06:42 +00:00
|
|
|
setTabText(0, tr("Trip notes"));
|
2014-07-30 15:52:11 +00:00
|
|
|
currentTrip = *MainWindow::instance()->dive_list()->selectedTrips().begin();
|
2013-06-14 16:17:46 +00:00
|
|
|
// only use trip relevant fields
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.coordinates->setVisible(false);
|
2013-11-04 19:28:03 +00:00
|
|
|
ui.CoordinatedLabel->setVisible(false);
|
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);
|
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"));
|
2013-10-03 18:54:25 +00:00
|
|
|
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);
|
2013-06-14 16:17:46 +00:00
|
|
|
} else {
|
2014-07-10 23:06:42 +00:00
|
|
|
setTabText(0, tr("Dive notes"));
|
2014-07-30 15:52:11 +00:00
|
|
|
currentTrip = NULL;
|
2013-06-14 16:17:46 +00:00
|
|
|
// make all the fields visible writeable
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.coordinates->setVisible(true);
|
2013-11-04 19:28:03 +00:00
|
|
|
ui.CoordinatedLabel->setVisible(true);
|
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);
|
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();
|
2014-11-06 19:24:38 +00:00
|
|
|
extraDataModel->updateDive();
|
2014-07-02 21:15:17 +00:00
|
|
|
taglist_get_tagstring(displayed_dive.tag_list, buf, 1024);
|
2013-12-28 01:26:22 +00:00
|
|
|
ui.tagWidget->setText(QString(buf));
|
2013-06-14 16:17:46 +00:00
|
|
|
}
|
2014-07-02 21:15:17 +00:00
|
|
|
ui.maximumDepthText->setText(get_depth_string(displayed_dive.maxdepth, true));
|
|
|
|
ui.averageDepthText->setText(get_depth_string(displayed_dive.meandepth, true));
|
2014-09-12 21:58:33 +00:00
|
|
|
ui.maxcnsText->setText(QString("%1\%").arg(displayed_dive.maxcns));
|
2014-07-02 21:15:17 +00:00
|
|
|
ui.otuText->setText(QString("%1").arg(displayed_dive.otu));
|
|
|
|
ui.waterTemperatureText->setText(get_temperature_string(displayed_dive.watertemp, true));
|
|
|
|
ui.airTemperatureText->setText(get_temperature_string(displayed_dive.airtemp, true));
|
2015-01-11 15:29:29 +00:00
|
|
|
ui.DiveType->setCurrentIndex(get_dive_dc(&displayed_dive, dc_number)->divemode);
|
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);
|
Make gas use statistics be coherent and more complete
The gas use logic in the dive statistics page is confused.
The SAC case had a special case for "unknown", but only for
the first gas. Other gases had the normal empty case.
Also, the logic was really odd - if you had gases that weren't used (or
pressures not known) intermixed with gases you *did* have pressure for,
the statistics got really confused.
The list of gases showed all gases that we know about during the dive,
but then the gas use and SAC-rate lists wouldn't necessarily match,
because the loops that computed those stopped after the first gas that
didn't have any pressure change.
To make things worse, the first cylinder was special-cased again, so it
all lined up for the single-cylinder case.
This makes all the cylinders act the same way, leaving unknown gas use
(and thus SAC) just empty for that gas.
It also fixes the SAC calculation case where we don't have real samples,
and the profile is a fake profile - possibly with gas changes in between
the fake points. We now make the SAC calculations match what we show -
which is admittedly not at all necessarily what the dive was, but at
least we're consistent.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2014-07-30 17:08:33 +00:00
|
|
|
QString volumes;
|
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);
|
2013-11-20 06:50:02 +00:00
|
|
|
volume_t sac;
|
Make gas use statistics be coherent and more complete
The gas use logic in the dive statistics page is confused.
The SAC case had a special case for "unknown", but only for
the first gas. Other gases had the normal empty case.
Also, the logic was really odd - if you had gases that weren't used (or
pressures not known) intermixed with gases you *did* have pressure for,
the statistics got really confused.
The list of gases showed all gases that we know about during the dive,
but then the gas use and SAC-rate lists wouldn't necessarily match,
because the loops that computed those stopped after the first gas that
didn't have any pressure change.
To make things worse, the first cylinder was special-cased again, so it
all lined up for the single-cylinder case.
This makes all the cylinders act the same way, leaving unknown gas use
(and thus SAC) just empty for that gas.
It also fixes the SAC calculation case where we don't have real samples,
and the profile is a fake profile - possibly with gas changes in between
the fake points. We now make the SAC calculations match what we show -
which is admittedly not at all necessarily what the dive was, but at
least we're consistent.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2014-07-30 17:08:33 +00:00
|
|
|
QString gaslist, SACs, separator;
|
|
|
|
|
|
|
|
gaslist = ""; SACs = ""; volumes = ""; separator = "";
|
|
|
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
|
|
|
if (!is_cylinder_used(&displayed_dive, i))
|
|
|
|
continue;
|
|
|
|
gaslist.append(separator); volumes.append(separator); SACs.append(separator);
|
|
|
|
separator = "\n";
|
|
|
|
|
|
|
|
gaslist.append(gasname(&displayed_dive.cylinder[i].gasmix));
|
|
|
|
if (!gases[i].mliter)
|
|
|
|
continue;
|
|
|
|
volumes.append(get_volume_string(gases[i], true));
|
|
|
|
if (duration[i]) {
|
2014-07-02 21:15:17 +00:00
|
|
|
sac.mliter = gases[i].mliter / (depth_to_atm(mean[i], &displayed_dive) * duration[i] / 60);
|
Make gas use statistics be coherent and more complete
The gas use logic in the dive statistics page is confused.
The SAC case had a special case for "unknown", but only for
the first gas. Other gases had the normal empty case.
Also, the logic was really odd - if you had gases that weren't used (or
pressures not known) intermixed with gases you *did* have pressure for,
the statistics got really confused.
The list of gases showed all gases that we know about during the dive,
but then the gas use and SAC-rate lists wouldn't necessarily match,
because the loops that computed those stopped after the first gas that
didn't have any pressure change.
To make things worse, the first cylinder was special-cased again, so it
all lined up for the single-cylinder case.
This makes all the cylinders act the same way, leaving unknown gas use
(and thus SAC) just empty for that gas.
It also fixes the SAC calculation case where we don't have real samples,
and the profile is a fake profile - possibly with gas changes in between
the fake points. We now make the SAC calculations match what we show -
which is admittedly not at all necessarily what the dive was, but at
least we're consistent.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2014-07-30 17:08:33 +00:00
|
|
|
SACs.append(get_volume_string(sac, true).append(tr("/min")));
|
2013-11-20 06:50:02 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-19 23:29:32 +00:00
|
|
|
ui.gasUsedText->setText(volumes);
|
Make gas use statistics be coherent and more complete
The gas use logic in the dive statistics page is confused.
The SAC case had a special case for "unknown", but only for
the first gas. Other gases had the normal empty case.
Also, the logic was really odd - if you had gases that weren't used (or
pressures not known) intermixed with gases you *did* have pressure for,
the statistics got really confused.
The list of gases showed all gases that we know about during the dive,
but then the gas use and SAC-rate lists wouldn't necessarily match,
because the loops that computed those stopped after the first gas that
didn't have any pressure change.
To make things worse, the first cylinder was special-cased again, so it
all lined up for the single-cylinder case.
This makes all the cylinders act the same way, leaving unknown gas use
(and thus SAC) just empty for that gas.
It also fixes the SAC calculation case where we don't have real samples,
and the profile is a fake profile - possibly with gas changes in between
the fake points. We now make the SAC calculations match what we show -
which is admittedly not at all necessarily what the dive was, but at
least we're consistent.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2014-07-30 17:08:33 +00:00
|
|
|
ui.oxygenHeliumText->setText(gaslist);
|
2014-07-02 21:15:17 +00:00
|
|
|
ui.dateText->setText(get_short_dive_date_string(displayed_dive.when));
|
|
|
|
ui.diveTimeText->setText(QString::number((int)((displayed_dive.duration.seconds + 30) / 60)));
|
2013-05-19 15:08:29 +00:00
|
|
|
if (prevd)
|
2014-07-02 21:15:17 +00:00
|
|
|
ui.surfaceIntervalText->setText(get_time_string(displayed_dive.when - (prevd->when + prevd->duration.seconds), 4));
|
2013-11-14 10:36:41 +00:00
|
|
|
else
|
|
|
|
ui.surfaceIntervalText->clear();
|
2013-11-20 06:50:02 +00:00
|
|
|
if (mean[0])
|
|
|
|
ui.sacText->setText(SACs);
|
2013-05-08 19:08:00 +00:00
|
|
|
else
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.sacText->clear();
|
2014-07-02 21:15:17 +00:00
|
|
|
if (displayed_dive.surface_pressure.mbar)
|
2013-05-08 19:08:00 +00:00
|
|
|
/* this is ALWAYS displayed in mbar */
|
2014-07-02 21:15:17 +00:00
|
|
|
ui.airPressureText->setText(QString("%1mbar").arg(displayed_dive.surface_pressure.mbar));
|
2013-05-08 19:08:00 +00:00
|
|
|
else
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.airPressureText->clear();
|
2014-07-02 21:15:17 +00:00
|
|
|
if (displayed_dive.salinity)
|
|
|
|
ui.salinityText->setText(QString("%1g/l").arg(displayed_dive.salinity / 10.0));
|
2013-10-10 08:16:32 +00:00
|
|
|
else
|
|
|
|
ui.salinityText->clear();
|
2014-01-15 08:30:42 +00:00
|
|
|
ui.depthLimits->setMaximum(get_depth_string(stats_selection.max_depth, true));
|
|
|
|
ui.depthLimits->setMinimum(get_depth_string(stats_selection.min_depth, true));
|
2014-06-10 03:32:44 +00:00
|
|
|
// the overall average depth is really confusing when listed between the
|
|
|
|
// deepest and shallowest dive - let's just not set it
|
|
|
|
// ui.depthLimits->setAverage(get_depth_string(stats_selection.avg_depth, true));
|
2014-07-10 23:06:42 +00:00
|
|
|
ui.depthLimits->overrideMaxToolTipText(tr("Deepest dive"));
|
|
|
|
ui.depthLimits->overrideMinToolTipText(tr("Shallowest dive"));
|
2014-11-17 18:40:08 +00:00
|
|
|
if (amount_selected > 1 && stats_selection.max_sac.mliter)
|
2014-08-06 14:38:18 +00:00
|
|
|
ui.sacLimits->setMaximum(get_volume_string(stats_selection.max_sac, true).append(tr("/min")));
|
|
|
|
else
|
|
|
|
ui.sacLimits->setMaximum("");
|
2014-11-17 18:40:08 +00:00
|
|
|
if (amount_selected > 1 && stats_selection.min_sac.mliter)
|
2014-08-06 14:38:18 +00:00
|
|
|
ui.sacLimits->setMinimum(get_volume_string(stats_selection.min_sac, true).append(tr("/min")));
|
|
|
|
else
|
|
|
|
ui.sacLimits->setMinimum("");
|
|
|
|
if (stats_selection.avg_sac.mliter)
|
|
|
|
ui.sacLimits->setAverage(get_volume_string(stats_selection.avg_sac, true).append(tr("/min")));
|
|
|
|
else
|
|
|
|
ui.sacLimits->setAverage("");
|
2014-11-17 18:40:08 +00:00
|
|
|
ui.sacLimits->overrideMaxToolTipText(tr("Highest total SAC of a dive"));
|
|
|
|
ui.sacLimits->overrideMinToolTipText(tr("Lowest total SAC of a dive"));
|
|
|
|
ui.sacLimits->overrideAvgToolTipText(tr("Average total SAC of all selected dives"));
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.divesAllText->setText(QString::number(stats_selection.selection_size));
|
2013-05-20 05:42:24 +00:00
|
|
|
temp.mkelvin = stats_selection.max_temp;
|
2014-01-15 08:30:42 +00:00
|
|
|
ui.tempLimits->setMaximum(get_temperature_string(temp, true));
|
2013-05-20 05:42:24 +00:00
|
|
|
temp.mkelvin = stats_selection.min_temp;
|
2014-01-15 08:30:42 +00:00
|
|
|
ui.tempLimits->setMinimum(get_temperature_string(temp, true));
|
2013-05-20 05:42:24 +00:00
|
|
|
if (stats_selection.combined_temp && stats_selection.combined_count) {
|
|
|
|
const char *unit;
|
|
|
|
get_temp_units(0, &unit);
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.tempLimits->setAverage(QString("%1%2").arg(stats_selection.combined_temp / stats_selection.combined_count, 0, 'f', 1).arg(unit));
|
2013-05-20 05:42:24 +00:00
|
|
|
}
|
2014-11-17 18:40:08 +00:00
|
|
|
ui.tempLimits->overrideMaxToolTipText(tr("Highest temperature"));
|
|
|
|
ui.tempLimits->overrideMinToolTipText(tr("Lowest temperature"));
|
|
|
|
ui.tempLimits->overrideAvgToolTipText(tr("Average temperature of all selected dives"));
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.totalTimeAllText->setText(get_time_string(stats_selection.total_time.seconds, 0));
|
2013-05-20 05:42:24 +00:00
|
|
|
int seconds = stats_selection.total_time.seconds;
|
|
|
|
if (stats_selection.selection_size)
|
|
|
|
seconds /= stats_selection.selection_size;
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.timeLimits->setAverage(get_time_string(seconds, 0));
|
2014-11-17 18:40:08 +00:00
|
|
|
if (amount_selected > 1) {
|
|
|
|
ui.timeLimits->setMaximum(get_time_string(stats_selection.longest_time.seconds, 0));
|
|
|
|
ui.timeLimits->setMinimum(get_time_string(stats_selection.shortest_time.seconds, 0));
|
|
|
|
}
|
|
|
|
ui.timeLimits->overrideMaxToolTipText(tr("Longest dive"));
|
|
|
|
ui.timeLimits->overrideMinToolTipText(tr("Shortest dive"));
|
|
|
|
ui.timeLimits->overrideAvgToolTipText(tr("Average length of all selected dives"));
|
2014-06-10 05:45:44 +00:00
|
|
|
// now let's get some gas use statistics
|
|
|
|
QVector<QPair<QString, int> > gasUsed;
|
|
|
|
QString gasUsedString;
|
|
|
|
volume_t vol;
|
|
|
|
selectedDivesGasUsed(gasUsed);
|
2014-06-10 18:45:20 +00:00
|
|
|
for (int j = 0; j < 20; j++) {
|
2014-06-10 05:45:44 +00:00
|
|
|
if (gasUsed.isEmpty())
|
|
|
|
break;
|
|
|
|
QPair<QString, int> gasPair = gasUsed.last();
|
|
|
|
gasUsed.pop_back();
|
|
|
|
vol.mliter = gasPair.second;
|
|
|
|
gasUsedString.append(gasPair.first).append(": ").append(get_volume_string(vol, true)).append("\n");
|
|
|
|
}
|
|
|
|
if (!gasUsed.isEmpty())
|
|
|
|
gasUsedString.append("...");
|
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
|
|
|
|
|
|
|
/* No need to show the gas mixing information if diving
|
|
|
|
* with pure air, and only display the he / O2 part when
|
|
|
|
* it is used.
|
|
|
|
*/
|
|
|
|
if (he_tot.mliter || o2_tot.mliter) {
|
2014-07-16 17:37:06 +00:00
|
|
|
gasUsedString.append(tr("These gases could be\nmixed from Air and using:\n"));
|
2014-07-06 02:34:43 +00:00
|
|
|
if (he_tot.mliter)
|
|
|
|
gasUsedString.append(QString("He: %1").arg(get_volume_string(he_tot, true)));
|
|
|
|
if (he_tot.mliter && o2_tot.mliter)
|
2014-07-16 17:37:06 +00:00
|
|
|
gasUsedString.append(tr(" and "));
|
2014-07-06 02:34:43 +00:00
|
|
|
if (o2_tot.mliter)
|
|
|
|
gasUsedString.append(QString("O2: %2\n").arg(get_volume_string(o2_tot, true)));
|
|
|
|
}
|
2014-06-10 05:45:44 +00:00
|
|
|
ui.gasConsumption->setText(gasUsedString);
|
2013-05-08 19:08:00 +00:00
|
|
|
} else {
|
2013-05-20 00:38:20 +00:00
|
|
|
/* clear the fields */
|
2013-10-10 08:16:32 +00:00
|
|
|
clearInfo();
|
|
|
|
clearStats();
|
|
|
|
clearEquipment();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.rating->setCurrentStars(0);
|
|
|
|
ui.coordinates->clear();
|
|
|
|
ui.visibility->setCurrentStars(0);
|
2013-05-08 19:08:00 +00:00
|
|
|
}
|
2014-07-03 05:15:08 +00:00
|
|
|
editMode = NONE;
|
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);
|
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();
|
|
|
|
locationModel.updateModel();
|
|
|
|
diveMasterModel.updateModel();
|
|
|
|
tagModel.updateModel();
|
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
|
|
|
|
// loop over all dives, for each selected dive do WHAT, but do it
|
|
|
|
// last for the current dive; this is required in case the invocation
|
|
|
|
// wants to compare things to the original value in current_dive like it should
|
2014-07-02 18:50:28 +00:00
|
|
|
#define MODIFY_SELECTED_DIVES(WHAT) \
|
2014-05-07 20:00:33 +00:00
|
|
|
do { \
|
|
|
|
struct dive *mydive = NULL; \
|
2014-05-19 21:37:19 +00:00
|
|
|
int _i; \
|
|
|
|
for_each_dive (_i, mydive) { \
|
2014-06-03 01:13:50 +00:00
|
|
|
if (!mydive->selected || mydive == cd) \
|
2014-05-07 20:00:33 +00:00
|
|
|
continue; \
|
|
|
|
\
|
|
|
|
WHAT; \
|
|
|
|
} \
|
2014-06-03 01:13:50 +00:00
|
|
|
mydive = cd; \
|
2014-05-07 20:00:33 +00:00
|
|
|
WHAT; \
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
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-09 16:35:27 +00:00
|
|
|
on_location_editingFinished(); // complete coordinates *before* saving
|
2014-07-03 21:45:01 +00:00
|
|
|
if (editMode == ADD) {
|
2014-07-03 23:12:47 +00:00
|
|
|
// We need to add the dive we just created to the dive list and select it.
|
2014-07-03 21:45:01 +00:00
|
|
|
// Easy, right?
|
|
|
|
struct dive *added_dive = clone_dive(&displayed_dive);
|
|
|
|
record_dive(added_dive);
|
|
|
|
addedId = added_dive->id;
|
2014-08-22 00:58:15 +00:00
|
|
|
// unselect everything as far as the UI is concerned and select the new
|
|
|
|
// dive - we'll have to undo/redo this later after we resort the dive_table
|
|
|
|
// but we need the dive selected for the middle part of this function - this
|
|
|
|
// way we can reuse the code used for editing dives
|
2014-07-03 21:45:01 +00:00
|
|
|
MainWindow::instance()->dive_list()->unselectDives();
|
|
|
|
selected_dive = get_divenr(added_dive);
|
|
|
|
amount_selected = 1;
|
2014-07-24 15:20:34 +00:00
|
|
|
} else if (MainWindow::instance() && MainWindow::instance()->dive_list()->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 {
|
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);
|
|
|
|
}
|
2014-06-03 01:13:50 +00:00
|
|
|
struct dive *cd = current_dive;
|
2013-09-19 16:37:44 +00:00
|
|
|
//Reset coordinates field, in case it contains garbage.
|
2015-01-19 05:17:01 +00:00
|
|
|
updateGpsCoordinates();
|
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)
|
2014-07-02 18:50:28 +00:00
|
|
|
if (!same_string(displayed_dive.buddy, cd->buddy))
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_TEXT(buddy));
|
|
|
|
if (!same_string(displayed_dive.suit, cd->suit))
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_TEXT(suit));
|
|
|
|
if (!same_string(displayed_dive.notes, cd->notes))
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_TEXT(notes));
|
|
|
|
if (!same_string(displayed_dive.divemaster, cd->divemaster))
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_TEXT(divemaster));
|
|
|
|
if (displayed_dive.rating != cd->rating)
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_VALUE(rating));
|
|
|
|
if (displayed_dive.visibility != cd->visibility)
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_VALUE(visibility));
|
|
|
|
if (displayed_dive.airtemp.mkelvin != cd->airtemp.mkelvin)
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_VALUE(airtemp.mkelvin));
|
2015-01-10 23:01:15 +00:00
|
|
|
if (displayed_dive.dc.divemode != cd->dc.divemode) {
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_VALUE(dc.divemode));
|
2015-01-08 13:42:07 +00:00
|
|
|
MODIFY_SELECTED_DIVES(update_setpoint_events(&mydive->dc));
|
2015-01-10 22:42:21 +00:00
|
|
|
do_replot = true;
|
2015-01-08 13:42:07 +00:00
|
|
|
}
|
2014-07-02 18:50:28 +00:00
|
|
|
if (displayed_dive.watertemp.mkelvin != cd->watertemp.mkelvin)
|
|
|
|
MODIFY_SELECTED_DIVES(EDIT_VALUE(watertemp.mkelvin));
|
|
|
|
if (displayed_dive.when != cd->when) {
|
2014-07-09 16:35:27 +00:00
|
|
|
time_t offset = cd->when - displayed_dive.when;
|
2014-07-02 18:50:28 +00:00
|
|
|
MODIFY_SELECTED_DIVES(mydive->when -= offset;);
|
2013-09-20 23:41:42 +00:00
|
|
|
}
|
2014-07-09 16:35:27 +00:00
|
|
|
if (displayed_dive.latitude.udeg != cd->latitude.udeg ||
|
|
|
|
displayed_dive.longitude.udeg != cd->longitude.udeg)
|
|
|
|
MODIFY_SELECTED_DIVES(
|
2014-11-05 14:34:29 +00:00
|
|
|
if (copyPaste ||
|
|
|
|
(same_string(mydive->location, cd->location) &&
|
|
|
|
mydive->latitude.udeg == cd->latitude.udeg &&
|
|
|
|
mydive->longitude.udeg == cd->longitude.udeg))
|
2014-07-09 16:35:27 +00:00
|
|
|
gpsHasChanged(mydive, cd, ui.coordinates->text(), 0);
|
|
|
|
);
|
|
|
|
if (!same_string(displayed_dive.location, cd->location))
|
2014-07-02 18:50:28 +00:00
|
|
|
MODIFY_SELECTED_DIVES(EDIT_TEXT(location));
|
2014-07-09 16:35:27 +00:00
|
|
|
|
2014-07-08 21:18:33 +00:00
|
|
|
saveTags();
|
2014-07-03 21:45:01 +00:00
|
|
|
|
|
|
|
if (editMode != ADD && cylindersModel->changed) {
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2014-07-02 18:50:28 +00:00
|
|
|
MODIFY_SELECTED_DIVES(
|
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);
|
|
|
|
}
|
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);
|
2014-07-02 18:50:28 +00:00
|
|
|
MODIFY_SELECTED_DIVES(
|
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
|
|
|
}
|
|
|
|
// 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) {
|
|
|
|
if (d->selected)
|
|
|
|
fixup_dive(d);
|
2013-09-25 17:57:41 +00:00
|
|
|
}
|
2013-05-19 14:45:01 +00:00
|
|
|
}
|
2013-11-19 22:16:33 +00:00
|
|
|
if (current_dive->divetrip) {
|
|
|
|
current_dive->divetrip->when = current_dive->when;
|
|
|
|
find_new_trip_start_time(current_dive->divetrip);
|
|
|
|
}
|
2013-11-01 15:48:34 +00:00
|
|
|
if (editMode == ADD || editMode == MANUALLY_ADDED_DIVE) {
|
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
|
|
|
}
|
2014-02-12 14:22:54 +00:00
|
|
|
int scrolledBy = MainWindow::instance()->dive_list()->verticalScrollBar()->sliderPosition();
|
2013-09-25 17:36:59 +00:00
|
|
|
resetPallete();
|
2014-01-16 04:50:56 +00:00
|
|
|
if (editMode == ADD || editMode == MANUALLY_ADDED_DIVE) {
|
2014-08-22 00:58:15 +00:00
|
|
|
// since a newly added dive could be in the middle of the dive_table we need
|
|
|
|
// to resort the dive list and make sure the newly added dive gets selected again
|
2014-07-24 15:20:34 +00:00
|
|
|
sort_table(&dive_table);
|
2014-07-04 04:05:08 +00:00
|
|
|
MainWindow::instance()->dive_list()->reload(DiveTripModel::CURRENT, true);
|
2014-07-03 21:45:01 +00:00
|
|
|
int newDiveNr = get_divenr(get_dive_by_uniq_id(addedId));
|
2014-08-22 00:58:15 +00:00
|
|
|
MainWindow::instance()->dive_list()->unselectDives();
|
2014-07-03 21:45:01 +00:00
|
|
|
MainWindow::instance()->dive_list()->selectDive(newDiveNr, true);
|
2013-12-03 23:25:20 +00:00
|
|
|
editMode = NONE;
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->refreshDisplay();
|
2014-03-09 13:59:31 +00:00
|
|
|
MainWindow::instance()->graphics()->replot();
|
2014-05-21 23:34:06 +00:00
|
|
|
emit addDiveFinished();
|
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)
|
|
|
|
MainWindow::instance()->graphics()->replot();
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->rememberSelection();
|
2013-12-03 22:34:05 +00:00
|
|
|
sort_table(&dive_table);
|
2014-08-07 17:23:08 +00:00
|
|
|
MainWindow::instance()->refreshDisplay();
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->restoreSelection();
|
2013-12-03 22:34:05 +00:00
|
|
|
}
|
2014-02-19 17:43:34 +00:00
|
|
|
DivePlannerPointsModel::instance()->setPlanMode(DivePlannerPointsModel::NOTHING);
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->verticalScrollBar()->setSliderPosition(scrolledBy);
|
|
|
|
MainWindow::instance()->dive_list()->setFocus();
|
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;
|
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.coordinates->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);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
#define EDIT_TEXT2(what, text) \
|
2013-12-16 22:50:42 +00:00
|
|
|
textByteArray = text.toUtf8(); \
|
2014-02-28 04:09:57 +00:00
|
|
|
free(what); \
|
2013-08-16 16:31:52 +00:00
|
|
|
what = strdup(textByteArray.data());
|
|
|
|
|
2014-07-02 18:50:28 +00:00
|
|
|
#define FREE_IF_DIFFERENT(what) \
|
|
|
|
if (displayed_dive.what != cd->what) \
|
|
|
|
free(displayed_dive.what)
|
2014-06-04 01:12:24 +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) ||
|
|
|
|
memcmp(¤t_dive->cylinder[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)
|
|
|
|
MainWindow::instance()->dive_list()->restoreSelection();
|
2014-07-06 19:36:25 +00:00
|
|
|
|
|
|
|
// now make sure that the correct dive is displayed
|
|
|
|
if (selected_dive >= 0)
|
|
|
|
copy_dive(current_dive, &displayed_dive);
|
|
|
|
else
|
|
|
|
clear_dive(&displayed_dive);
|
|
|
|
updateDiveInfo(selected_dive < 0);
|
2014-08-02 20:05:52 +00:00
|
|
|
DivePictureModel::instance()->updateDivePictures();
|
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
|
2014-05-07 20:58:07 +00:00
|
|
|
MainWindow::instance()->globe()->centerOnCurrentDive();
|
2014-07-06 19:36:25 +00:00
|
|
|
MainWindow::instance()->globe()->reload();
|
|
|
|
// show the profile and dive info
|
|
|
|
MainWindow::instance()->graphics()->replot();
|
2014-08-04 15:58:21 +00:00
|
|
|
MainWindow::instance()->setEnabledToolbar(true);
|
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();
|
2014-11-06 19:24:38 +00:00
|
|
|
extraDataModel->updateDive();
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
2013-08-16 16:31:52 +00:00
|
|
|
#undef EDIT_TEXT2
|
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);
|
2014-07-03 05:15:08 +00:00
|
|
|
if (!modified) {
|
|
|
|
modified = true;
|
|
|
|
enableEdition();
|
|
|
|
}
|
2013-08-16 18:52:40 +00:00
|
|
|
}
|
2013-05-18 23:42:59 +00:00
|
|
|
|
2014-01-15 20:35:14 +00:00
|
|
|
void MainTab::on_buddy_textChanged()
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2014-03-26 20:09:01 +00:00
|
|
|
QStringList text_list = ui.buddy->toPlainText().split(",", QString::SkipEmptyParts);
|
|
|
|
for (int i = 0; i < text_list.size(); i++)
|
|
|
|
text_list[i] = text_list[i].trimmed();
|
|
|
|
QString text = text_list.join(", ");
|
2014-07-03 04:31:55 +00:00
|
|
|
free(displayed_dive.buddy);
|
2014-07-02 18:50:28 +00:00
|
|
|
displayed_dive.buddy = strdup(text.toUtf8().data());
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.buddy);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2014-01-19 17:30:47 +00:00
|
|
|
void MainTab::on_divemaster_textChanged()
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2014-03-26 20:09:01 +00:00
|
|
|
QStringList text_list = ui.divemaster->toPlainText().split(",", QString::SkipEmptyParts);
|
|
|
|
for (int i = 0; i < text_list.size(); i++)
|
|
|
|
text_list[i] = text_list[i].trimmed();
|
|
|
|
QString text = text_list.join(", ");
|
2014-07-03 04:31:55 +00:00
|
|
|
free(displayed_dive.divemaster);
|
2014-07-02 18:50:28 +00:00
|
|
|
displayed_dive.divemaster = strdup(text.toUtf8().data());
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.divemaster);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_airtemp_textChanged(const QString &text)
|
2013-09-20 23:41:42 +00:00
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2014-07-02 18:50:28 +00:00
|
|
|
displayed_dive.airtemp.mkelvin = parseTemperatureToMkelvin(text);
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.airtemp);
|
2014-04-13 16:19:15 +00:00
|
|
|
validate_temp_field(ui.airtemp, text);
|
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
|
|
|
{
|
|
|
|
if (editMode == IGNORE)
|
|
|
|
return;
|
2015-01-10 23:01:15 +00:00
|
|
|
displayed_dive.dc.divemode = (enum dive_comp_type) index;
|
2015-01-01 16:00:46 +00:00
|
|
|
update_setpoint_events(&displayed_dive.dc);
|
|
|
|
markChangedWidget(ui.DiveType);
|
2015-01-16 12:02:26 +00:00
|
|
|
MainWindow::instance()->graphics()->replot();
|
2015-01-01 16:00:46 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_watertemp_textChanged(const QString &text)
|
2013-09-20 23:41:42 +00:00
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2014-07-02 18:50:28 +00:00
|
|
|
displayed_dive.watertemp.mkelvin = parseTemperatureToMkelvin(text);
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.watertemp);
|
2014-04-13 16:19:15 +00:00
|
|
|
validate_temp_field(ui.watertemp, text);
|
2013-09-20 23:41:42 +00:00
|
|
|
}
|
|
|
|
|
2014-05-22 18:40:22 +00:00
|
|
|
void MainTab::validate_temp_field(QLineEdit *tempField, const QString &text)
|
2014-04-13 16:19:15 +00:00
|
|
|
{
|
|
|
|
static bool missing_unit = false;
|
|
|
|
static bool missing_precision = false;
|
|
|
|
if (!text.contains(QRegExp("^[-+]{0,1}[0-9]+([,.][0-9]+){0,1}(°[CF]){0,1}$")) &&
|
|
|
|
!text.isEmpty() &&
|
|
|
|
!text.contains(QRegExp("^[-+]$"))) {
|
|
|
|
if (text.contains(QRegExp("^[-+]{0,1}[0-9]+([,.][0-9]+){0,1}(°)$")) && !missing_unit) {
|
|
|
|
if (!missing_unit) {
|
|
|
|
missing_unit = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (text.contains(QRegExp("^[-+]{0,1}[0-9]+([,.]){0,1}(°[CF]){0,1}$")) && !missing_precision) {
|
|
|
|
if (!missing_precision) {
|
|
|
|
missing_precision = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QPalette p;
|
|
|
|
p.setBrush(QPalette::Base, QColor(Qt::red).lighter());
|
|
|
|
tempField->setPalette(p);
|
|
|
|
} else {
|
|
|
|
missing_unit = false;
|
|
|
|
missing_precision = false;
|
|
|
|
}
|
|
|
|
}
|
2014-05-06 20:56:46 +00:00
|
|
|
|
2014-06-26 17:57:25 +00:00
|
|
|
void MainTab::on_dateEdit_dateChanged(const QDate &date)
|
2013-09-20 23:41:42 +00:00
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2014-10-21 00:25:13 +00:00
|
|
|
markChangedWidget(ui.dateEdit);
|
2014-07-29 17:58:35 +00:00
|
|
|
QDateTime dateTime = QDateTime::fromTime_t(displayed_dive.when - gettimezoneoffset(displayed_dive.when));
|
2014-06-26 17:57:25 +00:00
|
|
|
dateTime.setTimeSpec(Qt::UTC);
|
|
|
|
dateTime.setDate(date);
|
2014-10-21 00:25:13 +00:00
|
|
|
DivePlannerPointsModel::instance()->getDiveplan().when = displayed_dive.when = dateTime.toTime_t();
|
2014-10-21 00:36:24 +00:00
|
|
|
emit dateTimeChanged();
|
2013-09-20 23:41:42 +00:00
|
|
|
}
|
|
|
|
|
2014-06-26 17:54:16 +00:00
|
|
|
void MainTab::on_timeEdit_timeChanged(const QTime &time)
|
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-26 17:54:16 +00:00
|
|
|
return;
|
2014-10-21 00:25:13 +00:00
|
|
|
markChangedWidget(ui.timeEdit);
|
2014-07-29 17:58:35 +00:00
|
|
|
QDateTime dateTime = QDateTime::fromTime_t(displayed_dive.when - gettimezoneoffset(displayed_dive.when));
|
2014-06-26 17:57:25 +00:00
|
|
|
dateTime.setTimeSpec(Qt::UTC);
|
2014-06-26 17:54:16 +00:00
|
|
|
dateTime.setTime(time);
|
2014-10-21 00:25:13 +00:00
|
|
|
DivePlannerPointsModel::instance()->getDiveplan().when = displayed_dive.when = dateTime.toTime_t();
|
2014-10-21 00:36:24 +00:00
|
|
|
emit dateTimeChanged();
|
2014-06-26 17:54:16 +00:00
|
|
|
}
|
|
|
|
|
2014-05-06 20:56:46 +00:00
|
|
|
// changing the tags on multiple dives is semantically strange - what's the right thing to do?
|
2013-11-02 01:20:02 +00:00
|
|
|
void MainTab::saveTags()
|
|
|
|
{
|
2014-06-03 01:13:50 +00:00
|
|
|
struct dive *cd = current_dive;
|
2014-10-30 20:01:09 +00:00
|
|
|
taglist_free(displayed_dive.tag_list);
|
|
|
|
displayed_dive.tag_list = NULL;
|
2014-07-10 16:39:51 +00:00
|
|
|
Q_FOREACH (const QString& tag, ui.tagWidget->getBlockStringList())
|
2014-07-09 11:43:49 +00:00
|
|
|
taglist_add_tag(&displayed_dive.tag_list, tag.toUtf8().data());
|
2014-07-10 16:39:51 +00:00
|
|
|
taglist_cleanup(&displayed_dive.tag_list);
|
2014-07-02 18:50:28 +00:00
|
|
|
MODIFY_SELECTED_DIVES(
|
2014-05-22 18:40:22 +00:00
|
|
|
QString tag;
|
|
|
|
taglist_free(mydive->tag_list);
|
|
|
|
mydive->tag_list = NULL;
|
2014-06-03 01:13:50 +00:00
|
|
|
Q_FOREACH (tag, ui.tagWidget->getBlockStringList())
|
2014-07-08 21:45:20 +00:00
|
|
|
taglist_add_tag(&mydive->tag_list, tag.toUtf8().data());
|
|
|
|
);
|
2013-11-02 01:20:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::on_tagWidget_textChanged()
|
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2014-07-08 21:45:20 +00:00
|
|
|
markChangedWidget(ui.tagWidget);
|
2013-11-02 01:20:02 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_location_textChanged(const QString &text)
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-05-07 21:51:39 +00:00
|
|
|
return;
|
2014-07-30 15:52:11 +00:00
|
|
|
if (currentTrip) {
|
|
|
|
free(displayedTrip.location);
|
|
|
|
displayedTrip.location = strdup(ui.location->text().toUtf8().data());
|
|
|
|
} else {
|
|
|
|
free(displayed_dive.location);
|
|
|
|
displayed_dive.location = strdup(ui.location->text().toUtf8().data());
|
|
|
|
}
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.location);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2014-07-09 16:35:27 +00:00
|
|
|
// If we have GPS data for the location entered, add it.
|
|
|
|
void MainTab::on_location_editingFinished()
|
|
|
|
{
|
2014-08-16 13:09:11 +00:00
|
|
|
// if we have a location and no GPS data, look up the GPS data;
|
|
|
|
// but if the GPS data was intentionally cleared then don't
|
2014-07-30 15:52:11 +00:00
|
|
|
if (!currentTrip &&
|
|
|
|
!same_string(displayed_dive.location, "") &&
|
2014-08-16 13:09:11 +00:00
|
|
|
ui.coordinates->text().trimmed().isEmpty() &&
|
|
|
|
!(editMode == DIVE && dive_has_gps_location(current_dive))) {
|
2014-07-09 16:35:27 +00:00
|
|
|
struct dive *dive;
|
|
|
|
int i = 0;
|
|
|
|
for_each_dive (i, dive) {
|
|
|
|
if (same_string(displayed_dive.location, dive->location) &&
|
|
|
|
(dive->latitude.udeg || dive->longitude.udeg)) {
|
|
|
|
displayed_dive.latitude = dive->latitude;
|
|
|
|
displayed_dive.longitude = dive->longitude;
|
|
|
|
MainWindow::instance()->globe()->reload();
|
2015-01-19 05:17:01 +00:00
|
|
|
updateGpsCoordinates();
|
2014-07-09 16:35:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_suit_textChanged(const QString &text)
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2014-07-03 04:31:55 +00:00
|
|
|
free(displayed_dive.suit);
|
2014-07-02 18:50:28 +00:00
|
|
|
displayed_dive.suit = strdup(text.toUtf8().data());
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.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) {
|
|
|
|
free(displayedTrip.notes);
|
|
|
|
displayedTrip.notes = strdup(ui.notes->toPlainText().toUtf8().data());
|
|
|
|
} else {
|
|
|
|
free(displayed_dive.notes);
|
|
|
|
if (ui.notes->toHtml().indexOf("<table") != -1)
|
|
|
|
displayed_dive.notes = strdup(ui.notes->toHtml().toUtf8().data());
|
|
|
|
else
|
|
|
|
displayed_dive.notes = strdup(ui.notes->toPlainText().toUtf8().data());
|
|
|
|
}
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.notes);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_coordinates_textChanged(const QString &text)
|
2013-09-17 19:50:15 +00:00
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (editMode == IGNORE || acceptingEdit == true)
|
2014-06-03 01:13:50 +00:00
|
|
|
return;
|
2013-12-23 22:56:40 +00:00
|
|
|
bool gpsChanged = false;
|
|
|
|
bool parsed = false;
|
2014-05-07 22:14:01 +00:00
|
|
|
QPalette p;
|
|
|
|
ui.coordinates->setPalette(p); // reset palette
|
2015-01-19 09:03:42 +00:00
|
|
|
gpsChanged = gpsHasChanged(&displayed_dive, &displayed_dive, text, &parsed);
|
2014-05-07 22:14:01 +00:00
|
|
|
if (gpsChanged)
|
|
|
|
markChangedWidget(ui.coordinates); // marks things yellow
|
|
|
|
if (!parsed) {
|
2013-09-19 16:37:44 +00:00
|
|
|
p.setBrush(QPalette::Base, QColor(Qt::red).lighter());
|
2014-05-07 22:14:01 +00:00
|
|
|
ui.coordinates->setPalette(p); // marks things red
|
2013-09-19 16:37:44 +00:00
|
|
|
}
|
2013-09-17 19:50:15 +00:00
|
|
|
}
|
|
|
|
|
2013-05-18 23:42:59 +00:00
|
|
|
void MainTab::on_rating_valueChanged(int value)
|
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (acceptingEdit == true)
|
|
|
|
return;
|
2014-07-03 04:33:03 +00:00
|
|
|
if (displayed_dive.rating != value) {
|
|
|
|
displayed_dive.rating = value;
|
|
|
|
modified = true;
|
2014-07-03 05:15:08 +00:00
|
|
|
enableEdition();
|
2014-07-03 04:33:03 +00:00
|
|
|
}
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
2013-05-20 13:25:16 +00:00
|
|
|
|
|
|
|
void MainTab::on_visibility_valueChanged(int value)
|
|
|
|
{
|
2015-01-04 18:06:33 +00:00
|
|
|
if (acceptingEdit == true)
|
|
|
|
return;
|
2014-07-03 04:33:03 +00:00
|
|
|
if (displayed_dive.visibility != value) {
|
|
|
|
displayed_dive.visibility = value;
|
|
|
|
modified = true;
|
2014-07-03 05:15:08 +00:00
|
|
|
enableEdition();
|
2014-07-03 04:33:03 +00:00
|
|
|
}
|
2013-05-20 13:25:16 +00:00
|
|
|
}
|
2013-06-16 17:36:23 +00:00
|
|
|
|
2014-07-03 04:33:03 +00:00
|
|
|
#undef MODIFY_SELECTED_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
|
|
|
|
2013-11-19 12:12:31 +00:00
|
|
|
void MainTab::updateCoordinatesText(qreal lat, qreal lon)
|
|
|
|
{
|
|
|
|
int ulat = rint(lat * 1000000);
|
|
|
|
int ulon = rint(lon * 1000000);
|
|
|
|
ui.coordinates->setText(printGPSCoords(ulat, ulon));
|
|
|
|
}
|
|
|
|
|
2015-01-19 05:17:01 +00:00
|
|
|
void MainTab::updateGpsCoordinates()
|
2013-11-11 23:21:45 +00:00
|
|
|
{
|
2015-01-19 05:32:17 +00:00
|
|
|
if (editMode == NONE)
|
|
|
|
enableEdition();
|
|
|
|
|
2015-01-19 05:17:01 +00:00
|
|
|
ui.coordinates->setText(printGPSCoords(displayed_dive.latitude.udeg, displayed_dive.longitude.udeg));
|
|
|
|
ui.coordinates->setModified(displayed_dive.latitude.udeg || displayed_dive.longitude.udeg);
|
2013-11-11 23:21:45 +00:00
|
|
|
}
|
2014-05-07 22:12:45 +00:00
|
|
|
|
2014-06-03 22:29:28 +00:00
|
|
|
void MainTab::escDetected()
|
|
|
|
{
|
|
|
|
if (editMode != NONE)
|
|
|
|
rejectChanges();
|
|
|
|
}
|
2014-06-27 12:17:33 +00:00
|
|
|
|
|
|
|
void MainTab::photoDoubleClicked(const QString filePath)
|
|
|
|
{
|
|
|
|
QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
|
|
|
|
}
|
2014-08-06 21:05:54 +00:00
|
|
|
|
|
|
|
void MainTab::removeSelectedPhotos()
|
|
|
|
{
|
|
|
|
if (!ui.photosView->selectionModel()->hasSelection())
|
|
|
|
return;
|
|
|
|
|
|
|
|
QModelIndex photoIndex = ui.photosView->selectionModel()->selectedIndexes().first();
|
|
|
|
QString fileUrl = photoIndex.data(Qt::DisplayPropertyRole).toString();
|
|
|
|
DivePictureModel::instance()->removePicture(fileUrl);
|
|
|
|
}
|
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(location);
|
|
|
|
SHOW_SELECTIVE(buddy);
|
|
|
|
SHOW_SELECTIVE(divemaster);
|
|
|
|
SHOW_SELECTIVE(suit);
|
|
|
|
if (what.notes) {
|
|
|
|
QString tmp(displayed_dive.notes);
|
|
|
|
if (tmp.contains("<table"))
|
|
|
|
ui.notes->setHtml(tmp);
|
|
|
|
else
|
|
|
|
ui.notes->setPlainText(tmp);
|
|
|
|
}
|
|
|
|
if (what.rating)
|
|
|
|
ui.rating->setCurrentStars(displayed_dive.rating);
|
|
|
|
if (what.visibility)
|
|
|
|
ui.visibility->setCurrentStars(displayed_dive.visibility);
|
|
|
|
if (what.gps)
|
2015-01-19 05:17:01 +00:00
|
|
|
updateGpsCoordinates();
|
2014-08-17 14:26:09 +00:00
|
|
|
if (what.tags) {
|
|
|
|
char buf[1024];
|
|
|
|
taglist_get_tagstring(displayed_dive.tag_list, buf, 1024);
|
|
|
|
ui.tagWidget->setText(QString(buf));
|
|
|
|
}
|
|
|
|
if (what.cylinders) {
|
|
|
|
cylindersModel->updateDive();
|
|
|
|
cylindersModel->changed = true;
|
|
|
|
}
|
|
|
|
if (what.weights) {
|
|
|
|
weightModel->updateDive();
|
|
|
|
weightModel->changed = true;
|
|
|
|
}
|
|
|
|
}
|