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"
|
2013-05-07 03:36:37 +00:00
|
|
|
#include "../helpers.h"
|
|
|
|
#include "../statistics.h"
|
2013-05-19 03:09:36 +00:00
|
|
|
#include "divelistview.h"
|
2013-05-22 17:11:49 +00:00
|
|
|
#include "modeldelegates.h"
|
2013-06-05 02:39:40 +00:00
|
|
|
#include "globe.h"
|
2013-08-13 13:49:59 +00:00
|
|
|
#include "completionmodels.h"
|
2013-09-19 04:33:39 +00:00
|
|
|
#include "diveplanner.h"
|
2013-11-19 22:16:33 +00:00
|
|
|
#include "divelist.h"
|
2013-10-05 16:48:26 +00:00
|
|
|
#include "qthelper.h"
|
2014-03-07 15:42:13 +00:00
|
|
|
#include "display.h"
|
2013-04-13 13:17:59 +00:00
|
|
|
|
|
|
|
#include <QLabel>
|
2013-08-13 13:49:59 +00:00
|
|
|
#include <QCompleter>
|
2013-05-18 23:42:59 +00:00
|
|
|
#include <QDebug>
|
2013-06-14 16:17:46 +00:00
|
|
|
#include <QSet>
|
2013-11-28 11:17:30 +00:00
|
|
|
#include <QSettings>
|
2013-09-02 19:21:08 +00:00
|
|
|
#include <QTableView>
|
2013-08-16 18:38:18 +00:00
|
|
|
#include <QPalette>
|
2013-12-12 01:08:56 +00:00
|
|
|
#include <QScrollBar>
|
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()),
|
|
|
|
editMode(NONE)
|
2013-04-07 22:20:43 +00:00
|
|
|
{
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.setupUi(this);
|
2014-02-09 18:49:15 +00:00
|
|
|
|
|
|
|
memset(&multiEditEquipmentPlaceholder, 0, sizeof(multiEditEquipmentPlaceholder));
|
|
|
|
|
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
|
|
|
|
2013-12-02 17:33:00 +00:00
|
|
|
QAction *action = new QAction(tr("Save"), this);
|
|
|
|
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
|
|
|
|
|
|
|
action = new QAction(tr("Cancel"), this);
|
|
|
|
connect(action, SIGNAL(triggered(bool)), this, SLOT(rejectChanges()));
|
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);
|
|
|
|
ui.dateTimeEdit->installEventFilter(this);
|
2013-11-02 01:20:02 +00:00
|
|
|
ui.tagWidget->installEventFilter(this);
|
2013-10-03 18:54:25 +00:00
|
|
|
|
|
|
|
QList<QObject *> statisticsTabWidgets = ui.statisticsTab->children();
|
2014-02-28 04:09:57 +00:00
|
|
|
Q_FOREACH(QObject * obj, statisticsTabWidgets) {
|
|
|
|
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"));
|
|
|
|
ui.cylinders->setBtnToolTip(tr("Add Cylinder"));
|
|
|
|
connect(ui.cylinders, SIGNAL(addButtonClicked()), this, SLOT(addCylinder_clicked()));
|
|
|
|
|
|
|
|
ui.weights->setTitle(tr("Weights"));
|
|
|
|
ui.weights->setBtnToolTip(tr("Add Weight System"));
|
|
|
|
connect(ui.weights, SIGNAL(addButtonClicked()), this, SLOT(addWeight_clicked()));
|
|
|
|
|
|
|
|
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));
|
|
|
|
ui.weights->view()->setItemDelegateForColumn(WeightModel::TYPE, new WSInfoDelegate(this));
|
2014-03-22 14:13:58 +00:00
|
|
|
#ifdef ENABLE_PLANNER
|
|
|
|
ui.cylinders->view()->setColumnHidden(CylindersModel::DEPTH, true);
|
|
|
|
#endif
|
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-02-28 04:09:57 +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
|
|
|
}
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
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-03-11 03:49:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::updateTextLabels(bool showUnits)
|
|
|
|
{
|
2014-04-05 16:03:45 +00:00
|
|
|
if (showUnits) {
|
2014-03-17 21:52:42 +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-03-17 21:52:42 +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
|
|
|
{
|
2013-12-27 16:18:53 +00:00
|
|
|
if (current_dive == NULL || editMode != NONE)
|
2013-08-13 11:34:04 +00:00
|
|
|
return;
|
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-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-05-01 17:47:52 +00:00
|
|
|
if (amount_selected == 1)
|
2014-05-07 21:01:05 +00:00
|
|
|
MainWindow::instance()->globe()->prepareForGetDiveCoordinates();
|
2013-09-19 00:56:53 +00:00
|
|
|
// We may be editing one or more dives here. backup everything.
|
|
|
|
notesBackup.clear();
|
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."));
|
2013-10-03 18:54:25 +00:00
|
|
|
notesBackup[NULL].notes = ui.notes->toPlainText();
|
|
|
|
notesBackup[NULL].location = ui.location->text();
|
2013-09-19 00:56:53 +00:00
|
|
|
editMode = TRIP;
|
|
|
|
} else {
|
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-09-19 00:56:53 +00:00
|
|
|
|
|
|
|
// We may be editing one or more dives here. backup everything.
|
|
|
|
struct dive *mydive;
|
|
|
|
for (int i = 0; i < dive_table.nr; i++) {
|
|
|
|
mydive = get_dive(i);
|
|
|
|
if (!mydive)
|
|
|
|
continue;
|
|
|
|
if (!mydive->selected)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
notesBackup[mydive].buddy = QString(mydive->buddy);
|
|
|
|
notesBackup[mydive].suit = QString(mydive->suit);
|
|
|
|
notesBackup[mydive].notes = QString(mydive->notes);
|
|
|
|
notesBackup[mydive].divemaster = QString(mydive->divemaster);
|
|
|
|
notesBackup[mydive].location = QString(mydive->location);
|
|
|
|
notesBackup[mydive].rating = mydive->rating;
|
|
|
|
notesBackup[mydive].visibility = mydive->visibility;
|
|
|
|
notesBackup[mydive].latitude = mydive->latitude;
|
|
|
|
notesBackup[mydive].longitude = mydive->longitude;
|
2014-02-28 04:09:57 +00:00
|
|
|
notesBackup[mydive].coordinates = ui.coordinates->text();
|
2013-09-20 23:41:42 +00:00
|
|
|
notesBackup[mydive].airtemp = get_temperature_string(mydive->airtemp, true);
|
|
|
|
notesBackup[mydive].watertemp = get_temperature_string(mydive->watertemp, true);
|
2013-11-30 07:35:15 +00:00
|
|
|
notesBackup[mydive].datetime = QDateTime::fromTime_t(mydive->when).toUTC().toString();
|
2013-11-02 01:20:02 +00:00
|
|
|
char buf[1024];
|
|
|
|
taglist_get_tagstring(mydive->tag_list, buf, 1024);
|
|
|
|
notesBackup[mydive].tags = QString(buf);
|
2013-09-25 17:10:15 +00:00
|
|
|
|
|
|
|
// maybe this is a place for memset?
|
2014-02-12 14:07:32 +00:00
|
|
|
for (int j = 0; j < MAX_CYLINDERS; j++) {
|
|
|
|
notesBackup[mydive].cylinders[j] = mydive->cylinder[j];
|
2013-09-25 17:10:15 +00:00
|
|
|
}
|
2014-02-12 14:07:32 +00:00
|
|
|
for (int j = 0; j < MAX_WEIGHTSYSTEMS; j++) {
|
|
|
|
notesBackup[mydive].weightsystem[j] = mydive->weightsystem[j];
|
2013-09-25 17:10:15 +00:00
|
|
|
}
|
2013-09-19 00:56:53 +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
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
bool MainTab::eventFilter(QObject *object, QEvent *event)
|
2013-05-19 14:45:01 +00:00
|
|
|
{
|
2013-12-19 21:45:54 +00:00
|
|
|
if (!isEnabled())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (editMode != NONE)
|
|
|
|
return false;
|
2013-12-14 05:15:07 +00:00
|
|
|
// for the dateTimeEdit widget we need to ignore Wheel events as well (as long as we aren't editing)
|
2013-12-19 21:45:54 +00:00
|
|
|
if (object->objectName() == "dateTimeEdit" &&
|
2013-12-14 05:15:07 +00:00
|
|
|
(event->type() == QEvent::FocusIn || event->type() == QEvent::Wheel))
|
|
|
|
return true;
|
|
|
|
// MouseButtonPress in any widget (not all will ever get this), KeyPress in the dateTimeEdit,
|
|
|
|
// FocusIn for the starWidgets or RequestSoftwareInputPanel for tagWidget start the editing
|
2013-12-19 21:45:54 +00:00
|
|
|
if ((event->type() == QEvent::MouseButtonPress) ||
|
2013-12-14 05:15:07 +00:00
|
|
|
(event->type() == QEvent::KeyPress && object == ui.dateTimeEdit) ||
|
2014-01-19 17:36:51 +00:00
|
|
|
(event->type() == QEvent::FocusIn && (object == ui.rating || object == ui.visibility || object == ui.buddy || object == ui.tagWidget || object || ui.divemaster))) {
|
2013-09-19 01:38:38 +00:00
|
|
|
tabBar()->setTabIcon(currentIndex(), QIcon(":warning"));
|
2013-08-13 11:34:04 +00:00
|
|
|
enableEdition();
|
2013-05-19 14:45:01 +00:00
|
|
|
}
|
2013-08-13 11:34:04 +00:00
|
|
|
return false; // don't "eat" the event.
|
2013-05-19 14:45:01 +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
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::clearInfo()
|
|
|
|
{
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.sacText->clear();
|
|
|
|
ui.otuText->clear();
|
|
|
|
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) \
|
|
|
|
if (!d || !d->field) \
|
|
|
|
ui.field->setText(""); \
|
|
|
|
else \
|
|
|
|
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) \
|
|
|
|
if (!d || d->field.mkelvin == 0) \
|
|
|
|
ui.field->setText(""); \
|
|
|
|
else \
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-05-06 16:23:14 +00:00
|
|
|
void MainTab::updateDiveInfo(int dive)
|
|
|
|
{
|
2013-11-12 07:33:27 +00:00
|
|
|
// don't execute this while adding a dive
|
2013-12-25 21:02:38 +00:00
|
|
|
if (editMode == ADD || editMode == MANUALLY_ADDED_DIVE)
|
2013-11-12 07:33:27 +00:00
|
|
|
return;
|
2013-09-22 15:19:05 +00:00
|
|
|
if (!isEnabled() && dive != -1)
|
2013-09-19 00:56:53 +00:00
|
|
|
setEnabled(true);
|
2013-09-22 15:19:05 +00:00
|
|
|
if (isEnabled() && dive == -1)
|
|
|
|
setEnabled(false);
|
2013-08-16 16:31:52 +00:00
|
|
|
editMode = NONE;
|
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-05-06 16:23:14 +00:00
|
|
|
struct dive *d = get_dive(dive);
|
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();
|
2013-05-19 15:08:29 +00:00
|
|
|
process_all_dives(d, &prevd);
|
2013-08-16 16:31:52 +00:00
|
|
|
|
2013-05-06 17:16:16 +00:00
|
|
|
UPDATE_TEXT(d, notes);
|
|
|
|
UPDATE_TEXT(d, location);
|
|
|
|
UPDATE_TEXT(d, suit);
|
|
|
|
UPDATE_TEXT(d, divemaster);
|
|
|
|
UPDATE_TEXT(d, buddy);
|
2013-09-20 23:41:42 +00:00
|
|
|
UPDATE_TEMP(d, airtemp);
|
|
|
|
UPDATE_TEMP(d, watertemp);
|
2013-05-08 19:08:00 +00:00
|
|
|
if (d) {
|
2013-11-11 23:21:45 +00:00
|
|
|
updateGpsCoordinates(d);
|
2013-11-30 07:35:15 +00:00
|
|
|
ui.dateTimeEdit->setDateTime(QDateTime::fromTime_t(d->when).toUTC());
|
2014-02-12 14:22:54 +00:00
|
|
|
if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
|
2013-11-25 19:05:09 +00:00
|
|
|
setTabText(0, tr("Trip Notes"));
|
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);
|
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-02-12 14:22:54 +00:00
|
|
|
dive_trip_t *currentTrip = *MainWindow::instance()->dive_list()->selectedTrips().begin();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.LocationLabel->setText(tr("Trip Location"));
|
|
|
|
ui.location->setText(currentTrip->location);
|
|
|
|
ui.NotesLabel->setText(tr("Trip Notes"));
|
|
|
|
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 {
|
2013-11-25 19:05:09 +00:00
|
|
|
setTabText(0, tr("Dive Notes"));
|
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);
|
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 */
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.rating->setCurrentStars(d->rating);
|
|
|
|
ui.visibility->setCurrentStars(d->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);
|
|
|
|
multiEditEquipmentPlaceholder = *d;
|
|
|
|
cylindersModel->setDive(&multiEditEquipmentPlaceholder);
|
|
|
|
weightModel->setDive(&multiEditEquipmentPlaceholder);
|
|
|
|
taglist_get_tagstring(d->tag_list, buf, 1024);
|
|
|
|
ui.tagWidget->setText(QString(buf));
|
2013-06-14 16:17:46 +00:00
|
|
|
}
|
2014-01-15 08:30:42 +00:00
|
|
|
ui.maximumDepthText->setText(get_depth_string(d->maxdepth, true));
|
|
|
|
ui.averageDepthText->setText(get_depth_string(d->meandepth, true));
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.otuText->setText(QString("%1").arg(d->otu));
|
2014-01-15 08:30:42 +00:00
|
|
|
ui.waterTemperatureText->setText(get_temperature_string(d->watertemp, true));
|
|
|
|
ui.airTemperatureText->setText(get_temperature_string(d->airtemp, true));
|
2013-12-09 21:37:49 +00:00
|
|
|
volume_t gases[MAX_CYLINDERS] = {};
|
2013-11-19 23:29:32 +00:00
|
|
|
get_gas_used(d, gases);
|
2014-01-15 08:30:42 +00:00
|
|
|
QString volumes = get_volume_string(gases[0], true);
|
2013-11-20 06:50:02 +00:00
|
|
|
int mean[MAX_CYLINDERS], duration[MAX_CYLINDERS];
|
2014-03-17 15:19:09 +00:00
|
|
|
per_cylinder_mean_depth(d, select_dc(d), mean, duration);
|
2013-11-20 06:50:02 +00:00
|
|
|
volume_t sac;
|
|
|
|
QString SACs;
|
|
|
|
if (mean[0] && duration[0]) {
|
2014-02-11 21:08:29 +00:00
|
|
|
sac.mliter = gases[0].mliter / (depth_to_atm(mean[0], d) * duration[0] / 60.0);
|
2014-01-15 08:30:42 +00:00
|
|
|
SACs = get_volume_string(sac, true).append(tr("/min"));
|
2013-11-20 06:50:02 +00:00
|
|
|
} else {
|
|
|
|
SACs = QString(tr("unknown"));
|
|
|
|
}
|
2014-02-28 04:09:57 +00:00
|
|
|
for (int i = 1; i < MAX_CYLINDERS && gases[i].mliter != 0; i++) {
|
2014-01-15 08:30:42 +00:00
|
|
|
volumes.append("\n" + get_volume_string(gases[i], true));
|
2013-11-20 06:50:02 +00:00
|
|
|
if (duration[i]) {
|
2014-02-11 21:08:29 +00:00
|
|
|
sac.mliter = gases[i].mliter / (depth_to_atm(mean[i], d) * duration[i] / 60);
|
2014-01-15 08:30:42 +00:00
|
|
|
SACs.append("\n" + get_volume_string(sac, true).append(tr("/min")));
|
2013-11-20 06:50:02 +00:00
|
|
|
} else {
|
|
|
|
SACs.append("\n");
|
|
|
|
}
|
|
|
|
}
|
2013-11-19 23:29:32 +00:00
|
|
|
ui.gasUsedText->setText(volumes);
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.oxygenHeliumText->setText(get_gaslist(d));
|
|
|
|
ui.dateText->setText(get_short_dive_date_string(d->when));
|
|
|
|
ui.diveTimeText->setText(QString::number((int)((d->duration.seconds + 30) / 60)));
|
2013-05-19 15:08:29 +00:00
|
|
|
if (prevd)
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.surfaceIntervalText->setText(get_time_string(d->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();
|
2013-05-08 19:08:00 +00:00
|
|
|
if (d->surface_pressure.mbar)
|
|
|
|
/* this is ALWAYS displayed in mbar */
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.airPressureText->setText(QString("%1mbar").arg(d->surface_pressure.mbar));
|
2013-05-08 19:08:00 +00:00
|
|
|
else
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.airPressureText->clear();
|
2013-10-10 08:16:32 +00:00
|
|
|
if (d->salinity)
|
2014-02-28 04:09:57 +00:00
|
|
|
ui.salinityText->setText(QString("%1g/l").arg(d->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));
|
|
|
|
ui.depthLimits->setAverage(get_depth_string(stats_selection.avg_depth, true));
|
|
|
|
ui.sacLimits->setMaximum(get_volume_string(stats_selection.max_sac, true).append(tr("/min")));
|
|
|
|
ui.sacLimits->setMinimum(get_volume_string(stats_selection.min_sac, true).append(tr("/min")));
|
|
|
|
ui.sacLimits->setAverage(get_volume_string(stats_selection.avg_sac, true).append(tr("/min")));
|
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
|
|
|
}
|
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));
|
|
|
|
ui.timeLimits->setMaximum(get_time_string(stats_selection.longest_time.seconds, 0));
|
|
|
|
ui.timeLimits->setMinimum(get_time_string(stats_selection.shortest_time.seconds, 0));
|
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-09-22 14:33:09 +00:00
|
|
|
/* turns out this is non-trivial for a dateTimeEdit... this is a partial hack */
|
2014-02-28 04:09:57 +00:00
|
|
|
QLineEdit *le = ui.dateTimeEdit->findChild<QLineEdit *>();
|
2013-09-22 14:33:09 +00:00
|
|
|
le->setText("");
|
2013-05-08 19:08:00 +00:00
|
|
|
}
|
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
|
|
|
|
#define EDIT_SELECTED_DIVES(WHAT) \
|
|
|
|
do { \
|
|
|
|
struct dive *mydive = NULL; \
|
|
|
|
if (editMode == NONE) \
|
|
|
|
return; \
|
|
|
|
\
|
|
|
|
for (int _i = 0; _i < dive_table.nr; _i++) { \
|
|
|
|
mydive = get_dive(_i); \
|
|
|
|
if (!mydive || mydive == current_dive)\
|
|
|
|
continue; \
|
|
|
|
if (!mydive->selected) \
|
|
|
|
continue; \
|
|
|
|
\
|
|
|
|
WHAT; \
|
|
|
|
} \
|
|
|
|
mydive = current_dive; \
|
|
|
|
WHAT; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
// this macro is rather fragile and is intended to be used as WHAT inside
|
|
|
|
// an invocation of EDIT_SELECTED_DIVES(WHAT)
|
|
|
|
#define EDIT_TEXT(what, text) \
|
|
|
|
if (same_string(mydive->what, current_dive->what)) { \
|
|
|
|
QByteArray textByteArray = text.toUtf8(); \
|
|
|
|
free(mydive->what); \
|
|
|
|
mydive->what = strdup(textByteArray.data()); \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define EDIT_VALUE(what, value) \
|
|
|
|
if (mydive->what == current_dive->what) { \
|
|
|
|
mydive->what = value; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define EDIT_TRIP_TEXT(what, text) \
|
|
|
|
QByteArray textByteArray = text.toUtf8(); \
|
|
|
|
free(what); \
|
|
|
|
what = strdup(textByteArray.data());
|
|
|
|
|
2013-09-19 00:56:53 +00:00
|
|
|
void MainTab::acceptChanges()
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->setEnabled(true);
|
2014-03-19 05:24:37 +00:00
|
|
|
MainWindow::instance()->setFocus();
|
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-12-28 01:26:22 +00:00
|
|
|
ui.equipmentTab->setEnabled(true);
|
2013-09-19 00:56:53 +00:00
|
|
|
/* now figure out if things have changed */
|
2014-02-12 14:22:54 +00:00
|
|
|
if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
|
2013-10-03 18:54:25 +00:00
|
|
|
if (notesBackup[NULL].notes != ui.notes->toPlainText() ||
|
2014-02-28 04:09:57 +00:00
|
|
|
notesBackup[NULL].location != ui.location->text())
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2013-05-19 16:00:57 +00:00
|
|
|
} else {
|
2013-09-19 00:56:53 +00:00
|
|
|
struct dive *curr = current_dive;
|
2013-09-19 16:37:44 +00:00
|
|
|
//Reset coordinates field, in case it contains garbage.
|
2013-11-11 23:21:45 +00:00
|
|
|
updateGpsCoordinates(curr);
|
2013-10-03 18:54:25 +00:00
|
|
|
if (notesBackup[curr].buddy != ui.buddy->text() ||
|
2014-02-28 04:09:57 +00:00
|
|
|
notesBackup[curr].suit != ui.suit->text() ||
|
|
|
|
notesBackup[curr].notes != ui.notes->toPlainText() ||
|
|
|
|
notesBackup[curr].divemaster != ui.divemaster->text() ||
|
|
|
|
notesBackup[curr].location != ui.location->text() ||
|
|
|
|
notesBackup[curr].coordinates != ui.coordinates->text() ||
|
|
|
|
notesBackup[curr].rating != ui.visibility->currentStars() ||
|
|
|
|
notesBackup[curr].airtemp != ui.airtemp->text() ||
|
|
|
|
notesBackup[curr].watertemp != ui.watertemp->text() ||
|
|
|
|
notesBackup[curr].datetime != ui.dateTimeEdit->dateTime().toString() ||
|
|
|
|
notesBackup[curr].visibility != ui.rating->currentStars() ||
|
|
|
|
notesBackup[curr].tags != ui.tagWidget->text()) {
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2013-09-20 23:41:42 +00:00
|
|
|
}
|
2014-05-07 20:00:33 +00:00
|
|
|
if (notesBackup[curr].location != ui.location->text()) {
|
|
|
|
EDIT_SELECTED_DIVES(EDIT_TEXT(location, ui.location->text()));
|
|
|
|
// if we have a location text and haven't edited the coordinates, try to fill the coordinates
|
|
|
|
// from the existing dives
|
|
|
|
if (!ui.location->text().trimmed().isEmpty() &&
|
|
|
|
(!ui.coordinates->isModified() ||
|
|
|
|
ui.coordinates->text().trimmed().isEmpty())) {
|
|
|
|
struct dive *dive;
|
|
|
|
int i = 0;
|
|
|
|
for_each_dive(i, dive) {
|
|
|
|
QString location(dive->location);
|
|
|
|
if (location == ui.location->text() &&
|
|
|
|
(dive->latitude.udeg || dive->longitude.udeg)) {
|
|
|
|
EDIT_SELECTED_DIVES(if (same_string(mydive->location, dive->location)) {
|
|
|
|
mydive->latitude = dive->latitude;
|
|
|
|
mydive->longitude = dive->longitude;
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-10-03 18:54:25 +00:00
|
|
|
if (notesBackup[curr].location != ui.location->text() ||
|
2014-02-28 04:09:57 +00:00
|
|
|
notesBackup[curr].coordinates != ui.coordinates->text()) {
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->globe()->reload();
|
2013-06-14 16:17:46 +00:00
|
|
|
}
|
2013-09-25 17:57:41 +00:00
|
|
|
|
2013-11-02 01:20:02 +00:00
|
|
|
if (notesBackup[curr].tags != ui.tagWidget->text())
|
|
|
|
saveTags();
|
2013-11-14 09:36:21 +00:00
|
|
|
if (editMode == MANUALLY_ADDED_DIVE) {
|
|
|
|
DivePlannerPointsModel::instance()->copyCylinders(curr);
|
|
|
|
} else if (editMode != ADD && cylindersModel->changed) {
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2014-02-28 04:09:57 +00:00
|
|
|
Q_FOREACH(dive * d, notesBackup.keys()) {
|
2013-09-25 17:59:11 +00:00
|
|
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
2013-12-14 17:20:37 +00:00
|
|
|
if (notesBackup.keys().count() > 1)
|
|
|
|
// only copy the cylinder type, none of the other values
|
|
|
|
d->cylinder[i].type = multiEditEquipmentPlaceholder.cylinder[i].type;
|
|
|
|
else
|
|
|
|
d->cylinder[i] = multiEditEquipmentPlaceholder.cylinder[i];
|
2013-09-25 17:57:41 +00:00
|
|
|
}
|
|
|
|
}
|
2014-03-24 18:15:19 +00:00
|
|
|
MainWindow::instance()->graphics()->replot();
|
2013-09-25 17:57:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (weightModel->changed) {
|
2014-01-15 08:30:42 +00:00
|
|
|
mark_divelist_changed(true);
|
2014-02-28 04:09:57 +00:00
|
|
|
Q_FOREACH(dive * d, notesBackup.keys()) {
|
2013-10-01 13:52:23 +00:00
|
|
|
for (int i = 0; i < MAX_WEIGHTSYSTEMS; i++) {
|
|
|
|
d->weightsystem[i] = multiEditEquipmentPlaceholder.weightsystem[i];
|
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
|
|
|
// clean up the dive data (get duration, depth information from samples)
|
|
|
|
fixup_dive(current_dive);
|
2013-09-22 14:00:14 +00:00
|
|
|
if (dive_table.nr == 1)
|
|
|
|
current_dive->number = 1;
|
2013-11-12 05:21:50 +00:00
|
|
|
else if (selected_dive == dive_table.nr - 1 && get_dive(dive_table.nr - 2)->number)
|
2013-09-20 12:14:25 +00:00
|
|
|
current_dive->number = get_dive(dive_table.nr - 2)->number + 1;
|
2013-09-19 04:33:39 +00:00
|
|
|
DivePlannerPointsModel::instance()->cancelPlan();
|
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
|
|
|
}
|
2013-12-02 04:17:17 +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
|
2014-02-28 04:09:57 +00:00
|
|
|
Q_FOREACH(dive * d, notesBackup.keys()) {
|
2013-12-03 23:17:38 +00:00
|
|
|
if (d)
|
|
|
|
fixup_dive(d);
|
2013-12-02 04:17:17 +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-04-03 17:11:39 +00:00
|
|
|
// it's tricky to keep the right dive selected;
|
|
|
|
// first remember which one is selected in the current sort order
|
|
|
|
// and unselect all dives
|
|
|
|
int rememberSelected = selected_dive;
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->unselectDives();
|
2014-04-03 17:11:39 +00:00
|
|
|
struct dive *d = get_dive(rememberSelected);
|
|
|
|
// mark the previously selected dive as remembered (abusing the selected flag)
|
2013-12-10 05:17:15 +00:00
|
|
|
// and then clear that flag out on the other side of the sort_table()
|
2013-12-03 22:34:05 +00:00
|
|
|
d->selected = true;
|
|
|
|
sort_table(&dive_table);
|
2014-04-03 17:11:39 +00:00
|
|
|
for_each_dive(rememberSelected, d) {
|
2013-12-10 05:17:15 +00:00
|
|
|
if (d->selected) {
|
|
|
|
d->selected = false;
|
|
|
|
break;
|
|
|
|
}
|
2013-12-03 22:34:05 +00:00
|
|
|
}
|
2014-04-03 17:11:39 +00:00
|
|
|
// refreshDisplay() will select the top dive if no dive was
|
|
|
|
// selected - but that may not be the right one, so select the one
|
|
|
|
// we remembered instead
|
|
|
|
MainWindow::instance()->dive_list()->selectDive(rememberSelected, 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();
|
2013-12-10 05:17:15 +00:00
|
|
|
} else {
|
2013-12-03 23:25:20 +00:00
|
|
|
editMode = NONE;
|
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-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->refreshDisplay();
|
|
|
|
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();
|
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);
|
|
|
|
ui.watertemp->setPalette(p);
|
|
|
|
ui.dateTimeEdit->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());
|
|
|
|
|
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;
|
2013-09-19 01:38:38 +00:00
|
|
|
tabBar()->setTabIcon(0, QIcon()); // Notes
|
|
|
|
tabBar()->setTabIcon(1, QIcon()); // Equipment
|
2013-09-19 02:23:04 +00:00
|
|
|
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->setEnabled(true);
|
|
|
|
if (MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
|
2014-02-28 04:09:57 +00:00
|
|
|
ui.notes->setText(notesBackup[NULL].notes);
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.location->setText(notesBackup[NULL].location);
|
2013-11-08 09:15:04 +00:00
|
|
|
} else {
|
2013-11-12 05:41:29 +00:00
|
|
|
if (lastMode == ADD) {
|
2013-09-24 19:32:18 +00:00
|
|
|
// clean up
|
|
|
|
DivePlannerPointsModel::instance()->cancelPlan();
|
2014-02-28 04:09:57 +00:00
|
|
|
} else if (lastMode == MANUALLY_ADDED_DIVE) {
|
2013-11-18 19:55:56 +00:00
|
|
|
// when we tried to edit a manually added dive, we destroyed
|
|
|
|
// the dive we edited, so let's just restore it from backup
|
|
|
|
DivePlannerPointsModel::instance()->restoreBackupDive();
|
2013-11-01 18:06:03 +00:00
|
|
|
}
|
2013-08-16 16:31:52 +00:00
|
|
|
struct dive *curr = current_dive;
|
2014-02-28 04:09:57 +00:00
|
|
|
ui.notes->setText(notesBackup[curr].notes);
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.location->setText(notesBackup[curr].location);
|
|
|
|
ui.buddy->setText(notesBackup[curr].buddy);
|
|
|
|
ui.suit->setText(notesBackup[curr].suit);
|
|
|
|
ui.divemaster->setText(notesBackup[curr].divemaster);
|
|
|
|
ui.rating->setCurrentStars(notesBackup[curr].rating);
|
|
|
|
ui.visibility->setCurrentStars(notesBackup[curr].visibility);
|
|
|
|
ui.airtemp->setText(notesBackup[curr].airtemp);
|
|
|
|
ui.watertemp->setText(notesBackup[curr].watertemp);
|
2013-11-02 01:20:02 +00:00
|
|
|
ui.tagWidget->setText(notesBackup[curr].tags);
|
2013-11-13 13:23:59 +00:00
|
|
|
// it's a little harder to do the right thing for the date time widget
|
|
|
|
if (curr) {
|
2013-11-17 11:31:09 +00:00
|
|
|
ui.dateTimeEdit->setDateTime(QDateTime::fromString(notesBackup[curr].datetime));
|
2013-11-13 13:23:59 +00:00
|
|
|
} else {
|
2014-02-28 04:09:57 +00:00
|
|
|
QLineEdit *le = ui.dateTimeEdit->findChild<QLineEdit *>();
|
2013-11-13 13:23:59 +00:00
|
|
|
le->setText("");
|
|
|
|
}
|
2013-08-16 16:31:52 +00:00
|
|
|
|
|
|
|
struct dive *mydive;
|
|
|
|
for (int i = 0; i < dive_table.nr; i++) {
|
|
|
|
mydive = get_dive(i);
|
|
|
|
if (!mydive)
|
|
|
|
continue;
|
|
|
|
if (!mydive->selected)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
QByteArray textByteArray;
|
|
|
|
EDIT_TEXT2(mydive->buddy, notesBackup[mydive].buddy);
|
|
|
|
EDIT_TEXT2(mydive->suit, notesBackup[mydive].suit);
|
|
|
|
EDIT_TEXT2(mydive->notes, notesBackup[mydive].notes);
|
|
|
|
EDIT_TEXT2(mydive->divemaster, notesBackup[mydive].divemaster);
|
|
|
|
EDIT_TEXT2(mydive->location, notesBackup[mydive].location);
|
2013-09-17 19:50:15 +00:00
|
|
|
mydive->latitude = notesBackup[mydive].latitude;
|
|
|
|
mydive->longitude = notesBackup[mydive].longitude;
|
2013-08-16 16:31:52 +00:00
|
|
|
mydive->rating = notesBackup[mydive].rating;
|
|
|
|
mydive->visibility = notesBackup[mydive].visibility;
|
2013-09-25 17:10:15 +00:00
|
|
|
|
|
|
|
// maybe this is a place for memset?
|
2014-02-12 14:07:32 +00:00
|
|
|
for (int j = 0; j < MAX_CYLINDERS; j++) {
|
|
|
|
mydive->cylinder[j] = notesBackup[mydive].cylinders[j];
|
2013-09-25 17:10:15 +00:00
|
|
|
}
|
2014-02-12 14:07:32 +00:00
|
|
|
for (int j = 0; j < MAX_WEIGHTSYSTEMS; j++) {
|
|
|
|
mydive->weightsystem[j] = notesBackup[mydive].weightsystem[j];
|
2013-09-25 17:10:15 +00:00
|
|
|
}
|
2013-08-16 16:31:52 +00:00
|
|
|
}
|
2013-11-11 23:21:45 +00:00
|
|
|
updateGpsCoordinates(curr);
|
2013-11-14 08:52:03 +00:00
|
|
|
if (lastMode == ADD) {
|
|
|
|
delete_single_dive(selected_dive);
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->reload(DiveTripModel::CURRENT);
|
|
|
|
MainWindow::instance()->dive_list()->restoreSelection();
|
2013-11-14 08:52:03 +00:00
|
|
|
}
|
2013-11-06 01:15:19 +00:00
|
|
|
if (selected_dive >= 0) {
|
2013-10-09 06:24:44 +00:00
|
|
|
multiEditEquipmentPlaceholder = *get_dive(selected_dive);
|
|
|
|
cylindersModel->setDive(&multiEditEquipmentPlaceholder);
|
|
|
|
weightModel->setDive(&multiEditEquipmentPlaceholder);
|
|
|
|
} else {
|
|
|
|
cylindersModel->clear();
|
|
|
|
weightModel->clear();
|
2013-11-13 13:23:59 +00:00
|
|
|
setEnabled(false);
|
2013-10-09 06:24:44 +00:00
|
|
|
}
|
2013-06-14 16:17:46 +00:00
|
|
|
}
|
2013-09-19 02:23:04 +00:00
|
|
|
|
2013-12-03 20:44:48 +00:00
|
|
|
hideMessage();
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->dive_list()->setEnabled(true);
|
2013-08-16 16:31:52 +00:00
|
|
|
notesBackup.clear();
|
2013-09-25 17:36:59 +00:00
|
|
|
resetPallete();
|
2013-11-14 08:52:03 +00:00
|
|
|
editMode = NONE;
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->globe()->reload();
|
2013-11-12 05:41:29 +00:00
|
|
|
if (lastMode == ADD || lastMode == MANUALLY_ADDED_DIVE) {
|
2013-09-24 19:32:18 +00:00
|
|
|
// more clean up
|
|
|
|
updateDiveInfo(selected_dive);
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->showProfile();
|
2013-11-14 08:52:03 +00:00
|
|
|
// we already reloaded the divelist above, so don't recreate it or we'll lose the selection
|
2014-02-12 14:22:54 +00:00
|
|
|
MainWindow::instance()->refreshDisplay(false);
|
2013-09-20 03:58:53 +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()->setFocus();
|
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();
|
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-02-28 04:09:57 +00:00
|
|
|
void markChangedWidget(QWidget *w)
|
|
|
|
{
|
2013-08-16 18:38:18 +00:00
|
|
|
QPalette p;
|
2013-12-24 11:49:38 +00:00
|
|
|
qreal h, s, l, a;
|
|
|
|
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);
|
|
|
|
}
|
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
|
|
|
{
|
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-05-06 17:19:43 +00:00
|
|
|
EDIT_SELECTED_DIVES(EDIT_TEXT(buddy, text));
|
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
|
|
|
{
|
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-05-06 17:19:43 +00:00
|
|
|
EDIT_SELECTED_DIVES(EDIT_TEXT(divemaster, text));
|
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
|
|
|
{
|
2014-05-06 20:56:46 +00:00
|
|
|
EDIT_SELECTED_DIVES(EDIT_VALUE(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
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_watertemp_textChanged(const QString &text)
|
2013-09-20 23:41:42 +00:00
|
|
|
{
|
2014-05-06 20:56:46 +00:00
|
|
|
EDIT_SELECTED_DIVES(EDIT_VALUE(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-04-13 16:19:15 +00:00
|
|
|
void MainTab::validate_temp_field(QLineEdit *tempField,const QString &text)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
|
|
|
// changing the time stamp on multiple dives really needs to be a relative shift
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_dateTimeEdit_dateTimeChanged(const QDateTime &datetime)
|
2013-09-20 23:41:42 +00:00
|
|
|
{
|
2013-11-30 07:35:15 +00:00
|
|
|
QDateTime dateTimeUtc(datetime);
|
|
|
|
dateTimeUtc.setTimeSpec(Qt::UTC);
|
2014-05-06 20:56:46 +00:00
|
|
|
time_t offset = current_dive->when - dateTimeUtc.toTime_t();
|
|
|
|
EDIT_SELECTED_DIVES(mydive->when -= offset);
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.dateTimeEdit);
|
2013-09-20 23:41:42 +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()
|
|
|
|
{
|
|
|
|
EDIT_SELECTED_DIVES(
|
2014-02-28 04:09:57 +00:00
|
|
|
QString tag;
|
Get rid of crazy empty tag_list element at the start
So this is totally unrelated to the git repository format, except for
the fact that I noticed it while writing the git saving code.
The subsurface divetag list handling is being stupid, and has a
initial dummy entry at the head of the list for no good reason.
I say "no good reason", because there *is* a reason for it: it allows
code to avoid the special case of empty list and adding entries to
before the first entry etc etc. But that reason is a really *bad*
reason, because it's valid only because people don't understand basic
list manipulation and pointers to pointers.
So get rid of the dummy element, and do things right instead - by
passing a *pointer* to the list, instead of the list. And then when
traversing the list and looking for a place to insert things, don't go
to the next entry - just update the "pointer to pointer" to point to
the address of the next entry. Each entry in a C linked list is no
different than the list itself, so you can use the pointer to the
pointer to the next entry as a pointer to the list.
This is a pet peeve of mine. The real beauty of pointers can never be
understood unless you understand the indirection they allow. People
who grew up with Pascal and were corrupted by that mindset are
mentally stunted. Niklaus Wirth has a lot to answer for!
But never fear. You too can overcome that mental limitation, it just
needs some brain exercise. Reading this patch may help. In particular,
contemplate the new "taglist_add_divetag()".
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2014-03-10 17:18:13 +00:00
|
|
|
taglist_free(mydive->tag_list);
|
|
|
|
mydive->tag_list = NULL;
|
2014-02-28 04:09:57 +00:00
|
|
|
foreach(tag, ui.tagWidget->getBlockStringList())
|
Get rid of crazy empty tag_list element at the start
So this is totally unrelated to the git repository format, except for
the fact that I noticed it while writing the git saving code.
The subsurface divetag list handling is being stupid, and has a
initial dummy entry at the head of the list for no good reason.
I say "no good reason", because there *is* a reason for it: it allows
code to avoid the special case of empty list and adding entries to
before the first entry etc etc. But that reason is a really *bad*
reason, because it's valid only because people don't understand basic
list manipulation and pointers to pointers.
So get rid of the dummy element, and do things right instead - by
passing a *pointer* to the list, instead of the list. And then when
traversing the list and looking for a place to insert things, don't go
to the next entry - just update the "pointer to pointer" to point to
the address of the next entry. Each entry in a C linked list is no
different than the list itself, so you can use the pointer to the
pointer to the next entry as a pointer to the list.
This is a pet peeve of mine. The real beauty of pointers can never be
understood unless you understand the indirection they allow. People
who grew up with Pascal and were corrupted by that mindset are
mentally stunted. Niklaus Wirth has a lot to answer for!
But never fear. You too can overcome that mental limitation, it just
needs some brain exercise. Reading this patch may help. In particular,
contemplate the new "taglist_add_divetag()".
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2014-03-10 17:18:13 +00:00
|
|
|
taglist_add_tag(&mydive->tag_list, tag.toUtf8().data()););
|
2013-11-02 01:20:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::on_tagWidget_textChanged()
|
|
|
|
{
|
|
|
|
markChangedWidget(ui.tagWidget);
|
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_location_textChanged(const QString &text)
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.location);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
2014-02-28 04:09:57 +00:00
|
|
|
void MainTab::on_suit_textChanged(const QString &text)
|
2013-05-18 23:42:59 +00:00
|
|
|
{
|
2014-05-06 17:19:43 +00:00
|
|
|
EDIT_SELECTED_DIVES(EDIT_TEXT(suit, text));
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.suit);
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainTab::on_notes_textChanged()
|
|
|
|
{
|
2013-08-16 16:31:52 +00:00
|
|
|
if (editMode == NONE)
|
|
|
|
return;
|
2014-02-12 14:22:54 +00:00
|
|
|
if (editMode == TRIP && MainWindow::instance() && MainWindow::instance()->dive_list()->selectedTrips().count() == 1) {
|
2013-06-14 16:17:46 +00:00
|
|
|
// we are editing a trip
|
2014-02-12 14:22:54 +00:00
|
|
|
dive_trip_t *currentTrip = *MainWindow::instance()->dive_list()->selectedTrips().begin();
|
2014-05-06 17:19:43 +00:00
|
|
|
EDIT_TRIP_TEXT(currentTrip->notes, ui.notes->toPlainText());
|
2013-12-27 16:18:53 +00:00
|
|
|
} else if (editMode == DIVE || editMode == ADD || editMode == MANUALLY_ADDED_DIVE) {
|
2014-05-06 17:19:43 +00:00
|
|
|
EDIT_SELECTED_DIVES(EDIT_TEXT(notes, ui.notes->toPlainText()));
|
2013-06-14 16:17:46 +00:00
|
|
|
}
|
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
|
|
|
{
|
2013-12-23 22:56:40 +00:00
|
|
|
bool gpsChanged = false;
|
|
|
|
bool parsed = false;
|
|
|
|
EDIT_SELECTED_DIVES(gpsChanged |= gpsHasChanged(mydive, current_dive, text, &parsed));
|
2013-09-19 16:37:44 +00:00
|
|
|
if (gpsChanged) {
|
2013-10-03 18:54:25 +00:00
|
|
|
markChangedWidget(ui.coordinates);
|
2013-12-23 22:56:40 +00:00
|
|
|
} else if (!parsed) {
|
2013-09-19 16:37:44 +00:00
|
|
|
QPalette p;
|
|
|
|
p.setBrush(QPalette::Base, QColor(Qt::red).lighter());
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.coordinates->setPalette(p);
|
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)
|
|
|
|
{
|
2014-05-06 20:56:46 +00:00
|
|
|
EDIT_SELECTED_DIVES(EDIT_VALUE(rating, value));
|
2013-05-18 23:42:59 +00:00
|
|
|
}
|
2013-05-20 13:25:16 +00:00
|
|
|
|
|
|
|
void MainTab::on_visibility_valueChanged(int value)
|
|
|
|
{
|
2014-05-06 20:56:46 +00:00
|
|
|
EDIT_SELECTED_DIVES(EDIT_VALUE(visibility, value));
|
2013-05-20 13:25:16 +00:00
|
|
|
}
|
2013-06-16 17:36:23 +00:00
|
|
|
|
2014-05-06 20:56:46 +00:00
|
|
|
#undef EDIT_SELECTED_DIVES
|
|
|
|
#undef EDIT_TEXT
|
|
|
|
#undef EDIT_TRIP_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-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;
|
|
|
|
}
|
|
|
|
if (index.isValid() && index.column() != CylindersModel::REMOVE) {
|
|
|
|
if (editMode == NONE)
|
|
|
|
enableEdition();
|
2013-10-03 18:54:25 +00:00
|
|
|
ui.cylinders->edit(index);
|
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
|
|
|
|
|
|
|
QString MainTab::printGPSCoords(int lat, int lon)
|
|
|
|
{
|
|
|
|
unsigned int latdeg, londeg;
|
2013-12-31 22:14:55 +00:00
|
|
|
unsigned int latmin, lonmin;
|
2014-02-28 04:09:57 +00:00
|
|
|
double latsec, lonsec;
|
2013-10-07 18:48:14 +00:00
|
|
|
QString lath, lonh, result;
|
|
|
|
|
|
|
|
if (!lat && !lon)
|
|
|
|
return QString("");
|
|
|
|
|
|
|
|
lath = lat >= 0 ? tr("N") : tr("S");
|
|
|
|
lonh = lon >= 0 ? tr("E") : tr("W");
|
|
|
|
lat = abs(lat);
|
|
|
|
lon = abs(lon);
|
|
|
|
latdeg = lat / 1000000;
|
|
|
|
londeg = lon / 1000000;
|
2013-12-31 22:14:55 +00:00
|
|
|
latmin = (lat % 1000000) * 60;
|
|
|
|
lonmin = (lon % 1000000) * 60;
|
|
|
|
latsec = (latmin % 1000000) * 60;
|
|
|
|
lonsec = (lonmin % 1000000) * 60;
|
|
|
|
result.sprintf("%u%s%02d\'%06.3f\"%s %u%s%02d\'%06.3f\"%s",
|
|
|
|
latdeg, UTF8_DEGREE, latmin / 1000000, latsec / 1000000, lath.toUtf8().data(),
|
|
|
|
londeg, UTF8_DEGREE, lonmin / 1000000, lonsec / 1000000, lonh.toUtf8().data());
|
2013-10-07 18:48:14 +00:00
|
|
|
return result;
|
|
|
|
}
|
2013-11-11 23:21:45 +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));
|
|
|
|
}
|
|
|
|
|
2013-11-11 23:21:45 +00:00
|
|
|
void MainTab::updateGpsCoordinates(const struct dive *dive)
|
|
|
|
{
|
2013-11-13 13:23:59 +00:00
|
|
|
if (dive) {
|
|
|
|
ui.coordinates->setText(printGPSCoords(dive->latitude.udeg, dive->longitude.udeg));
|
|
|
|
ui.coordinates->setModified(dive->latitude.udeg || dive->longitude.udeg);
|
|
|
|
} else {
|
|
|
|
ui.coordinates->clear();
|
|
|
|
}
|
2013-11-11 23:21:45 +00:00
|
|
|
}
|