summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--device.c28
-rw-r--r--device.h2
-rw-r--r--divelist.c9
-rw-r--r--parse-xml.c1
-rw-r--r--qt-ui/divelistview.cpp60
-rw-r--r--qt-ui/divelistview.h4
-rw-r--r--qt-ui/downloadfromdivecomputer.cpp1
-rw-r--r--qt-ui/downloadfromdivecomputer.ui2
-rw-r--r--qt-ui/globe.cpp7
-rw-r--r--qt-ui/maintab.cpp243
-rw-r--r--qt-ui/maintab.h5
-rw-r--r--qt-ui/maintab.ui67
-rw-r--r--qt-ui/mainwindow.cpp79
-rw-r--r--qt-ui/mainwindow.h6
-rw-r--r--qt-ui/mainwindow.ui39
-rw-r--r--qt-ui/modeldelegates.cpp62
-rw-r--r--qt-ui/modeldelegates.h17
-rw-r--r--qt-ui/models.cpp171
-rw-r--r--qt-ui/models.h7
-rw-r--r--qt-ui/profilegraphics.cpp268
-rw-r--r--qt-ui/profilegraphics.h40
-rw-r--r--qt-ui/subsurfacewebservices.cpp8
-rw-r--r--statistics.c6
-rw-r--r--xslt/uddf.xslt209
24 files changed, 959 insertions, 382 deletions
diff --git a/device.c b/device.c
index 52c49a5bd..2baa2e03a 100644
--- a/device.c
+++ b/device.c
@@ -114,3 +114,31 @@ struct device_info *remove_device_info(const char *model, uint32_t deviceid)
}
return entry;
}
+
+struct divecomputer* fake_dc(struct divecomputer* dc)
+{
+ static struct sample fake[4];
+ static struct divecomputer fakedc;
+ static bool initialized = 0;
+ if (!initialized){
+ fakedc = (*dc);
+ fakedc.sample = fake;
+ fakedc.samples = 4;
+
+ /* The dive has no samples, so create a few fake ones. This assumes an
+ ascent/descent rate of 9 m/min, which is just below the limit for FAST. */
+ int duration = dc->duration.seconds;
+ int maxdepth = dc->maxdepth.mm;
+ int asc_desc_time = dc->maxdepth.mm*60/9000;
+ if (asc_desc_time * 2 >= duration)
+ asc_desc_time = duration / 2;
+ fake[1].time.seconds = asc_desc_time;
+ fake[1].depth.mm = maxdepth;
+ fake[2].time.seconds = duration - asc_desc_time;
+ fake[2].depth.mm = maxdepth;
+ fake[3].time.seconds = duration * 1.00;
+ fakedc.events = dc->events;
+ }
+ return &fakedc;
+}
+
diff --git a/device.h b/device.h
index 3efa42900..59969473a 100644
--- a/device.h
+++ b/device.h
@@ -2,6 +2,7 @@
#define DEVICE_INFO_H
#ifdef __cplusplus
+#include "dive.h"
extern "C" {
#endif
@@ -20,6 +21,7 @@ extern struct device_info *get_different_device_info(const char *model, uint32_t
extern struct device_info *create_device_info(const char *model, uint32_t deviceid);
extern struct device_info *remove_device_info(const char *model, uint32_t deviceid);
extern struct device_info *head_of_device_info_list(void);
+extern struct divecomputer *fake_dc(struct divecomputer* dc);
extern void remove_dive_computer(const char *model, uint32_t deviceid);
#ifdef __cplusplus
diff --git a/divelist.c b/divelist.c
index 7abad667b..606c30e01 100644
--- a/divelist.c
+++ b/divelist.c
@@ -607,12 +607,11 @@ char *get_trip_date_string(timestamp_t when, int nr)
struct tm tm;
utc_mkdate(when, &tm);
snprintf(buffer, MAX_DATE_STRING,
- /*++GETTEXT 60 char buffer weekday, monthname, day of month, year, nr dives */
- ngettext("Trip %1$s, %2$s %3$d, %4$d (%5$d dive)",
- "Trip %1$s, %2$s %3$d, %4$d (%5$d dives)", nr),
- weekday(tm.tm_wday),
+ /*++GETTEXT 60 char buffer monthname, year, nr dives */
+ ngettext("%1$s %2$d (%3$d dive)",
+ "%1$s %2$d (%3$d dives)", nr),
monthname(tm.tm_mon),
- tm.tm_mday, tm.tm_year + 1900,
+ tm.tm_year + 1900,
nr);
}
return buffer;
diff --git a/parse-xml.c b/parse-xml.c
index 58a9019c9..ba952957f 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -1913,6 +1913,7 @@ static struct xslt_files {
{ "dives", "MacDive.xslt" },
{ "DIVELOGSDATA", "divelogs.xslt" },
{ "uddf", "uddf.xslt" },
+ { "UDDF", "uddf.xslt" },
{ "profile", "udcf.xslt" },
{ "Divinglog", "DivingLog.xslt" },
{ NULL, }
diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp
index cbd62408b..752e12242 100644
--- a/qt-ui/divelistview.cpp
+++ b/qt-ui/divelistview.cpp
@@ -28,6 +28,8 @@ DiveListView::DiveListView(QWidget *parent) : QTreeView(parent), mouseClickSelec
model->setSortRole(TreeItemDT::SORT_ROLE);
model->setFilterKeyColumn(-1); // filter all columns
setModel(model);
+ connect(model, SIGNAL(layoutChanged()), this, SLOT(fixMessyQtModelBehaviour()));
+
setSortingEnabled(false);
setContextMenuPolicy(Qt::DefaultContextMenu);
header()->setContextMenuPolicy(Qt::ActionsContextMenu);
@@ -40,6 +42,17 @@ DiveListView::DiveListView(QWidget *parent) : QTreeView(parent), mouseClickSelec
searchBox->hide();
connect(showSearchBox, SIGNAL(triggered(bool)), this, SLOT(showSearchEdit()));
connect(searchBox, SIGNAL(textChanged(QString)), model, SLOT(setFilterFixedString(QString)));
+ selectedTrips.clear();
+}
+
+void DiveListView::fixMessyQtModelBehaviour()
+{
+ QAbstractItemModel *m = model();
+ for(int i = 0; i < model()->rowCount(); i++){
+ if (m->rowCount( m->index(i, 0) ) != 0){
+ setFirstColumnSpanned(i, QModelIndex(), true);
+ }
+ }
}
void DiveListView::unselectDives()
@@ -47,16 +60,19 @@ void DiveListView::unselectDives()
selectionModel()->clearSelection();
}
-void DiveListView::selectDive(struct dive *dive, bool scrollto)
+void DiveListView::selectDive(struct dive *dive, bool scrollto, bool toggle)
{
QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel*>(model());
QModelIndexList match = m->match(m->index(0,0), TreeItemDT::NR, dive->number, 1, Qt::MatchRecursive);
+ QItemSelectionModel::SelectionFlags flags;
QModelIndex idx = match.first();
QModelIndex parent = idx.parent();
if (parent.isValid())
expand(parent);
- selectionModel()->select( idx, QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ flags = toggle ? QItemSelectionModel::Toggle : QItemSelectionModel::Select;
+ flags |= QItemSelectionModel::Rows;
+ selectionModel()->select( idx, flags);
if (scrollto)
scrollTo(idx, PositionAtCenter);
}
@@ -183,6 +199,12 @@ void DiveListView::reloadHeaderActions()
setColumnHidden(i, !shown);
}
s.endGroup();
+ } else {
+ // Skip first QAction item ( static text Visible )
+ for(int i = 0; i < model()->columnCount(); i++) {
+ QString title = QString("%1").arg(model()->headerData(i, Qt::Horizontal).toString());
+ header()->actions()[i+1]->setText( title );
+ }
}
}
@@ -224,48 +246,51 @@ void DiveListView::selectionChanged(const QItemSelection& selected, const QItemS
disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
disconnect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(currentChanged(QModelIndex,QModelIndex)));
- Q_FOREACH(const QModelIndex& index, newSelected.indexes()) {
+ Q_FOREACH(const QModelIndex& index, newDeselected.indexes()) {
if (index.column() != 0)
continue;
-
const QAbstractItemModel *model = index.model();
struct dive *dive = (struct dive*) model->data(index, TreeItemDT::DIVE_ROLE).value<void*>();
if (!dive) { // it's a trip!
if (model->rowCount(index)) {
- QItemSelection selection;
struct dive *child = (struct dive*) model->data(index.child(0,0), TreeItemDT::DIVE_ROLE).value<void*>();
+ if (child && child->divetrip)
+ selectedTrips.remove(child->divetrip);
while (child) {
- select_dive(get_index_for_dive(child));
+ deselect_dive(get_index_for_dive(child));
child = child->next;
}
- selection.select(index.child(0,0), index.child(model->rowCount(index) -1 , 0));
- selectionModel()->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows);
- selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select | QItemSelectionModel::NoUpdate);
- if (!isExpanded(index))
- expand(index);
}
} else {
- select_dive(get_index_for_dive(dive));
+ deselect_dive(get_index_for_dive(dive));
}
}
- Q_FOREACH(const QModelIndex& index, newDeselected.indexes()) {
+ Q_FOREACH(const QModelIndex& index, newSelected.indexes()) {
if (index.column() != 0)
continue;
+
const QAbstractItemModel *model = index.model();
struct dive *dive = (struct dive*) model->data(index, TreeItemDT::DIVE_ROLE).value<void*>();
if (!dive) { // it's a trip!
if (model->rowCount(index)) {
+ QItemSelection selection;
struct dive *child = (struct dive*) model->data(index.child(0,0), TreeItemDT::DIVE_ROLE).value<void*>();
+ if (child && child->divetrip)
+ selectedTrips.insert(child->divetrip);
while (child) {
- deselect_dive(get_index_for_dive(child));
+ select_dive(get_index_for_dive(child));
child = child->next;
}
+ selection.select(index.child(0,0), index.child(model->rowCount(index) -1 , 0));
+ selectionModel()->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows);
+ selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select | QItemSelectionModel::NoUpdate);
+ if (!isExpanded(index))
+ expand(index);
}
} else {
- deselect_dive(get_index_for_dive(dive));
+ select_dive(get_index_for_dive(dive));
}
}
-
QTreeView::selectionChanged(selectionModel()->selection(), newDeselected);
connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged(QItemSelection,QItemSelection)));
connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(currentChanged(QModelIndex,QModelIndex)));
@@ -320,7 +345,8 @@ void DiveListView::contextMenuEvent(QContextMenuEvent *event)
popup.addAction(tr("remove dive from trip"), this, SLOT(removeFromTrip()));
}
}
- popup.addAction(tr("delete dive"), this, SLOT(deleteDive()));
+ if (d)
+ popup.addAction(tr("delete dive"), this, SLOT(deleteDive()));
// "collapse all" really closes all trips,
// "collapse" keeps the trip with the selected dive open
QAction * actionTaken = popup.exec(event->globalPos());
diff --git a/qt-ui/divelistview.h b/qt-ui/divelistview.h
index a9b986f97..88f52ba7d 100644
--- a/qt-ui/divelistview.h
+++ b/qt-ui/divelistview.h
@@ -27,8 +27,9 @@ public:
void reload(DiveTripModel::Layout layout, bool forceSort = true);
bool eventFilter(QObject* , QEvent* );
void unselectDives();
- void selectDive(struct dive *, bool scrollto = false);
+ void selectDive(struct dive *, bool scrollto = false, bool toggle = false);
void contextMenuEvent(QContextMenuEvent *event);
+ QSet<dive_trip_t *> selectedTrips;
public slots:
void toggleColumnVisibilityByIndex();
@@ -38,6 +39,7 @@ public slots:
void removeFromTrip();
void deleteDive();
void testSlot();
+ void fixMessyQtModelBehaviour();
Q_SIGNALS:
void currentDiveChanged(int divenr);
diff --git a/qt-ui/downloadfromdivecomputer.cpp b/qt-ui/downloadfromdivecomputer.cpp
index b0bdea739..37ca2775b 100644
--- a/qt-ui/downloadfromdivecomputer.cpp
+++ b/qt-ui/downloadfromdivecomputer.cpp
@@ -157,6 +157,7 @@ void DownloadFromDCWidget::on_ok_clicked()
data.product = strdup(ui->product->currentText().toUtf8().data());
data.descriptor = descriptorLookup[ui->vendor->currentText() + ui->product->currentText()];
data.force_download = ui->forceDownload->isChecked();
+ data.deviceid = data.diveid = 0;
set_default_dive_computer(data.vendor, data.product);
set_default_dive_computer_device(data.devname);
diff --git a/qt-ui/downloadfromdivecomputer.ui b/qt-ui/downloadfromdivecomputer.ui
index 4b46a6e43..41f9a4751 100644
--- a/qt-ui/downloadfromdivecomputer.ui
+++ b/qt-ui/downloadfromdivecomputer.ui
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
- <string>Form</string>
+ <string>Download From Dive Computer</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
diff --git a/qt-ui/globe.cpp b/qt-ui/globe.cpp
index 78283e49e..24806d520 100644
--- a/qt-ui/globe.cpp
+++ b/qt-ui/globe.cpp
@@ -82,6 +82,7 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit)
int idx;
struct dive *dive;
bool clear = !(QApplication::keyboardModifiers() && Qt::ControlModifier);
+ bool toggle = !clear;
bool first = true;
for_each_dive(idx, dive) {
long lat_diff, lon_diff;
@@ -100,7 +101,7 @@ void GlobeGPS::mouseClicked(qreal lon, qreal lat, GeoDataCoordinates::Unit unit)
mainWindow()->dive_list()->unselectDives();
clear = false;
}
- mainWindow()->dive_list()->selectDive(dive, first);
+ mainWindow()->dive_list()->selectDive(dive, first, toggle);
first = false;
}
}
@@ -129,10 +130,10 @@ void GlobeGPS::reload()
place->setCoordinate(dive->longitude.udeg / 1000000.0,dive->latitude.udeg / 1000000.0 , 0, GeoDataCoordinates::Degree);
// don't add dive locations twice, unless they are at least 50m apart
if (locationMap[QString(dive->location)]) {
- GeoDataPoint existingLocation = locationMap[QString(dive->location)]->coordinate();
+ GeoDataCoordinates existingLocation = locationMap[QString(dive->location)]->coordinate();
GeoDataLineString segment = GeoDataLineString();
segment.append(existingLocation);
- GeoDataPoint newLocation = place->coordinate();
+ GeoDataCoordinates newLocation = place->coordinate();
segment.append(newLocation);
double dist = segment.length(6371);
// the dist is scaled to the radius given - so with 6371km as radius
diff --git a/qt-ui/maintab.cpp b/qt-ui/maintab.cpp
index b9b5d0ab7..c6b49da39 100644
--- a/qt-ui/maintab.cpp
+++ b/qt-ui/maintab.cpp
@@ -15,19 +15,26 @@
#include <QLabel>
#include <QDebug>
+#include <QSet>
+#include <QSettings>
MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
ui(new Ui::MainTab()),
weightModel(new WeightModel()),
cylindersModel(new CylindersModel()),
- currentDive(0)
+ currentDive(0),
+ editMode(NONE)
{
ui->setupUi(this);
ui->cylinders->setModel(cylindersModel);
ui->weights->setModel(weightModel);
ui->diveNotesMessage->hide();
ui->diveNotesMessage->setCloseButtonVisible(false);
-
+#ifdef __APPLE__
+ setDocumentMode(false);
+#else
+ setDocumentMode(true);
+#endif
// we start out with the fields read-only; once things are
// filled from a dive, they are made writeable
ui->location->setReadOnly(true);
@@ -73,13 +80,17 @@ MainTab::MainTab(QWidget *parent) : QTabWidget(parent),
connect(ui->cylinders, SIGNAL(clicked(QModelIndex)), ui->cylinders->model(), SLOT(remove(QModelIndex)));
connect(ui->weights, SIGNAL(clicked(QModelIndex)), ui->weights->model(), SLOT(remove(QModelIndex)));
- ui->cylinders->setColumnWidth(CylindersModel::REMOVE, 24);
- ui->cylinders->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
+ QFontMetrics metrics(defaultModelFont());
+ QFontMetrics metrics2(font());
+
ui->cylinders->horizontalHeader()->setResizeMode(CylindersModel::REMOVE, QHeaderView::Fixed);
+ ui->cylinders->verticalHeader()->setDefaultSectionSize( metrics.height() +8 );
ui->cylinders->setItemDelegateForColumn(CylindersModel::TYPE, new TankInfoDelegate());
- ui->weights->setColumnWidth(WeightModel::REMOVE, 24);
+
ui->weights->horizontalHeader()->setResizeMode (WeightModel::REMOVE , QHeaderView::Fixed);
+ ui->weights->verticalHeader()->setDefaultSectionSize( metrics.height() +8 );
ui->weights->setItemDelegateForColumn(WeightModel::TYPE, new WSInfoDelegate());
+ initialUiSetup();
}
// We need to manually position the 'plus' on cylinder and weight.
@@ -155,15 +166,11 @@ void MainTab::clearStats()
void MainTab::updateDiveInfo(int dive)
{
- // So, this is what happens now:
- // Every tab should be populated from this method,
- // it will be called whenever a new dive is selected
- // I'm already populating the 'notes' box
- // to show how it can be done.
- // If you are unsure about the name of something,
- // open the file maintab.ui on the designer
- // click on the item and check its objectName,
- // the access is ui->objectName from here on.
+ // 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
volume_t sacVal;
temperature_t temp;
struct dive *prevd;
@@ -177,18 +184,48 @@ void MainTab::updateDiveInfo(int dive)
UPDATE_TEXT(d, suit);
UPDATE_TEXT(d, divemaster);
UPDATE_TEXT(d, buddy);
- /* infoTab */
if (d) {
- /* make the fields writeable */
- ui->location->setReadOnly(false);
- ui->divemaster->setReadOnly(false);
- ui->buddy->setReadOnly(false);
- ui->suit->setReadOnly(false);
- ui->notes->setReadOnly(false);
- ui->rating->setReadOnly(false);
- ui->visibility->setReadOnly(false);
- /* and fill them from the dive */
- ui->rating->setCurrentStars(d->rating);
+ if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
+ // only use trip relevant fields
+ 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);
+ // rename the remaining fields and fill data from selected trip
+ dive_trip_t *currentTrip = *mainWindow()->dive_list()->selectedTrips.begin();
+ ui->location->setReadOnly(false);
+ ui->LocationLabel->setText(tr("Trip Location"));
+ ui->location->setText(currentTrip->location);
+ ui->notes->setReadOnly(false);
+ ui->NotesLabel->setText(tr("Trip Notes"));
+ ui->notes->setText(currentTrip->notes);
+ } else {
+ // make all the fields visible writeable
+ ui->divemaster->setVisible(true);
+ ui->buddy->setVisible(true);
+ ui->suit->setVisible(true);
+ ui->rating->setVisible(true);
+ ui->visibility->setVisible(true);
+ ui->divemaster->setReadOnly(false);
+ ui->buddy->setReadOnly(false);
+ ui->suit->setReadOnly(false);
+ ui->rating->setReadOnly(false);
+ ui->visibility->setReadOnly(false);
+ /* and fill them from the dive */
+ ui->rating->setCurrentStars(d->rating);
+ ui->visibility->setCurrentStars(d->visibility);
+ // reset labels in case we last displayed trip notes
+ ui->location->setReadOnly(false);
+ ui->LocationLabel->setText(tr("Location"));
+ ui->notes->setReadOnly(false);
+ ui->NotesLabel->setText(tr("Notes"));
+ }
ui->maximumDepthText->setText(get_depth_string(d->maxdepth, TRUE));
ui->averageDepthText->setText(get_depth_string(d->meandepth, TRUE));
ui->otuText->setText(QString("%1").arg(d->otu));
@@ -209,7 +246,6 @@ void MainTab::updateDiveInfo(int dive)
ui->airPressureText->setText(QString("%1mbar").arg(d->surface_pressure.mbar));
else
ui->airPressureText->clear();
- ui->visibility->setCurrentStars(d->visibility);
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));
@@ -272,13 +308,6 @@ void MainTab::updateDiveInfo(int dive)
ui->totalTimeAllText->clear();
ui->timeLimits->clear();
}
- /* statisticsTab*/
- /* we can access the stats_selection struct, but how do we ensure the relevant dives are selected
- * if we don't use the gtk widget to drive this?
- * Maybe call process_selected_dives? Or re-write to query our Qt list view.
- */
-// qDebug("max temp %u",stats_selection.max_temp);
-// qDebug("min temp %u",stats_selection.min_temp);
}
void MainTab::addCylinder_clicked()
@@ -308,30 +337,47 @@ void MainTab::on_editAccept_clicked(bool edit)
mainWindow()->dive_list()->setEnabled(!edit);
if (edit) {
- ui->diveNotesMessage->setText(tr("This dive is being edited. Select Save or Undo when ready."));
- ui->diveNotesMessage->animatedShow();
- notesBackup.buddy = ui->buddy->text();
- notesBackup.suit = ui->suit->text();
- notesBackup.notes = ui->notes->toPlainText();
- notesBackup.divemaster = ui->divemaster->text();
- notesBackup.location = ui->location->text();
- notesBackup.rating = ui->rating->currentStars();
- notesBackup.visibility = ui->visibility->currentStars();
+ if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
+ // we are editing trip location and notes
+ ui->diveNotesMessage->setText(tr("This trip is being edited. Select Save or Undo when ready."));
+ ui->diveNotesMessage->animatedShow();
+ notesBackup.notes = ui->notes->toPlainText();
+ notesBackup.location = ui->location->text();
+ editMode = TRIP;
+ } else {
+ ui->diveNotesMessage->setText(tr("This dive is being edited. Select Save or Undo when ready."));
+ ui->diveNotesMessage->animatedShow();
+ notesBackup.buddy = ui->buddy->text();
+ notesBackup.suit = ui->suit->text();
+ notesBackup.notes = ui->notes->toPlainText();
+ notesBackup.divemaster = ui->divemaster->text();
+ notesBackup.location = ui->location->text();
+ notesBackup.rating = ui->rating->currentStars();
+ notesBackup.visibility = ui->visibility->currentStars();
+ editMode = DIVE;
+ }
} else {
ui->diveNotesMessage->animatedHide();
ui->editAccept->hide();
ui->editReset->hide();
/* now figure out if things have changed */
- if (notesBackup.buddy != ui->buddy->text() ||
- notesBackup.suit != ui->suit->text() ||
- notesBackup.notes != ui->notes->toPlainText() ||
- notesBackup.divemaster != ui->divemaster->text() ||
- notesBackup.location != ui->location->text() ||
- notesBackup.visibility != ui->visibility->currentStars() ||
- notesBackup.rating != ui->rating->currentStars())
- mark_divelist_changed(TRUE);
- if (notesBackup.location != ui->location->text())
- mainWindow()->globe()->reload();
+ if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
+ if (notesBackup.notes != ui->notes->toPlainText() ||
+ notesBackup.location != ui->location->text())
+ mark_divelist_changed(TRUE);
+ } else {
+ if (notesBackup.buddy != ui->buddy->text() ||
+ notesBackup.suit != ui->suit->text() ||
+ notesBackup.notes != ui->notes->toPlainText() ||
+ notesBackup.divemaster != ui->divemaster->text() ||
+ notesBackup.location != ui->location->text() ||
+ notesBackup.visibility != ui->visibility->currentStars() ||
+ notesBackup.rating != ui->rating->currentStars())
+ mark_divelist_changed(TRUE);
+ if (notesBackup.location != ui->location->text())
+ mainWindow()->globe()->reload();
+ }
+ editMode = NONE;
}
}
@@ -340,13 +386,15 @@ void MainTab::on_editReset_clicked()
if (!ui->editAccept->isChecked())
return;
- ui->buddy->setText(notesBackup.buddy);
- ui->suit->setText(notesBackup.suit);
ui->notes->setText(notesBackup.notes);
- ui->divemaster->setText(notesBackup.divemaster);
ui->location->setText(notesBackup.location);
- ui->rating->setCurrentStars(notesBackup.rating);
- ui->visibility->setCurrentStars(notesBackup.visibility);
+ if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() != 1) {
+ ui->buddy->setText(notesBackup.buddy);
+ ui->suit->setText(notesBackup.suit);
+ ui->divemaster->setText(notesBackup.divemaster);
+ ui->rating->setCurrentStars(notesBackup.rating);
+ ui->visibility->setCurrentStars(notesBackup.visibility);
+ }
ui->editAccept->setChecked(false);
ui->diveNotesMessage->animatedHide();
@@ -361,49 +409,62 @@ void MainTab::on_editReset_clicked()
ui->editAccept->hide();
ui->editReset->hide();
+ editMode = NONE;
}
-#define EDIT_NOTES(what, text) \
+#define EDIT_TEXT(what, text) \
QByteArray textByteArray = text.toLocal8Bit(); \
- free(currentDive->what);\
- currentDive->what = strdup(textByteArray.data());
+ free(what);\
+ what = strdup(textByteArray.data());
void MainTab::on_buddy_textChanged(const QString& text)
{
if (!currentDive)
return;
- EDIT_NOTES(buddy, text);
+ EDIT_TEXT(currentDive->buddy, text);
}
void MainTab::on_divemaster_textChanged(const QString& text)
{
if (!currentDive)
return;
- EDIT_NOTES(divemaster, text);
+ EDIT_TEXT(currentDive->divemaster, text);
}
void MainTab::on_location_textChanged(const QString& text)
{
- if (!currentDive)
- return;
- EDIT_NOTES(location, text);
+ if (editMode == TRIP && mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
+ // we are editing a trip
+ dive_trip_t *currentTrip = *mainWindow()->dive_list()->selectedTrips.begin();
+ EDIT_TEXT(currentTrip->location, text);
+ } else if (editMode == DIVE){
+ if (!currentDive)
+ return;
+ EDIT_TEXT(currentDive->location, text);
+ }
}
void MainTab::on_suit_textChanged(const QString& text)
{
if (!currentDive)
return;
- EDIT_NOTES(suit, text);
+ EDIT_TEXT(currentDive->suit, text);
}
void MainTab::on_notes_textChanged()
{
- if (!currentDive)
- return;
- EDIT_NOTES(notes, ui->notes->toPlainText());
+ if (editMode == TRIP && mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1) {
+ // we are editing a trip
+ dive_trip_t *currentTrip = *mainWindow()->dive_list()->selectedTrips.begin();
+ EDIT_TEXT(currentTrip->notes, ui->notes->toPlainText());
+ } else if (editMode == DIVE) {
+ if (!currentDive)
+ return;
+ EDIT_TEXT(currentDive->notes, ui->notes->toPlainText());
+ }
}
-#undef EDIT_NOTES
+#undef EDIT_TEXT
void MainTab::on_rating_valueChanged(int value)
{
@@ -418,3 +479,45 @@ void MainTab::on_visibility_valueChanged(int value)
return;
currentDive->visibility = value;
}
+
+void MainTab::hideEvent(QHideEvent* event)
+{
+ QSettings s;
+ s.beginGroup("MainTab");
+ s.beginGroup("Cylinders");
+ for (int i = 0; i < CylindersModel::COLUMNS; i++) {
+ s.setValue(QString("colwidth%1").arg(i), ui->cylinders->columnWidth(i));
+ }
+ s.endGroup();
+ s.beginGroup("Weights");
+ for (int i = 0; i < WeightModel::COLUMNS; i++) {
+ s.setValue(QString("colwidth%1").arg(i), ui->weights->columnWidth(i));
+ }
+ s.endGroup();
+ s.sync();
+}
+
+void MainTab::initialUiSetup()
+{
+ QSettings s;
+ s.beginGroup("MainTab");
+ s.beginGroup("Cylinders");
+ for (int i = 0; i < CylindersModel::COLUMNS; i++) {
+ QVariant width = s.value(QString("colwidth%1").arg(i));
+ if (width.isValid())
+ ui->cylinders->setColumnWidth(i, width.toInt());
+ else
+ ui->cylinders->resizeColumnToContents(i);
+ }
+ s.endGroup();
+ s.beginGroup("Weights");
+ for (int i = 0; i < WeightModel::COLUMNS; i++) {
+ QVariant width = s.value(QString("colwidth%1").arg(i));
+ if (width.isValid())
+ ui->weights->setColumnWidth(i, width.toInt());
+ else
+ ui->weights->resizeColumnToContents(i);
+ }
+ s.endGroup();
+
+}
diff --git a/qt-ui/maintab.h b/qt-ui/maintab.h
index 38d01e806..124bcff7e 100644
--- a/qt-ui/maintab.h
+++ b/qt-ui/maintab.h
@@ -40,6 +40,10 @@ public:
bool eventFilter(QObject* , QEvent*);
virtual void resizeEvent(QResizeEvent*);
virtual void showEvent(QShowEvent*);
+ virtual void hideEvent(QHideEvent* );
+
+ void initialUiSetup();
+
public Q_SLOTS:
void addCylinder_clicked();
@@ -63,6 +67,7 @@ private:
struct dive* currentDive;
QPushButton *addCylinder;
QPushButton *addWeight;
+ enum { NONE, DIVE, TRIP } editMode;
};
#endif
diff --git a/qt-ui/maintab.ui b/qt-ui/maintab.ui
index 55d4f3a54..c42dc4638 100644
--- a/qt-ui/maintab.ui
+++ b/qt-ui/maintab.ui
@@ -6,18 +6,15 @@
<rect>
<x>0</x>
<y>0</y>
- <width>409</width>
- <height>368</height>
+ <width>505</width>
+ <height>459</height>
</rect>
</property>
<property name="windowTitle">
<string>TabWidget</string>
</property>
<property name="currentIndex">
- <number>3</number>
- </property>
- <property name="documentMode">
- <bool>true</bool>
+ <number>1</number>
</property>
<widget class="QWidget" name="notesTab">
<attribute name="title">
@@ -25,7 +22,7 @@
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="LocationLabel">
<property name="text">
<string>Location</string>
</property>
@@ -39,14 +36,14 @@
</widget>
</item>
<item row="3" column="0">
- <widget class="QLabel" name="label_15">
+ <widget class="QLabel" name="DivemasterLabel">
<property name="text">
<string>Divemaster</string>
</property>
</widget>
</item>
<item row="3" column="1">
- <widget class="QLabel" name="label_3">
+ <widget class="QLabel" name="BuddyLabel">
<property name="text">
<string>Buddy</string>
</property>
@@ -83,7 +80,7 @@
<item row="5" column="0">
<layout class="QHBoxLayout" name="ratingVisibilityLabels">
<item>
- <widget class="QLabel" name="label_14">
+ <widget class="QLabel" name="RatingLabel">
<property name="text">
<string>Rating</string>
</property>
@@ -99,14 +96,14 @@
</layout>
</item>
<item row="5" column="1">
- <widget class="QLabel" name="label_19">
+ <widget class="QLabel" name="SuitLabel">
<property name="text">
<string>Suit</string>
</property>
</widget>
</item>
<item row="7" column="0">
- <widget class="QLabel" name="label_16">
+ <widget class="QLabel" name="NotesLabel">
<property name="text">
<string>Notes</string>
</property>
@@ -195,6 +192,12 @@
<property name="alternatingRowColors">
<bool>true</bool>
</property>
+ <property name="showGrid">
+ <bool>false</bool>
+ </property>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
</widget>
</item>
</layout>
@@ -205,7 +208,45 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
- <widget class="QTableView" name="weights"/>
+ <widget class="QTableView" name="weights">
+ <property name="styleSheet">
+ <string notr="true"> QTableView {
+ show-decoration-selected: 1;
+ }
+
+ QTableView::item {
+ border: 1px solid #d9d9d9;
+ border-top-color: transparent;
+ border-bottom-color: transparent;
+ padding: 2px;
+ }
+
+ QTableView::item:hover {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e7effd, stop: 1 #cbdaf1);
+ border: 1px solid #bfcde4;
+ }
+
+ QTableView::item:selected {
+ border: 1px solid #567dbc;
+ }
+
+ QTableView::item:selected:active{
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6ea1f1, stop: 1 #567dbc);
+ }
+
+ QTableView::item:selected:!active {
+ background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #6b9be8, stop: 1 #577fbf);
+ }
+
+</string>
+ </property>
+ <property name="showGrid">
+ <bool>false</bool>
+ </property>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
</item>
</layout>
</widget>
diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp
index a927c0231..53546fa67 100644
--- a/qt-ui/mainwindow.cpp
+++ b/qt-ui/mainwindow.cpp
@@ -45,9 +45,9 @@ MainWindow::MainWindow() : ui(new Ui::MainWindow()), helpView(0)
connect(ui->ListWidget, SIGNAL(currentDiveChanged(int)), this, SLOT(current_dive_changed(int)));
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), this, SLOT(readSettings()));
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui->ListWidget, SLOT(update()));
+ connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui->ListWidget, SLOT(reloadHeaderActions()));
connect(PreferencesDialog::instance(), SIGNAL(settingsChanged()), ui->ProfileWidget, SLOT(refresh()));
ui->mainErrorMessage->hide();
- ui->ProfileWidget->setFocusProxy(ui->ListWidget);
ui->ListWidget->reload(DiveTripModel::TREE);
initialUiSetup();
readSettings();
@@ -87,10 +87,27 @@ void MainWindow::on_actionNew_triggered()
void MainWindow::on_actionOpen_triggered()
{
- QString filename = QFileDialog::getOpenFileName(this, tr("Open File"), QDir::homePath(), filter());
+ QSettings settings;
+ QString lastDir = QDir::homePath();
+
+ settings.beginGroup("FileDialog");
+ if (settings.contains("LastDir")) {
+ if(QDir::setCurrent(settings.value("LastDir").toString())) {
+ lastDir = settings.value("LastDir").toString();
+ }
+ }
+ settings.endGroup();
+
+ QString filename = QFileDialog::getOpenFileName(this, tr("Open File"), lastDir, filter());
if (filename.isEmpty())
return;
+ // Keep last open dir
+ QFileInfo fileInfo(filename);
+ settings.beginGroup("FileDialog");
+ settings.setValue("LastDir",fileInfo.dir().path());
+ settings.endGroup();
+
// Needed to convert to char*
QByteArray fileNamePtr = filename.toLocal8Bit();
@@ -194,7 +211,15 @@ void MainWindow::on_actionEditDeviceNames_triggered()
void MainWindow::on_actionAddDive_triggered()
{
- qDebug("actionAddDive");
+ struct dive *dive;
+ dive = alloc_dive();
+ record_dive(dive);
+ process_dives(FALSE, FALSE);
+
+ ui->InfoWidget->reload();
+ ui->globe->reload();
+ ui->ListWidget->reload(DiveTripModel::TREE);
+ ui->ListWidget->setFocus();
}
void MainWindow::on_actionRenumber_triggered()
@@ -217,32 +242,54 @@ void MainWindow::on_actionYearlyStatistics_triggered()
qDebug("actionYearlyStatistics");
}
+/**
+ * So, here's the deal.
+ * We have a few QSplitters that takes care of helping us with the
+ * size of a few widgets, they are ok, and we should continue using them
+ * to manage the visibility of them too. But the way that we did before was to
+ * widget->hide(); something, and if you hided something using the splitter,
+ * by holding it's handle and collapsing the widget, then you used the 'ctrl+number'
+ * shortcut to show it, it whould only show a gray panel.
+ *
+ * This patch makes everything behave using the splitters.
+ */
+
+#define BEHAVIOR QList<int>()
void MainWindow::on_actionViewList_triggered()
{
- ui->InfoWidget->setVisible(false);
- ui->ListWidget->setVisible(true);
- ui->ProfileWidget->setVisible(false);
+ ui->listGlobeSplitter->setSizes( BEHAVIOR << EXPANDED << COLLAPSED);
+ ui->mainSplitter->setSizes( BEHAVIOR << COLLAPSED << EXPANDED);
}
void MainWindow::on_actionViewProfile_triggered()
{
- ui->InfoWidget->setVisible(false);
- ui->ListWidget->setVisible(false);
- ui->ProfileWidget->setVisible(true);
+ ui->infoProfileSplitter->setSizes(BEHAVIOR << COLLAPSED << EXPANDED);
+ ui->mainSplitter->setSizes( BEHAVIOR << EXPANDED << COLLAPSED);
}
void MainWindow::on_actionViewInfo_triggered()
{
- ui->InfoWidget->setVisible(true);
- ui->ListWidget->setVisible(false);
- ui->ProfileWidget->setVisible(false);
+ ui->infoProfileSplitter->setSizes(BEHAVIOR << EXPANDED << COLLAPSED);
+ ui->mainSplitter->setSizes( BEHAVIOR << EXPANDED << COLLAPSED);
}
+void MainWindow::on_actionViewGlobe_triggered()
+{
+ ui->infoProfileSplitter->setSizes(BEHAVIOR << COLLAPSED << EXPANDED);
+ ui->mainSplitter->setSizes( BEHAVIOR << COLLAPSED << EXPANDED);
+}
+#undef BEHAVIOR
+
void MainWindow::on_actionViewAll_triggered()
{
- ui->InfoWidget->setVisible(true);
- ui->ListWidget->setVisible(true);
- ui->ProfileWidget->setVisible(true);
+ // big number squash the info profile to it's minimum.
+ ui->infoProfileSplitter->setSizes(QList<int>() << 1 << 20000);
+
+ // big number squash the globe view.
+ ui->listGlobeSplitter->setSizes(QList<int>() << 2000 << 1 );
+
+ // half and half?
+ ui->mainSplitter->setSizes( QList<int>() << 1 << 1);
}
void MainWindow::on_actionPreviousDC_triggered()
@@ -382,6 +429,7 @@ void MainWindow::initialUiSetup()
resize(sz);
ui->mainSplitter->restoreState(settings.value("mainSplitter").toByteArray());
ui->infoProfileSplitter->restoreState(settings.value("infoProfileSplitter").toByteArray());
+ ui->listGlobeSplitter->restoreState(settings.value("listGlobeSplitter").toByteArray());
settings.endGroup();
settings.beginGroup("ListWidget");
@@ -473,6 +521,7 @@ void MainWindow::writeSettings()
settings.setValue("size",size());
settings.setValue("mainSplitter", ui->mainSplitter->saveState());
settings.setValue("infoProfileSplitter", ui->infoProfileSplitter->saveState());
+ settings.setValue("listGlobeSplitter", ui->listGlobeSplitter->saveState());
settings.endGroup();
settings.beginGroup("ListWidget");
diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h
index f3024ef8d..0b3812469 100644
--- a/qt-ui/mainwindow.h
+++ b/qt-ui/mainwindow.h
@@ -8,13 +8,13 @@
#define MAINWINDOW_H
#include <QMainWindow>
-#include <QModelIndex>
#include <QAction>
struct DiveList;
class QSortFilterProxyModel;
class DiveTripModel;
+
namespace Ui
{
class MainWindow;
@@ -35,6 +35,8 @@ class MainWindow : public QMainWindow
{
Q_OBJECT
public:
+ enum {COLLAPSED, EXPANDED};
+
MainWindow();
ProfileGraphicsView *graphics();
MainTab *information();
@@ -71,6 +73,7 @@ private Q_SLOTS:
void on_actionViewList_triggered();
void on_actionViewProfile_triggered();
void on_actionViewInfo_triggered();
+ void on_actionViewGlobe_triggered();
void on_actionViewAll_triggered();
void on_actionPreviousDC_triggered();
void on_actionNextDC_triggered();
@@ -102,6 +105,7 @@ private:
void redrawProfile();
void file_save();
void file_save_as();
+ void setupSplitters();
};
MainWindow *mainWindow();
diff --git a/qt-ui/mainwindow.ui b/qt-ui/mainwindow.ui
index fbf10cdf8..1a985f812 100644
--- a/qt-ui/mainwindow.ui
+++ b/qt-ui/mainwindow.ui
@@ -14,8 +14,8 @@
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
<widget class="QSplitter" name="mainSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -92,7 +92,7 @@
</widget>
</widget>
</item>
- <item>
+ <item row="1" column="0">
<widget class="KMessageWidget" name="mainErrorMessage" native="true"/>
</item>
</layout>
@@ -103,7 +103,7 @@
<x>0</x>
<y>0</y>
<width>763</width>
- <height>20</height>
+ <height>34</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@@ -147,7 +147,9 @@
<addaction name="actionViewList"/>
<addaction name="actionViewProfile"/>
<addaction name="actionViewInfo"/>
+ <addaction name="actionViewGlobe"/>
<addaction name="actionViewAll"/>
+ <addaction name="separator"/>
<addaction name="actionPreviousDC"/>
<addaction name="actionNextDC"/>
</widget>
@@ -157,12 +159,6 @@
</property>
<addaction name="actionSelectEvents"/>
</widget>
- <widget class="QMenu" name="menuPlanner">
- <property name="title">
- <string>Planner</string>
- </property>
- <addaction name="actionInputPlan"/>
- </widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
@@ -174,7 +170,6 @@
<addaction name="menuLog"/>
<addaction name="menuView"/>
<addaction name="menuFilter"/>
- <addaction name="menuPlanner"/>
<addaction name="menuHelp"/>
</widget>
<action name="actionNew">
@@ -323,7 +318,7 @@
<string>View All</string>
</property>
<property name="shortcut">
- <string>Ctrl+4</string>
+ <string>Ctrl+5</string>
</property>
</action>
<action name="actionPreviousDC">
@@ -365,9 +360,23 @@
<string>F1</string>
</property>
</action>
+ <action name="actionViewGlobe">
+ <property name="text">
+ <string>View Globe</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+4</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>
+ <class>KMessageWidget</class>
+ <extends>QWidget</extends>
+ <header>kmessagewidget.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
<class>MainTab</class>
<extends>QWidget</extends>
<header>maintab.h</header>
@@ -389,12 +398,6 @@
<header>globe.h</header>
<container>1</container>
</customwidget>
- <customwidget>
- <class>KMessageWidget</class>
- <extends>QWidget</extends>
- <header>kmessagewidget.h</header>
- <container>1</container>
- </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/qt-ui/modeldelegates.cpp b/qt-ui/modeldelegates.cpp
index c90a1e8e1..01f5197ce 100644
--- a/qt-ui/modeldelegates.cpp
+++ b/qt-ui/modeldelegates.cpp
@@ -17,7 +17,6 @@ StarWidgetsDelegate::StarWidgetsDelegate(QWidget* parent):
QStyledItemDelegate(parent),
parentWidget(parent)
{
-
}
void StarWidgetsDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
@@ -51,19 +50,11 @@ QSize StarWidgetsDelegate::sizeHint(const QStyleOptionViewItem& option, const QM
return QSize(IMG_SIZE * TOTALSTARS + SPACING * (TOTALSTARS-1), IMG_SIZE);
}
-QWidget* TankInfoDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
+ComboBoxDelegate::ComboBoxDelegate(QAbstractItemModel *model, QObject* parent): QStyledItemDelegate(parent), model(model)
{
- QComboBox *comboDelegate = new QComboBox(parent);
- TankInfoModel *model = TankInfoModel::instance();
- comboDelegate->setModel(model);
- comboDelegate->setEditable(true);
- comboDelegate->setAutoCompletion(true);
- comboDelegate->setAutoCompletionCaseSensitivity(Qt::CaseInsensitive);
- comboDelegate->completer()->setCompletionMode(QCompleter::PopupCompletion);
- return comboDelegate;
}
-void TankInfoDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
+void ComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QComboBox *c = qobject_cast<QComboBox*>(editor);
QString data = index.model()->data(index, Qt::DisplayRole).toString();
@@ -74,6 +65,28 @@ void TankInfoDelegate::setEditorData(QWidget* editor, const QModelIndex& index)
c->setEditText(data);
}
+QWidget* ComboBoxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ QComboBox *comboDelegate = new QComboBox(parent);
+ comboDelegate->setModel(model);
+ comboDelegate->setEditable(true);
+ comboDelegate->setAutoCompletion(true);
+ comboDelegate->setAutoCompletionCaseSensitivity(Qt::CaseInsensitive);
+ comboDelegate->completer()->setCompletionMode(QCompleter::PopupCompletion);
+ return comboDelegate;
+}
+
+void ComboBoxDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ QRect defaultRect = option.rect;
+ defaultRect.setX( defaultRect.x() -1);
+ defaultRect.setY( defaultRect.y() -1);
+ defaultRect.setWidth( defaultRect.width() + 2);
+ defaultRect.setHeight( defaultRect.height() + 2);
+ editor->setGeometry(defaultRect);
+}
+
+
void TankInfoDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& thisindex) const
{
QComboBox *c = qobject_cast<QComboBox*>(editor);
@@ -97,31 +110,8 @@ void TankInfoDelegate::setModelData(QWidget* editor, QAbstractItemModel* model,
mymodel->passInData(model->index(thisindex.row(), CylindersModel::SIZE), tankSize);
}
-TankInfoDelegate::TankInfoDelegate(QObject* parent): QStyledItemDelegate(parent)
-{
-}
-
-QWidget* WSInfoDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
+TankInfoDelegate::TankInfoDelegate(QObject* parent): ComboBoxDelegate(TankInfoModel::instance(), parent)
{
- QComboBox *comboDelegate = new QComboBox(parent);
- WSInfoModel *model = WSInfoModel::instance();
- comboDelegate->setModel(model);
- comboDelegate->setEditable(true);
- comboDelegate->setAutoCompletion(true);
- comboDelegate->setAutoCompletionCaseSensitivity(Qt::CaseInsensitive);
- comboDelegate->completer()->setCompletionMode(QCompleter::PopupCompletion);
- return comboDelegate;
-}
-
-void WSInfoDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
-{
- QComboBox *c = qobject_cast<QComboBox*>(editor);
- QString data = index.model()->data(index, Qt::DisplayRole).toString();
- int i = c->findText(data);
- if (i != -1)
- c->setCurrentIndex(i);
- else
- c->setEditText(data);
}
void WSInfoDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& thisindex) const
@@ -145,6 +135,6 @@ void WSInfoDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, co
mymodel->passInData(model->index(thisindex.row(), WeightModel::WEIGHT), grams);
}
-WSInfoDelegate::WSInfoDelegate(QObject* parent): QStyledItemDelegate(parent)
+WSInfoDelegate::WSInfoDelegate(QObject* parent): ComboBoxDelegate(WSInfoModel::instance(), parent)
{
}
diff --git a/qt-ui/modeldelegates.h b/qt-ui/modeldelegates.h
index 79fbe297b..a33fc891b 100644
--- a/qt-ui/modeldelegates.h
+++ b/qt-ui/modeldelegates.h
@@ -13,21 +13,28 @@ private:
QWidget *parentWidget;
};
-class TankInfoDelegate : public QStyledItemDelegate{
+class ComboBoxDelegate : public QStyledItemDelegate{
Q_OBJECT
public:
- explicit TankInfoDelegate(QObject* parent = 0);
+ explicit ComboBoxDelegate(QAbstractItemModel *model, QObject* parent = 0);
virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
virtual void setEditorData(QWidget* editor, const QModelIndex& index) const;
+ virtual void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const;
+protected:
+ QAbstractItemModel *model;
+};
+
+class TankInfoDelegate : public ComboBoxDelegate{
+ Q_OBJECT
+public:
+ explicit TankInfoDelegate(QObject* parent = 0);
virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;
};
-class WSInfoDelegate : public QStyledItemDelegate{
+class WSInfoDelegate : public ComboBoxDelegate{
Q_OBJECT
public:
explicit WSInfoDelegate(QObject* parent = 0);
- virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
- virtual void setEditorData(QWidget* editor, const QModelIndex& index) const;
virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;
};
diff --git a/qt-ui/models.cpp b/qt-ui/models.cpp
index 868cba952..03300a8d6 100644
--- a/qt-ui/models.cpp
+++ b/qt-ui/models.cpp
@@ -16,6 +16,13 @@
#include <QFont>
#include <QIcon>
+QFont defaultModelFont()
+{
+ QFont font;
+ font.setPointSizeF( font.pointSizeF() * 0.8);
+ return font;
+}
+
CylindersModel::CylindersModel(QObject* parent): QAbstractTableModel(parent), current(0), rows(0)
{
}
@@ -23,15 +30,14 @@ CylindersModel::CylindersModel(QObject* parent): QAbstractTableModel(parent), cu
QVariant CylindersModel::headerData(int section, Qt::Orientation orientation, int role) const
{
QVariant ret;
- QFont font;
if (orientation == Qt::Vertical)
return ret;
switch (role) {
case Qt::FontRole:
- font.setPointSizeF(font.pointSizeF() * 0.8);
- return font;
+ ret = defaultModelFont();
+ break;
case Qt::DisplayRole:
switch(section) {
case TYPE: ret = tr("Type"); break;
@@ -54,7 +60,6 @@ int CylindersModel::columnCount(const QModelIndex& parent) const
QVariant CylindersModel::data(const QModelIndex& index, int role) const
{
QVariant ret;
- QFont font;
if (!index.isValid() || index.row() >= MAX_CYLINDERS)
return ret;
@@ -62,11 +67,10 @@ QVariant CylindersModel::data(const QModelIndex& index, int role) const
cylinder_t *cyl = &current->cylinder[index.row()];
switch (role) {
case Qt::FontRole:
- font.setPointSizeF(font.pointSizeF() * 0.80);
- ret = font;
+ ret = defaultModelFont();
break;
case Qt::TextAlignmentRole:
- ret = Qt::AlignRight;
+ ret = Qt::AlignHCenter;
break;
case Qt::DisplayRole:
case Qt::EditRole:
@@ -338,7 +342,6 @@ int WeightModel::columnCount(const QModelIndex& parent) const
QVariant WeightModel::data(const QModelIndex& index, int role) const
{
QVariant ret;
- QFont font;
if (!index.isValid() || index.row() >= MAX_WEIGHTSYSTEMS)
return ret;
@@ -346,8 +349,7 @@ QVariant WeightModel::data(const QModelIndex& index, int role) const
switch (role) {
case Qt::FontRole:
- font.setPointSizeF(font.pointSizeF() * 0.80);
- ret = font;
+ ret = defaultModelFont();
break;
case Qt::TextAlignmentRole:
ret = Qt::AlignRight;
@@ -431,14 +433,12 @@ int WeightModel::rowCount(const QModelIndex& parent) const
QVariant WeightModel::headerData(int section, Qt::Orientation orientation, int role) const
{
QVariant ret;
- QFont font;
if (orientation == Qt::Vertical)
return ret;
switch (role) {
case Qt::FontRole:
- font.setPointSizeF(font.pointSizeF() * 0.8);
- ret = font;
+ ret = defaultModelFont();
break;
case Qt::DisplayRole:
switch(section) {
@@ -536,16 +536,21 @@ QVariant WSInfoModel::data(const QModelIndex& index, int role) const
struct ws_info *info = &ws_info[index.row()];
int gr = info->grams;
-
- if (role == Qt::DisplayRole || role == Qt::EditRole) {
- switch(index.column()) {
- case GR:
- ret = gr;
- break;
- case DESCRIPTION:
- ret = QString(info->name);
- break;
- }
+ switch(role){
+ case Qt::FontRole :
+ ret = defaultModelFont();
+ break;
+ case Qt::DisplayRole :
+ case Qt::EditRole :
+ switch(index.column()) {
+ case GR:
+ ret = gr;
+ break;
+ case DESCRIPTION:
+ ret = QString(info->name);
+ break;
+ }
+ break;
}
return ret;
}
@@ -557,15 +562,20 @@ QVariant WSInfoModel::headerData(int section, Qt::Orientation orientation, int r
if (orientation != Qt::Horizontal)
return ret;
- if (role == Qt::DisplayRole) {
- switch(section) {
- case GR:
- ret = tr("kg");
- break;
- case DESCRIPTION:
- ret = tr("Description");
- break;
- }
+ switch(role){
+ case Qt::FontRole :
+ ret = defaultModelFont();
+ break;
+ case Qt::DisplayRole :
+ switch(section) {
+ case GR:
+ ret = tr("kg");
+ break;
+ case DESCRIPTION:
+ ret = tr("Description");
+ break;
+ }
+ break;
}
return ret;
}
@@ -575,10 +585,20 @@ int WSInfoModel::rowCount(const QModelIndex& parent) const
return rows+1;
}
+const QString& WSInfoModel::biggerString() const
+{
+ return biggerEntry;
+}
+
WSInfoModel::WSInfoModel() : QAbstractTableModel(), rows(-1)
{
struct ws_info *info = ws_info;
- for (info = ws_info; info->name; info++, rows++);
+ for (info = ws_info; info->name; info++, rows++){
+ QString wsInfoName(info->name);
+ if( wsInfoName.count() > biggerEntry.count()){
+ biggerEntry = wsInfoName;
+ }
+ }
if (rows > -1) {
beginInsertRows(QModelIndex(), 0, rows);
@@ -608,6 +628,11 @@ TankInfoModel* TankInfoModel::instance()
return self;
}
+const QString& TankInfoModel::biggerString() const
+{
+ return biggerEntry;
+}
+
bool TankInfoModel::insertRows(int row, int count, const QModelIndex& parent)
{
beginInsertRows(parent, rowCount(), rowCount());
@@ -648,6 +673,10 @@ QVariant TankInfoModel::data(const QModelIndex& index, int role) const
if (!index.isValid()) {
return ret;
}
+ if (role == Qt::FontRole){
+ return defaultModelFont();
+ }
+
struct tank_info *info = &tank_info[index.row()];
int ml = info->ml;
@@ -682,8 +711,12 @@ QVariant TankInfoModel::headerData(int section, Qt::Orientation orientation, int
if (orientation != Qt::Horizontal)
return ret;
- if (role == Qt::DisplayRole) {
- switch(section) {
+ switch(role){
+ case Qt::FontRole:
+ ret = defaultModelFont();
+ break;
+ case Qt::DisplayRole:
+ switch(section) {
case BAR:
ret = tr("Bar");
break;
@@ -693,7 +726,8 @@ QVariant TankInfoModel::headerData(int section, Qt::Orientation orientation, int
case DESCRIPTION:
ret = tr("Description");
break;
- }
+ }
+ break;
}
return ret;
}
@@ -706,7 +740,13 @@ int TankInfoModel::rowCount(const QModelIndex& parent) const
TankInfoModel::TankInfoModel() : QAbstractTableModel(), rows(-1)
{
struct tank_info *info = tank_info;
- for (info = tank_info; info->name; info++, rows++);
+ for (info = tank_info; info->name; info++, rows++){
+ QString infoName(info->name);
+ if (infoName.count() > biggerEntry.count()){
+ biggerEntry = infoName;
+ }
+ }
+
if (rows > -1) {
beginInsertRows(QModelIndex(), 0, rows);
endInsertRows();
@@ -754,21 +794,25 @@ int TreeItemDT::row() const
QVariant TreeItemDT::data(int column, int role) const
{
QVariant ret;
- switch (column) {
- case NR: ret = tr("#"); break;
- case DATE: ret = tr("Date"); break;
- case RATING: ret = UTF8_BLACKSTAR; break;
- case DEPTH: ret = (get_units()->length == units::METERS) ? tr("m") : tr("ft"); break;
- case DURATION: ret = tr("min"); break;
- case TEMPERATURE: ret = QString("%1%2").arg(UTF8_DEGREE).arg((get_units()->temperature == units::CELSIUS) ? "C" : "F"); break;
- case TOTALWEIGHT: ret = (get_units()->weight == units::KG) ? tr("kg") : tr("lbs"); break;
- case SUIT: ret = tr("Suit"); break;
- case CYLINDER: ret = tr("Cyl"); break;
- case NITROX: ret = QString("O%1%").arg(UTF8_SUBSCRIPT_2); break;
- case SAC: ret = tr("SAC"); break;
- case OTU: ret = tr("OTU"); break;
- case MAXCNS: ret = tr("maxCNS"); break;
- case LOCATION: ret = tr("Location"); break;
+ switch(role){
+ case Qt::DisplayRole :
+ switch (column) {
+ case NR: ret = tr("#"); break;
+ case DATE: ret = tr("Date"); break;
+ case RATING: ret = UTF8_BLACKSTAR; break;
+ case DEPTH: ret = (get_units()->length == units::METERS) ? tr("m") : tr("ft"); break;
+ case DURATION: ret = tr("min"); break;
+ case TEMPERATURE: ret = QString("%1%2").arg(UTF8_DEGREE).arg((get_units()->temperature == units::CELSIUS) ? "C" : "F"); break;
+ case TOTALWEIGHT: ret = (get_units()->weight == units::KG) ? tr("kg") : tr("lbs"); break;
+ case SUIT: ret = tr("Suit"); break;
+ case CYLINDER: ret = tr("Cyl"); break;
+ case NITROX: ret = QString("O%1%").arg(UTF8_SUBSCRIPT_2); break;
+ case SAC: ret = tr("SAC"); break;
+ case OTU: ret = tr("OTU"); break;
+ case MAXCNS: ret = tr("maxCNS"); break;
+ case LOCATION: ret = tr("Location"); break;
+ }
+ break;
}
return ret;
}
@@ -787,11 +831,8 @@ QVariant TripItem::data(int column, int role) const
if (role == Qt::DisplayRole) {
switch (column) {
- case LOCATION:
- ret = QString(trip->location);
- break;
- case DATE:
- ret = QString(get_trip_date_string(trip->when, trip->nrdives));
+ case NR:
+ ret = QString(trip->location) + ", " + QString(get_trip_date_string(trip->when, trip->nrdives));
break;
}
}
@@ -837,7 +878,7 @@ QVariant DiveItem::data(int column, int role) const
break;
case SORT_ROLE:
switch (column) {
- case NR: retVal = dive->number; break;
+ case NR: retVal = (qulonglong) dive->when; break;
case DATE: retVal = (qulonglong) dive->when; break;
case RATING: retVal = dive->rating; break;
case DEPTH: retVal = dive->maxdepth.mm; break;
@@ -932,7 +973,7 @@ QString DiveItem::displaySac() const
QString str;
if (get_units()->volume == units::LITER)
- str = QString::number(dive->sac / 1000, 'f', 1);
+ str = QString::number(dive->sac / 1000.0, 'f', 1);
else
str = QString::number(ml_to_cuft(dive->sac), 'f', 2);
@@ -986,9 +1027,7 @@ QVariant DiveTripModel::data(const QModelIndex& index, int role) const
return QVariant();
if (role == Qt::FontRole) {
- QFont font;
- font.setPointSizeF(font.pointSizeF() * 0.7);
- return font;
+ return defaultModelFont();
}
TreeItemDT* item = static_cast<TreeItemDT*>(index.internalPointer());
@@ -1009,6 +1048,11 @@ QVariant DiveTripModel::headerData(int section, Qt::Orientation orientation,
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return rootItem->data(section, role);
+ switch(role){
+ case Qt::FontRole :
+ return defaultModelFont();
+ }
+
return QVariant();
}
@@ -1062,6 +1106,9 @@ void DiveTripModel::setupModelData()
endRemoveRows();
}
+ if (autogroup)
+ autogroup_dives();
+ dive_table.preexisting = dive_table.nr;
while (--i >= 0) {
struct dive* dive = get_dive(i);
update_cylinder_related_info(dive);
diff --git a/qt-ui/models.h b/qt-ui/models.h
index 5a7d2b214..b61c79cd6 100644
--- a/qt-ui/models.h
+++ b/qt-ui/models.h
@@ -14,6 +14,8 @@
#include "../dive.h"
#include "../divelist.h"
+QFont defaultModelFont();
+
/* Encapsulates the tank_info global variable
* to show on Qt's Model View System.*/
class TankInfoModel : public QAbstractTableModel {
@@ -30,10 +32,12 @@ public:
/*reimp*/ int rowCount(const QModelIndex& parent = QModelIndex()) const;
/*reimp*/ bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex());
/*reimp*/ bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
+ const QString& biggerString() const;
void clear();
void update();
private:
int rows;
+ QString biggerEntry;
};
/* Encapsulate ws_info */
@@ -51,11 +55,12 @@ public:
/*reimp*/ int rowCount(const QModelIndex& parent = QModelIndex()) const;
/*reimp*/ bool insertRows(int row, int count, const QModelIndex& parent = QModelIndex());
/*reimp*/ bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
+ const QString& biggerString() const;
void clear();
void update();
private:
int rows;
-
+ QString biggerEntry;
};
/* Encapsulation of the Cylinder Model, that presents the
diff --git a/qt-ui/profilegraphics.cpp b/qt-ui/profilegraphics.cpp
index cfd155132..126690750 100644
--- a/qt-ui/profilegraphics.cpp
+++ b/qt-ui/profilegraphics.cpp
@@ -1,4 +1,6 @@
#include "profilegraphics.h"
+#include "mainwindow.h"
+#include "divelistview.h"
#include <QGraphicsScene>
#include <QResizeEvent>
@@ -12,11 +14,13 @@
#include <QPropertyAnimation>
#include <QGraphicsSceneHoverEvent>
#include <QMouseEvent>
+#include <qtextdocument.h>
#include "../color.h"
#include "../display.h"
#include "../dive.h"
#include "../profile.h"
+#include "../device.h"
#include <libdivecomputer/parser.h>
#include <libdivecomputer/version.h>
@@ -145,6 +149,7 @@ void ProfileGraphicsView::wheelEvent(QWheelEvent* event)
// Scale the view / do the zoom
QPoint toolTipPos = mapFromScene(toolTip->pos());
+
double scaleFactor = 1.15;
if (event->delta() > 0 && zoomLevel <= 10) {
scale(scaleFactor, scaleFactor);
@@ -171,14 +176,20 @@ void ProfileGraphicsView::mouseMoveEvent(QMouseEvent* event)
ensureVisible(event->pos().x() + dx, event->pos().y() + dy, 1, 1);
- toolTip->setPos(mapToScene(toolTipPos).x(), mapToScene(toolTipPos).y());
-
if (zoomLevel == 0)
QGraphicsView::mouseMoveEvent(event);
+ else
+ toolTip->setPos(mapToScene(toolTipPos).x(), mapToScene(toolTipPos).y());
}
bool ProfileGraphicsView::eventFilter(QObject* obj, QEvent* event)
{
+ if (event->type() == QEvent::Leave) {
+ if (toolTip && toolTip->isExpanded())
+ toolTip->collapse();
+ return true;
+ }
+
// This will "Eat" the default tooltip behavior.
if (event->type() == QEvent::GraphicsSceneHelp) {
event->ignore();
@@ -206,7 +217,7 @@ void ProfileGraphicsView::showEvent(QShowEvent* event)
// but the dive was not ploted.
// force a replot by modifying the dive
// hold by the view, and issuing a plot.
- if (dive) {
+ if (dive && !scene()->items().count()) {
dive = 0;
plot(get_dive(selected_dive));
}
@@ -214,10 +225,14 @@ void ProfileGraphicsView::showEvent(QShowEvent* event)
void ProfileGraphicsView::clear()
{
- scene()->clear();
resetTransform();
zoomLevel = 0;
- toolTip = 0;
+ if(toolTip){
+ scene()->removeItem(toolTip);
+ toolTip->deleteLater();
+ toolTip = 0;
+ }
+ scene()->clear();
}
void ProfileGraphicsView::refresh()
@@ -243,42 +258,32 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
return;
}
+ // best place to put the focus stealer code.
+ setFocusProxy(mainWindow()->dive_list());
scene()->setSceneRect(0,0, viewport()->width()-50, viewport()->height()-50);
- QSettings s;
- s.beginGroup("ProfileMap");
- QPointF toolTipPos = s.value("tooltip_position", QPointF(0,0)).toPointF();
- s.endGroup();
-
toolTip = new ToolTipItem();
- toolTip->setPos(toolTipPos);
-
+ installEventFilter(toolTip);
scene()->addItem(toolTip);
// Fix this for printing / screen later.
// plot_set_scale(scale_mode_t);
if (!dc->samples) {
- static struct sample fake[4];
- static struct divecomputer fakedc;
- fakedc = dive->dc;
- fakedc.sample = fake;
- fakedc.samples = 4;
-
- /* The dive has no samples, so create a few fake ones. This assumes an
- ascent/descent rate of 9 m/min, which is just below the limit for FAST. */
- int duration = dive->dc.duration.seconds;
- int maxdepth = dive->dc.maxdepth.mm;
- int asc_desc_time = dive->dc.maxdepth.mm*60/9000;
- if (asc_desc_time * 2 >= duration)
- asc_desc_time = duration / 2;
- fake[1].time.seconds = asc_desc_time;
- fake[1].depth.mm = maxdepth;
- fake[2].time.seconds = duration - asc_desc_time;
- fake[2].depth.mm = maxdepth;
- fake[3].time.seconds = duration * 1.00;
- fakedc.events = dc->events;
- dc = &fakedc;
+ dc = fake_dc(dc);
+ }
+
+ QString nick(get_dc_nickname(dc->model, dc->deviceid));
+ if (nick.isEmpty())
+ nick = QString(dc->model);
+
+ if (nick.isEmpty())
+ nick = tr("unknown divecomputer");
+
+ if ( tr("unknown divecomputer") == nick){
+ mode = PLAN;
+ }else{
+ mode = DIVE;
}
/*
@@ -291,7 +296,7 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
gc.maxx = (profile_grid_area.width() - 2 * profile_grid_area.x());
gc.maxy = (profile_grid_area.height() - 2 * profile_grid_area.y());
- /* This is per-dive-computer. Right now we just do the first one */
+ /* This is per-dive-computer */
gc.pi = *create_plot_info(dive, dc, &gc);
/* Depth profile */
@@ -303,7 +308,7 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
plot_temperature_profile();
/* Cylinder pressure plot */
- plot_cylinder_pressure(dive, dc);
+ plot_cylinder_pressure(dc);
/* Text on top of all graphs.. */
plot_temperature_text();
@@ -322,13 +327,6 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
scene()->addItem(rect);
/* Put the dive computer name in the lower left corner */
- QString nick(get_dc_nickname(dc->model, dc->deviceid));
- if (nick.isEmpty())
- nick = QString(dc->model);
-
- if (nick.isEmpty())
- nick = tr("unknown divecomputer");
-
gc.leftx = 0; gc.rightx = 1.0;
gc.topy = 0; gc.bottomy = 1.0;
@@ -342,7 +340,6 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
plot_pp_text();
}
-
/* now shift the translation back by half the margin;
* this way we can draw the vertical scales on both sides */
//cairo_translate(gc->cr, -drawing_area->x / 2.0, 0);
@@ -366,6 +363,16 @@ void ProfileGraphicsView::plot(struct dive *d, bool forceRedraw)
if (zoomLevel == 0) {
fitInView(sceneRect());
}
+ toolTip->readPos();
+
+ if(mode == PLAN){
+ timeEditor = new GraphicsTextEditor();
+ timeEditor->setPlainText( dive->duration.seconds ? QString::number(dive->duration.seconds/60) : tr("Set Duration: 10 minutes"));
+ timeEditor->setPos(profile_grid_area.width() - timeEditor->boundingRect().width(), timeMarkers->y());
+ timeEditor->document();
+ connect(timeEditor, SIGNAL(editingFinished(QString)), this, SLOT(edit_dive_time(QString)));
+ scene()->addItem(timeEditor);
+ }
}
void ProfileGraphicsView::plot_depth_scale()
@@ -420,6 +427,17 @@ void ProfileGraphicsView::plot_pp_text()
}
}
+void ProfileGraphicsView::plot_add_line(int sec, double val, QColor c, QPointF &from)
+{
+ QPointF to = QPointF(SCALEGC(sec, val));
+ QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
+ QPen pen(defaultPen);
+ pen.setColor(c);
+ item->setPen(pen);
+ scene()->addItem(item);
+ from = to;
+}
+
void ProfileGraphicsView::plot_pp_gas_profile()
{
int i;
@@ -435,17 +453,10 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->pn2));
for (i = 1; i < pi->nr; i++) {
entry++;
- if (entry->pn2 < prefs.pp_graphs.pn2_threshold) {
- to = QPointF(SCALEGC(entry->sec, entry->pn2));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- from = to;
- } else {
+ if (entry->pn2 < prefs.pp_graphs.pn2_threshold)
+ plot_add_line(entry->sec, entry->pn2, c, from);
+ else
from = QPointF(SCALEGC(entry->sec, entry->pn2));
- }
}
c = profile_color[PN2_ALERT].first();
@@ -453,17 +464,10 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->pn2));
for (i = 1; i < pi->nr; i++) {
entry++;
- if (entry->pn2 >= prefs.pp_graphs.pn2_threshold) {
- to = QPointF(SCALEGC(entry->sec, entry->pn2));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- from = to;
- } else {
+ if (entry->pn2 >= prefs.pp_graphs.pn2_threshold)
+ plot_add_line(entry->sec, entry->pn2, c, from);
+ else
from = QPointF(SCALEGC(entry->sec, entry->pn2));
- }
}
}
@@ -474,17 +478,10 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->phe));
for (i = 1; i < pi->nr; i++) {
entry++;
- if (entry->phe < prefs.pp_graphs.phe_threshold) {
- to = QPointF(SCALEGC(entry->sec, entry->phe));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- from = to;
- } else {
+ if (entry->phe < prefs.pp_graphs.phe_threshold)
+ plot_add_line(entry->sec, entry->phe, c, from);
+ else
from = QPointF(SCALEGC(entry->sec, entry->phe));
- }
}
c = profile_color[PHE_ALERT].first();
@@ -492,17 +489,10 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->phe));
for (i = 1; i < pi->nr; i++) {
entry++;
- if (entry->phe >= prefs.pp_graphs.phe_threshold) {
- to = QPointF(SCALEGC(entry->sec, entry->phe));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- from = to;
- } else {
+ if (entry->phe >= prefs.pp_graphs.phe_threshold)
+ plot_add_line(entry->sec, entry->phe, c, from);
+ else
from = QPointF(SCALEGC(entry->sec, entry->phe));
- }
}
}
if (prefs.pp_graphs.po2) {
@@ -511,17 +501,10 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->po2));
for (i = 1; i < pi->nr; i++) {
entry++;
- if (entry->po2 < prefs.pp_graphs.po2_threshold) {
- to = QPointF(SCALEGC(entry->sec, entry->po2));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- QPen pen(defaultPen);
- pen.setColor(c);
- item->setPen(pen);
- scene()->addItem(item);
- from = to;
- } else {
+ if (entry->po2 < prefs.pp_graphs.po2_threshold)
+ plot_add_line(entry->sec, entry->po2, c, from);
+ else
from = QPointF(SCALEGC(entry->sec, entry->po2));
- }
}
c = profile_color[PO2_ALERT].first();
@@ -529,15 +512,10 @@ void ProfileGraphicsView::plot_pp_gas_profile()
from = QPointF(SCALEGC(entry->sec, entry->po2));
for (i = 1; i < pi->nr; i++) {
entry++;
- if (entry->po2 >= prefs.pp_graphs.po2_threshold) {
- to = QPointF(SCALEGC(entry->sec, entry->po2));
- QGraphicsLineItem *item = new QGraphicsLineItem(from.x(), from.y(), to.x(), to.y());
- item->setPen(QPen(c));
- scene()->addItem(item);
- from = to;
- } else {
+ if (entry->po2 >= prefs.pp_graphs.po2_threshold)
+ plot_add_line(entry->sec, entry->po2, c, from);
+ else
from = QPointF(SCALEGC(entry->sec, entry->po2));
- }
}
}
}
@@ -720,7 +698,7 @@ void ProfileGraphicsView::plot_single_temp_text(int sec, int mkelvin)
plot_text(&tro, QPointF(sec, mkelvin), QString("%1%2").arg(deg, 0, 'f', 1).arg(unit)); //"%.2g%s"
}
-void ProfileGraphicsView::plot_cylinder_pressure(struct dive *dive, struct divecomputer *dc)
+void ProfileGraphicsView::plot_cylinder_pressure(struct divecomputer *dc)
{
int i;
int last = -1, last_index = -1;
@@ -1213,6 +1191,12 @@ void ProfileGraphicsView::plot_temperature_profile()
}
}
+void ProfileGraphicsView::edit_dive_time(const QString& time)
+{
+ // this should set the full time of the dive.
+ refresh();
+}
+
void ToolTipItem::addToolTip(const QString& toolTip, const QIcon& icon)
{
QGraphicsPixmapItem *iconItem = 0;
@@ -1324,6 +1308,9 @@ void ToolTipItem::collapse()
animation->setStartValue(boundingRect());
animation->setEndValue(QRect(0, 0, ICON_SMALL, ICON_SMALL));
animation->start(QAbstractAnimation::DeleteWhenStopped);
+ clear();
+
+ status = COLLAPSED;
}
void ToolTipItem::expand()
@@ -1358,20 +1345,26 @@ void ToolTipItem::expand()
animation->setEndValue(nextRectangle);
animation->start(QAbstractAnimation::DeleteWhenStopped);
+ status = EXPANDED;
}
ToolTipItem::ToolTipItem(QGraphicsItem* parent): QGraphicsPathItem(parent), background(0)
{
title = new QGraphicsSimpleTextItem(tr("Information"), this);
separator = new QGraphicsLineItem(this);
-
+ dragging = false;
setFlag(ItemIgnoresTransformations);
- setFlag(ItemIsMovable);
-
+ status = COLLAPSED;
updateTitlePosition();
setZValue(99);
}
+ToolTipItem::~ToolTipItem()
+{
+ clear();
+}
+
+
void ToolTipItem::updateTitlePosition()
{
if (rectangle.width() < title->boundingRect().width() + SPACING*4) {
@@ -1401,6 +1394,51 @@ void ToolTipItem::updateTitlePosition()
}
}
+bool ToolTipItem::isExpanded() {
+ return status == EXPANDED;
+}
+
+void ToolTipItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+{
+ persistPos();
+ dragging = false;
+}
+
+void ToolTipItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
+{
+ dragging = true;
+}
+
+void ToolTipItem::persistPos()
+{
+ QPoint currentPos = scene()->views().at(0)->mapFromScene(pos());
+ QSettings s;
+ s.beginGroup("ProfileMap");
+ s.setValue("tooltip_position", currentPos);
+ s.endGroup();
+ s.sync();
+}
+
+void ToolTipItem::readPos()
+{
+ QSettings s;
+ s.beginGroup("ProfileMap");
+ QPointF value = scene()->views().at(0)->mapToScene(
+ s.value("tooltip_position").toPoint()
+ );
+ setPos(value);
+}
+
+bool ToolTipItem::eventFilter(QObject* view, QEvent* event)
+{
+ if (event->type() == QEvent::HoverMove && dragging){
+ QHoverEvent *e = static_cast<QHoverEvent*>(event);
+ QGraphicsView *v = scene()->views().at(0);
+ setPos( v->mapToScene(e->pos()));
+ }
+ return false;
+}
+
EventItem::EventItem(QGraphicsItem* parent): QGraphicsPolygonItem(parent)
{
setFlag(ItemIgnoresTransformations);
@@ -1431,5 +1469,27 @@ EventItem::EventItem(QGraphicsItem* parent): QGraphicsPolygonItem(parent)
QGraphicsEllipseItem *ball = new QGraphicsEllipseItem(-1, 12, 2,2, this);
ball->setBrush(QBrush(Qt::black));
+}
+GraphicsTextEditor::GraphicsTextEditor(QGraphicsItem* parent): QGraphicsTextItem(parent)
+{
+}
+
+void GraphicsTextEditor::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
+{
+ // Remove the proxy filter so we can focus here.
+ mainWindow()->graphics()->setFocusProxy(0);
+ setTextInteractionFlags(Qt::TextEditorInteraction | Qt::TextEditable);
+}
+
+void GraphicsTextEditor::keyReleaseEvent(QKeyEvent* event)
+{
+ if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return){
+ setTextInteractionFlags(Qt::NoTextInteraction);
+ emit editingFinished( toPlainText() );
+ mainWindow()->graphics()->setFocusProxy(mainWindow()->dive_list());
+ return;
+ }
+ emit textChanged( toPlainText() );
+ QGraphicsTextItem::keyReleaseEvent(event);
}
diff --git a/qt-ui/profilegraphics.h b/qt-ui/profilegraphics.h
index b440adf5d..ccc4841cb 100644
--- a/qt-ui/profilegraphics.h
+++ b/qt-ui/profilegraphics.h
@@ -5,6 +5,9 @@
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QIcon>
+#include <QDoubleSpinBox>
+#include <QPushButton>
+#include <QGraphicsProxyWidget>
struct text_render_options;
struct graphics_context;
@@ -25,6 +28,7 @@ public:
enum {ICON_SMALL = 16, ICON_MEDIUM = 24, ICON_BIG = 32, SPACING=4};
explicit ToolTipItem(QGraphicsItem* parent = 0);
+ virtual ~ToolTipItem();
void collapse();
void expand();
@@ -32,7 +36,12 @@ public:
void addToolTip(const QString& toolTip, const QIcon& icon = QIcon());
void removeToolTip(const QString& toolTip);
void refresh(struct graphics_context* gc, QPointF pos);
-
+ bool isExpanded();
+ void persistPos();
+ void readPos();
+ void mousePressEvent(QGraphicsSceneMouseEvent* event);
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
+ bool eventFilter(QObject* , QEvent* );
public Q_SLOTS:
void setRect(const QRectF& rect);
@@ -42,8 +51,9 @@ private:
QGraphicsPathItem *background;
QGraphicsLineItem *separator;
QGraphicsSimpleTextItem *title;
-
+ Status status;
QRectF rectangle;
+ bool dragging;
};
class EventItem : public QGraphicsPolygonItem
@@ -57,10 +67,26 @@ private:
QIcon icon;
};
+class GraphicsTextEditor : public QGraphicsTextItem{
+ Q_OBJECT
+public:
+ GraphicsTextEditor(QGraphicsItem* parent = 0);
+
+protected:
+ virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event);
+ virtual void keyReleaseEvent(QKeyEvent* event);
+
+signals:
+ void textChanged(const QString& text);
+ void editingFinished(const QString& text);
+};
+
class ProfileGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
+ enum Mode{DIVE, PLAN};
+
ProfileGraphicsView(QWidget* parent = 0);
void plot(struct dive *d, bool forceRedraw = FALSE);
bool eventFilter(QObject* obj, QEvent* event);
@@ -74,6 +100,7 @@ protected:
public Q_SLOTS:
void refresh();
+ void edit_dive_time(const QString& time);
private:
void plot_depth_profile();
@@ -81,7 +108,7 @@ private:
void plot_events(struct divecomputer *dc);
void plot_one_event(struct event *event);
void plot_temperature_profile();
- void plot_cylinder_pressure(struct dive *dive, struct divecomputer *dc);
+ void plot_cylinder_pressure(struct divecomputer *dc);
void plot_temperature_text();
void plot_single_temp_text(int sec, int mkelvin);
void plot_depth_text();
@@ -91,6 +118,7 @@ private:
void plot_pressure_value(int mbar, int sec, double xalign, double yalign);
void plot_gas_value(int mbar, int sec, double xalign, double yalign, int o2, int he);
void plot_deco_text();
+ void plot_add_line(int sec, double val, QColor c, QPointF &from);
void plot_pp_gas_profile();
void plot_pp_text();
void plot_depth_scale();
@@ -110,6 +138,12 @@ private:
QGraphicsItem* timeMarkers;
QGraphicsItem* depthMarkers;
QGraphicsItem* diveComputer;
+
+ // For 'Plan' mode.:
+ GraphicsTextEditor *depthEditor;
+ GraphicsTextEditor *timeEditor;
+
+ enum Mode mode;
};
#endif
diff --git a/qt-ui/subsurfacewebservices.cpp b/qt-ui/subsurfacewebservices.cpp
index 2f82d6d26..cd944ca17 100644
--- a/qt-ui/subsurfacewebservices.cpp
+++ b/qt-ui/subsurfacewebservices.cpp
@@ -59,10 +59,14 @@ void SubsurfaceWebServices::buttonClicked(QAbstractButton* button)
QSettings s;
s.setValue("webservice_uid", ui->userID->text());
s.sync();
+ hide();
+ close();
}
break;
case QDialogButtonBox::RejectRole:
- manager->deleteLater();
+ // we may want to clean up after ourselves, but this
+ // makes Subsurface throw a SIGSEGV...
+ // manager->deleteLater();
reply->deleteLater();
ui->progressBar->setMaximum(1);
break;
@@ -90,7 +94,7 @@ void SubsurfaceWebServices::startDownload()
ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
- connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
+ connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(downloadError(QNetworkReply::NetworkError)));
}
diff --git a/statistics.c b/statistics.c
index 6459b3802..ece5419d9 100644
--- a/statistics.c
+++ b/statistics.c
@@ -352,7 +352,11 @@ char *get_gaslist(struct dive *dive)
if (is_air(o2, he))
snprintf(buf + offset, MAXBUF - offset, (offset > 0) ? ", %s" : "%s", _("air"));
else
- snprintf(buf + offset, MAXBUF - offset, (offset > 0) ? ", %d/%d" : "%d/%d",
+ if (he == 0)
+ snprintf(buf + offset, MAXBUF - offset, (offset > 0) ? _(", EAN%d") : _("EAN%d"),
+ (o2 + 5) / 10);
+ else
+ snprintf(buf + offset, MAXBUF - offset, (offset > 0) ? ", %d/%d" : "%d/%d",
(o2 + 5) / 10, (he + 5) / 10);
offset = strlen(buf);
}
diff --git a/xslt/uddf.xslt b/xslt/uddf.xslt
index 1d65d2d19..274280169 100644
--- a/xslt/uddf.xslt
+++ b/xslt/uddf.xslt
@@ -2,7 +2,7 @@
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:u="http://www.streit.cc/uddf/3.2/"
xmlns:u1="http://www.streit.cc/uddf/3.1/"
- exclude-result-prefixes="u"
+ exclude-result-prefixes="u u1"
version="1.0">
<xsl:import href="commonTemplates.xsl"/>
<xsl:strip-space elements="*"/>
@@ -12,11 +12,18 @@
<divelog program="subsurface-import" version="2">
<settings>
<divecomputerid deviceid="ffffffff">
- <xsl:apply-templates select="/uddf/generator|/u:uddf/u:generator|/u1:uddf/u1:generator"/>
+ <xsl:choose>
+ <xsl:when test="/UDDF/history != ''">
+ <xsl:apply-templates select="/UDDF/history"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="/uddf/generator|/u:uddf/u:generator|/u1:uddf/u1:generator"/>
+ </xsl:otherwise>
+ </xsl:choose>
</divecomputerid>
</settings>
<dives>
- <xsl:apply-templates select="/uddf/profiledata/repetitiongroup/dive|/u:uddf/u:profiledata/u:repetitiongroup/u:dive|/u1:uddf/u1:profiledata/u1:repetitiongroup/u1:dive"/>
+ <xsl:apply-templates select="/uddf/profiledata/repetitiongroup/dive|/u:uddf/u:profiledata/u:repetitiongroup/u:dive|/u1:uddf/u1:profiledata/u1:repetitiongroup/u1:dive|/UDDF/dive"/>
</dives>
</divelog>
</xsl:template>
@@ -39,11 +46,24 @@
</xsl:if>
</xsl:template>
- <xsl:template match="gasdefinitions|u:gasdefinitions|u1:gasdefinitions">
- <xsl:for-each select="mix|u:mix|u1:mix">
+ <xsl:template match="modified">
+ <xsl:if test="application/name != ''">
+ <xsl:attribute name="model">
+ <xsl:value-of select="application/name"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="application/version != ''">
+ <xsl:attribute name="serial">
+ <xsl:value-of select="application/version"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="gasdefinitions|u:gasdefinitions|u1:gasdefinitions|gas_def">
+ <xsl:for-each select="mix|u:mix|u1:mix|gas_mix">
<cylinder>
<xsl:attribute name="description">
- <xsl:value-of select="name|u:name|u1:name"/>
+ <xsl:value-of select="name|u:name|u1:name|mixname"/>
</xsl:attribute>
<xsl:attribute name="o2">
@@ -69,7 +89,7 @@
<dive>
<!-- Count the amount of temeprature samples during the dive -->
<xsl:variable name="temperatureSamples">
- <xsl:call-template name="temperatureSamples" select="samples/waypoint/temperature|u:samples/u:waypoint/u:temperature|u1:samples/u1:waypoint/u1:temperature">
+ <xsl:call-template name="temperatureSamples" select="samples/waypoint/temperature|u:samples/u:waypoint/u:temperature|u1:samples/u1:waypoint/u1:temperature|samples/t">
<xsl:with-param name="units" select="'Kelvin'"/>
</xsl:call-template>
</xsl:variable>
@@ -91,8 +111,90 @@
</xsl:call-template>
</xsl:when>
</xsl:choose>
+ <xsl:if test="dive_number != ''">
+ <xsl:attribute name="number">
+ <xsl:value-of select="dive_number"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="dive_duration != '' and dive_duration != 0">
+ <xsl:attribute name="duration">
+ <xsl:call-template name="timeConvert">
+ <xsl:with-param name="timeSec">
+ <xsl:value-of select="dive_duration"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
- <xsl:for-each select="lowesttemperature|informationafterdive/lowesttemperature|u:lowesttemperature|u:informationafterdive/u:lowesttemperature|u1:lowesttemperature|u1:informationafterdive/u1:lowesttemperature">
+ <xsl:if test="condition/visibility != '' and condition/visibility != 0">
+ <xsl:attribute name="visibility">
+ <xsl:choose>
+ <xsl:when test="condition/visibility &lt; 1">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:when test="condition/visibility &lt;= 3">
+ <xsl:value-of select="2"/>
+ </xsl:when>
+ <xsl:when test="condition/visibility &lt;= 5">
+ <xsl:value-of select="3"/>
+ </xsl:when>
+ <xsl:when test="condition/visibility &lt;= 10">
+ <xsl:value-of select="4"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="5"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+
+ <xsl:if test="condition/air_temp != ''">
+ <divetemperature>
+ <xsl:attribute name="air">
+ <xsl:value-of select="concat(format-number(condition/air_temp - 273.15, '0.0'), ' C')"/>
+ </xsl:attribute>
+ </divetemperature>
+ </xsl:if>
+
+ <xsl:if test="dive_site_ref/@ref != ''">
+ <location>
+ <xsl:variable name="ref">
+ <xsl:value-of select="dive_site_ref/@ref"/>
+ </xsl:variable>
+ <xsl:for-each select="//dive_site[@id=$ref]/geography/location|//dive_site[@id=$ref]/name">
+ <xsl:value-of select="."/>
+ <xsl:if test=". != '' and following-sibling::*[1]/* != ''"> / </xsl:if>
+ </xsl:for-each>
+ </location>
+ </xsl:if>
+
+ <xsl:if test="buddy_ref/@ref != ''">
+ <buddy>
+ <xsl:variable name="ref">
+ <xsl:value-of select="buddy_ref/@ref"/>
+ </xsl:variable>
+ <xsl:for-each select="//diver[@id=$ref]/personal/first_name|//diver[@id=$ref]/personal/nick_name|//diver[@id=$ref]/personal/family_name">
+ <xsl:value-of select="."/>
+ <xsl:if test=". != '' and (following-sibling::*[1] != '' or following-sibling::*[2] != '')"> / </xsl:if>
+ </xsl:for-each>
+ </buddy>
+ </xsl:if>
+
+ <xsl:if test="note/text != ''">
+ <notes>
+ <xsl:value-of select="note/text"/>
+ </notes>
+ </xsl:if>
+
+ <xsl:if test="equipment_used/weight_used &gt; 0">
+ <weightsystem description="unknown">
+ <xsl:attribute name="weight">
+ <xsl:value-of select="concat(format-number(equipment_used/weight_used, '0.0'), ' kg')"/>
+ </xsl:attribute>
+ </weightsystem>
+ </xsl:if>
+
+ <xsl:for-each select="lowesttemperature|informationafterdive/lowesttemperature|u:lowesttemperature|u:informationafterdive/u:lowesttemperature|u1:lowesttemperature|u1:informationafterdive/u1:lowesttemperature|condition/water_temp">
<temperature>
<xsl:if test="$temperatureSamples &gt; 0 or . != 273.15">
<xsl:attribute name="water">
@@ -104,24 +206,76 @@
<divecomputer deviceid="ffffffff">
<xsl:attribute name="model">
- <xsl:value-of select="/uddf/generator/name|/u:uddf/u:generator/u:name|/u1:uddf/u1:generator/u1:name"/>
+ <xsl:value-of select="/uddf/generator/name|/u:uddf/u:generator/u:name|/u1:uddf/u1:generator/u1:name|/UDDF/history/modified/application/name"/>
</xsl:attribute>
</divecomputer>
+ <xsl:if test="equipment_used/tank_used != ''">
+ <xsl:for-each select="equipment_used/tank_used">
+ <cylinder>
+ <xsl:variable name="idx">
+ <xsl:value-of select="./tank_ref/@ref"/>
+ </xsl:variable>
+ <xsl:attribute name="size">
+ <xsl:value-of select="//equipment[@id=$idx]/tank/volume"/>
+ </xsl:attribute>
+ <xsl:attribute name="description">
+ <xsl:value-of select="//equipment[@id=$idx]/general/name"/>
+ </xsl:attribute>
+ <xsl:attribute name="start">
+ <xsl:value-of select="concat(substring-before(./pressure_start, '.') div 100000, ' bar')"/>
+ </xsl:attribute>
+ <xsl:attribute name="end">
+ <xsl:value-of select="concat(substring-before(./pressure_end, '.') div 100000, ' bar')"/>
+ </xsl:attribute>
+ </cylinder>
+ </xsl:for-each>
+ </xsl:if>
+
<xsl:apply-templates select="/uddf/gasdefinitions|/u:uddf/u:gasdefinitions|/u1:uddf/u1:gasdefinitions"/>
<depth>
- <xsl:for-each select="greatestdepth|informationafterdive/greatestdepth|u:greatestdepth|u:informationafterdive/u:greatestdepth|u1:greatestdepth|u1:informationafterdive/u1:greatestdepth">
+ <xsl:for-each select="greatestdepth|informationafterdive/greatestdepth|u:greatestdepth|u:informationafterdive/u:greatestdepth|u1:greatestdepth|u1:informationafterdive/u1:greatestdepth|max_depth">
<xsl:attribute name="max">
- <xsl:value-of select="concat(., ' m')"/>
+ <xsl:value-of select="concat(format-number(., '0.00'), ' m')"/>
</xsl:attribute>
</xsl:for-each>
<xsl:for-each select="averagedepth|informationafterdive/averagedepth|u:averagedepth|u:informationafterdive/u:averagedepth|u1:averagedepth|u1:informationafterdive/u1:averagedepth">
<xsl:attribute name="mean">
- <xsl:value-of select="concat(., ' m')"/>
+ <xsl:value-of select="concat(format-number(., '0.00'), ' m')"/>
</xsl:attribute>
</xsl:for-each>
</depth>
+ <!-- Aquadivelog gas switches require more lookups than other UDDF
+ formats I have seen -->
+ <xsl:for-each select="samples/switch">
+ <xsl:variable name="tank_idx">
+ <xsl:value-of select="./@tank"/>
+ </xsl:variable>
+ <xsl:variable name="idx">
+ <xsl:value-of select="//equipment_used/tank_used[@id=$tank_idx]/gas_ref/@ref"/>
+ </xsl:variable>
+
+ <event name="gaschange" type="11">
+ <xsl:attribute name="time">
+ <xsl:call-template name="timeConvert">
+ <xsl:with-param name="timeSec">
+ <xsl:value-of select="following-sibling::t"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:attribute>
+
+ <xsl:attribute name="value">
+ <xsl:call-template name="gasConvert">
+ <xsl:with-param name="mix">
+ <xsl:value-of select="//gas_def/gas_mix[@id=$idx]/o2"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:attribute>
+ </event>
+ </xsl:for-each>
+
+ <!-- Other gas switches than Aquadivelog -->
<xsl:for-each select="samples/waypoint/switchmix|u:samples/u:waypoint/u:switchmix|u1:samples/u1:waypoint/u1:switchmix">
<!-- Index to lookup gas per cent -->
<xsl:variable name="idx">
@@ -147,26 +301,33 @@
</event>
</xsl:for-each>
- <xsl:for-each select="samples/waypoint|u:samples/u:waypoint|u1:samples/u1:waypoint">
+ <xsl:for-each select="samples/waypoint|u:samples/u:waypoint|u1:samples/u1:waypoint|samples/d">
<sample>
<xsl:attribute name="time">
<xsl:call-template name="timeConvert">
<xsl:with-param name="timeSec">
- <xsl:value-of select="divetime|u:divetime|u1:divetime"/>
+ <xsl:value-of select="divetime|u:divetime|u1:divetime|preceding-sibling::t[1]"/>
</xsl:with-param>
</xsl:call-template>
</xsl:attribute>
- <xsl:if test="depth != ''">
- <xsl:attribute name="depth">
- <xsl:value-of select="concat(depth, ' m')"/>
- </xsl:attribute>
- </xsl:if>
- <xsl:if test="u:depth|u1:depth != ''">
- <xsl:attribute name="depth">
- <xsl:value-of select="concat(u:depth|u1:depth, ' m')"/>
- </xsl:attribute>
- </xsl:if>
+ <xsl:choose>
+ <xsl:when test="depth != ''">
+ <xsl:attribute name="depth">
+ <xsl:value-of select="concat(format-number(depth, '0.00'), ' m')"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="u:depth|u1:depth != ''">
+ <xsl:attribute name="depth">
+ <xsl:value-of select="concat(format-number(u:depth|u1:depth, '0.00'), ' m')"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test=". != 0">
+ <xsl:attribute name="depth">
+ <xsl:value-of select="concat(format-number(., '0.00'), ' m')"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
<xsl:if test="temperature != '' and $temperatureSamples &gt; 0">
<xsl:attribute name="temperature">