summaryrefslogtreecommitdiffstats
path: root/qt-ui/diveplanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qt-ui/diveplanner.cpp')
-rw-r--r--qt-ui/diveplanner.cpp505
1 files changed, 394 insertions, 111 deletions
diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp
index 39d3b20a8..e7c1b1962 100644
--- a/qt-ui/diveplanner.cpp
+++ b/qt-ui/diveplanner.cpp
@@ -1,34 +1,45 @@
#include "diveplanner.h"
#include "graphicsview-common.h"
+#include "models.h"
+#include "modeldelegates.h"
+#include "ui_diveplanner.h"
+#include "mainwindow.h"
#include "../dive.h"
#include "../divelist.h"
-#include <cmath>
+#include "../planner.h"
+
#include <QMouseEvent>
#include <QDebug>
-#include <QGraphicsWidget>
-#include <QGraphicsProxyWidget>
-#include <QPushButton>
#include <QGraphicsSceneMouseEvent>
#include <QMessageBox>
#include <QStringListModel>
-#include <QGraphicsProxyWidget>
#include <QListView>
-#include <QDesktopWidget>
#include <QModelIndex>
-
-#include "ui_diveplanner.h"
-#include "mainwindow.h"
+#include <QSettings>
#define TIME_INITIAL_MAX 30
#define MAX_DEEPNESS 150
#define MIN_DEEPNESS 40
-bool handlerLessThenMinutes(DiveHandler *d1, DiveHandler *d2){
- return d1->sec < d2->sec;
+QStringListModel *airTypes(){
+ static QStringListModel *self = new QStringListModel(QStringList()
+ << QObject::tr("AIR")
+ << QObject::tr("EAN32")
+ << QObject::tr("EAN36"));
+ return self;
}
+QString strForAir(const divedatapoint& p){
+ return p.o2 == 209 ? QObject::tr("AIR")
+ : p.o2 == 320 ? QObject::tr("EAN32")
+ : p.o2 == 360 ? QObject::tr("EAN36")
+ : QObject::tr("Choose Gas");
+}
+
+static DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
+
DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent), activeDraggedHandler(0)
{
fill_profile_color();
@@ -111,16 +122,10 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
connect(obj, SIGNAL(clicked()), this, SLOT(slot));
ADDBTN(plusDepth, ":plus", "" , 5, 5, tr("Increase maximum depth by 10m"), increaseDepth());
- ADDBTN(plusTime, ":plus", "" , 95, 5, tr("Increase minimum time by 10m"), increaseTime());
+ ADDBTN(plusTime, ":plus", "" , 95, 95, tr("Increase minimum time by 10m"), increaseTime());
ADDBTN(lessDepth, ":minimum","" , 2, 5, tr("Decreases maximum depth by 10m"), decreaseDepth());
ADDBTN(lessTime, ":minimum","" , 92, 95, tr("Decreases minimum time by 10m"), decreaseTime());
- ADDBTN(okBtn, "", tr("Ok"), 1, 95, "", okClicked());
- ADDBTN(cancelBtn, "", tr("Cancel"), 0,0, "", cancelClicked());
#undef ADDBTN
-
- cancelBtn->setPos(okBtn->pos().x() + okBtn->boundingRect().width()
- + fromPercent(2, Qt::Horizontal), fromPercent(95, Qt::Vertical));
-
minMinutes = TIME_INITIAL_MAX;
QAction *action = NULL;
@@ -141,31 +146,50 @@ DivePlannerGraphics::DivePlannerGraphics(QWidget* parent): QGraphicsView(parent)
#undef ADD_ACTION
// Prepare the stuff for the gas-choices.
- gasChoices = new QStringListModel(QStringList() << tr("AIR") << tr("EAN32") << tr("EAN36"));
- gasListView = new QListView(this);
- gasListView->setWindowFlags(Qt::FramelessWindowHint | Qt::Popup);
- gasListView->setModel(gasChoices);
- gasListView->setWindowModality(Qt::WindowModal);
+ gasListView = new QListView();
+ gasListView->setWindowFlags(Qt::Popup);
+ gasListView->setModel(airTypes());
gasListView->hide();
connect(gasListView, SIGNAL(activated(QModelIndex)), this, SLOT(selectGas(QModelIndex)));
+ connect(plannerModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(createDecoStops()));
+
+ connect(plannerModel, SIGNAL(rowsInserted(const QModelIndex&,int,int)),
+ this, SLOT(pointInserted(const QModelIndex&, int, int)));
+ connect(plannerModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
+ this, SLOT(pointsRemoved(const QModelIndex&, int, int)));
setRenderHint(QPainter::Antialiasing);
}
+void DivePlannerGraphics::pointInserted(const QModelIndex& parent, int start , int end)
+{
+ DiveHandler *item = new DiveHandler ();
+ scene()->addItem(item);
+ handles << item;
+
+ Button *gasChooseBtn = new Button();
+ scene()->addItem(gasChooseBtn);
+ gasChooseBtn->setZValue(10);
+ connect(gasChooseBtn, SIGNAL(clicked()), this, SLOT(prepareSelectGas()));
+
+ gases << gasChooseBtn;
+ createDecoStops();
+}
+
void DivePlannerGraphics::keyDownAction()
{
if(scene()->selectedItems().count()){
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- if (handler->mm / 1000 >= depthLine->maximum())
+ int row = handles.indexOf(handler);
+ divedatapoint dp = plannerModel->at(row);
+ if (dp.depth / 1000 >= depthLine->maximum())
continue;
- handler->mm += 1000;
- double ypos = depthLine->posAtValue(handler->mm / 1000);
- handler->setPos(handler->pos().x(), ypos);
+ dp.depth += 1000;
+ plannerModel->editStop(row, dp);
}
}
- createDecoStops();
}
}
@@ -173,12 +197,14 @@ void DivePlannerGraphics::keyUpAction()
{
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- if (handler->mm / 1000 <= 0)
+ int row = handles.indexOf(handler);
+ divedatapoint dp = plannerModel->at(row);
+
+ if (dp.depth / 1000 <= 0)
continue;
- handler->mm -= 1000;
- double ypos = depthLine->posAtValue(handler->mm / 1000);
- handler->setPos(handler->pos().x(), ypos);
+ dp.depth -= 1000;
+ plannerModel->editStop(row, dp);
}
}
createDecoStops();
@@ -188,12 +214,15 @@ void DivePlannerGraphics::keyLeftAction()
{
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- if (handler->sec / 60 <= 0)
+ int row = handles.indexOf(handler);
+ divedatapoint dp = plannerModel->at(row);
+
+ if (dp.time / 60 <= 0)
continue;
// don't overlap positions.
// maybe this is a good place for a 'goto'?
- double xpos = timeLine->posAtValue((handler->sec - 60) / 60);
+ double xpos = timeLine->posAtValue((dp.time - 60) / 60);
bool nextStep = false;
Q_FOREACH(DiveHandler *h, handles){
if (h->pos().x() == xpos){
@@ -204,23 +233,24 @@ void DivePlannerGraphics::keyLeftAction()
if(nextStep)
continue;
- handler->sec -= 60;
- handler->setPos(xpos, handler->pos().y());
+ dp.time -= 60;
+ plannerModel->editStop(row, dp);
}
}
- createDecoStops();
}
void DivePlannerGraphics::keyRightAction()
{
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- if (handler->sec / 60 >= timeLine->maximum())
+ int row = handles.indexOf(handler);
+ divedatapoint dp = plannerModel->at(row);
+ if (dp.time / 60 >= timeLine->maximum())
continue;
// don't overlap positions.
// maybe this is a good place for a 'goto'?
- double xpos = timeLine->posAtValue((handler->sec + 60) / 60);
+ double xpos = timeLine->posAtValue((dp.time + 60) / 60);
bool nextStep = false;
Q_FOREACH(DiveHandler *h, handles){
if (h->pos().x() == xpos){
@@ -231,32 +261,52 @@ void DivePlannerGraphics::keyRightAction()
if(nextStep)
continue;
- handler->sec += 60;
- handler->setPos(xpos, handler->pos().y());
+ dp.time += 60;
+ plannerModel->editStop(row, dp);
}
- } createDecoStops();
+ }
}
void DivePlannerGraphics::keyDeleteAction()
{
int selCount = scene()->selectedItems().count();
if(selCount){
-
- while(selCount--){
- Button *btn = gases.takeLast();
- delete btn;
- }
-
+ QVector<int> selectedIndexes;
Q_FOREACH(QGraphicsItem *i, scene()->selectedItems()){
if (DiveHandler *handler = qgraphicsitem_cast<DiveHandler*>(i)){
- handles.removeAll(handler);
- scene()->removeItem(handler);
- delete i;
+ selectedIndexes.push_back(handles.indexOf(handler));
}
}
+ plannerModel->removeSelectedPoints(selectedIndexes);
+ }
+}
- createDecoStops();
+void DivePlannerGraphics::pointsRemoved(const QModelIndex& , int start, int end)
+{ // start and end are inclusive.
+ int num = (end - start) + 1;
+ for(int i = num; i != 0; i--){
+ delete handles.back();
+ handles.pop_back();
+ delete gases.back();
+ gases.pop_back();
}
+ scene()->clearSelection();
+ createDecoStops();
+}
+
+bool intLessThan(int a, int b){
+ return a <= b;
+}
+void DivePlannerPointsModel::removeSelectedPoints(const QVector< int >& rows)
+{
+ int firstRow = rowCount() - rows.count();
+ QVector<int> v2 = rows;
+ std::sort(v2.begin(), v2.end(), intLessThan);
+ beginRemoveRows(QModelIndex(), firstRow, rowCount()-1);
+ for(int i = v2.count()-1; i >= 0; i--){
+ divepoints.remove(v2[i]);
+ }
+ endRemoveRows();
}
void DivePlannerGraphics::keyEscAction()
@@ -265,8 +315,7 @@ void DivePlannerGraphics::keyEscAction()
scene()->clearSelection();
return;
}
-
- cancelClicked();
+ cancelPlan();
}
qreal DivePlannerGraphics::fromPercent(qreal percent, Qt::Orientation orientation)
@@ -276,7 +325,7 @@ qreal DivePlannerGraphics::fromPercent(qreal percent, Qt::Orientation orientatio
return result;
}
-void DivePlannerGraphics::cancelClicked()
+void DivePlannerGraphics::cancelPlan()
{
if (handles.size()){
if (QMessageBox::warning(mainWindow(), tr("Save the Plan?"),
@@ -288,11 +337,6 @@ void DivePlannerGraphics::cancelClicked()
mainWindow()->showProfile();
}
-void DivePlannerGraphics::okClicked()
-{
- // todo.
-}
-
void DivePlannerGraphics::increaseDepth()
{
if (depthLine->maximum() + 10 > MAX_DEEPNESS)
@@ -324,7 +368,6 @@ void DivePlannerGraphics::decreaseDepth()
return;
}
}
-
depthLine->setMaximum(depthLine->maximum() - 10);
depthLine->updateTicks();
createDecoStops();
@@ -353,31 +396,7 @@ void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent* event)
int minutes = rint(timeLine->valueAt(mappedPos));
int meters = rint(depthLine->valueAt(mappedPos));
- double xpos = timeLine->posAtValue(minutes);
- double ypos = depthLine->posAtValue(meters);
- Q_FOREACH(DiveHandler* handler, handles){
- if (xpos == handler->pos().x()){
- qDebug() << "There's already an point at that place.";
- //TODO: Move this later to a KMessageWidget.
- return;
- }
- }
-
- DiveHandler *item = new DiveHandler ();
- item->sec = minutes * 60;
- item->mm = meters * 1000;
- item->setPos(QPointF(xpos, ypos));
- scene()->addItem(item);
- handles << item;
-
- Button *gasChooseBtn = new Button();
- gasChooseBtn ->setText(tr("Air"));
- scene()->addItem(gasChooseBtn);
- gasChooseBtn->setZValue(10);
- connect(gasChooseBtn, SIGNAL(clicked()), this, SLOT(prepareSelectGas()));
-
- gases << gasChooseBtn;
- createDecoStops();
+ plannerModel->addStop(meters * 1000, minutes * 60, tr("Air"), 0);
}
void DivePlannerGraphics::prepareSelectGas()
@@ -391,16 +410,15 @@ void DivePlannerGraphics::prepareSelectGas()
void DivePlannerGraphics::selectGas(const QModelIndex& index)
{
QString gasSelected = gasListView->model()->data(index, Qt::DisplayRole).toString();
- currentGasChoice->setText(gasSelected);
+ int idx = gases.indexOf(currentGasChoice);
+ plannerModel->setData(plannerModel->index(idx, DivePlannerPointsModel::GAS), gasSelected);
gasListView->hide();
}
-
void DivePlannerGraphics::createDecoStops()
{
qDeleteAll(lines);
lines.clear();
- qSort(handles.begin(), handles.end(), handlerLessThenMinutes);
// This needs to be done in the following steps:
// Get the user-input and calculate the dive info
@@ -413,18 +431,16 @@ void DivePlannerGraphics::createDecoStops()
diveplan.gflow = 30;
diveplan.gfhigh = 70;
diveplan.surface_pressure = 1013;
- DiveHandler *lastH = NULL;
- Q_FOREACH(DiveHandler *h, handles) {
- // these values need to come from the planner UI, eventually
- int o2 = 209;
- int he = 0;
- int po2 = 0;
- int deltaT = lastH ? h->sec - lastH->sec : h->sec;
- lastH = h;
- dp = plan_add_segment(&diveplan, deltaT, h->mm, o2, he, po2);
- dp->entered = TRUE;
- qDebug("time %d, depth %d", h->sec, h->mm);
+
+ int rowCount = plannerModel->rowCount();
+ int lastIndex = -1;
+ for(int i = 0; i < rowCount; i++){
+ divedatapoint p = plannerModel->at(i);
+ int deltaT = lastIndex != -1 ? p.time - plannerModel->at(lastIndex).time : p.time;
+ lastIndex = i;
+ dp = plan_add_segment(&diveplan, deltaT, p.depth, p.o2, p.he, p.po2);
}
+
#if DEBUG_PLAN
dump_plan(&diveplan);
#endif
@@ -449,19 +465,16 @@ void DivePlannerGraphics::createDecoStops()
}
// Re-position the user generated dive handlers
- Q_FOREACH(DiveHandler *h, handles){
- h->setPos(timeLine->posAtValue(h->sec / 60), depthLine->posAtValue(h->mm / 1000));
- }
-
- int gasCount = gases.count();
- for(int i = 0; i < gasCount; i++){
+ for(int i = 0; i < plannerModel->rowCount(); i++){
+ divedatapoint dp = plannerModel->at(i);
+ DiveHandler *h = handles.at(i);
+ h->setPos(timeLine->posAtValue(dp.time / 60), depthLine->posAtValue(dp.depth / 1000));
QPointF p1 = (i == 0) ? QPointF(timeLine->posAtValue(0), depthLine->posAtValue(0)) : handles[i-1]->pos();
QPointF p2 = handles[i]->pos();
-
QLineF line(p1, p2);
QPointF pos = line.pointAt(0.5);
gases[i]->setPos(pos);
- qDebug() << "Adding a gas at" << pos;
+ gases[i]->setText( strForAir(dp));
}
// (re-) create the profile with different colors for segments that were
@@ -620,8 +633,14 @@ void DivePlannerGraphics::mouseReleaseEvent(QMouseEvent* event)
}
}
- activeDraggedHandler->sec = rint(timeLine->valueAt(mappedPos)) * 60;
- activeDraggedHandler->mm = rint(depthLine->valueAt(mappedPos)) * 1000;
+ int pos = handles.indexOf(activeDraggedHandler);
+ divedatapoint data = plannerModel->at(pos);
+
+ data.depth = rint(depthLine->valueAt(mappedPos)) * 1000;
+ data.time = rint(timeLine->valueAt(mappedPos)) * 60;
+
+ plannerModel->editStop(pos, data);
+
activeDraggedHandler->setBrush(QBrush(Qt::white));
activeDraggedHandler->setPos(QPointF(xpos, ypos));
@@ -646,6 +665,10 @@ void DiveHandler::mousePressEvent(QGraphicsSceneMouseEvent* event)
}
// mousePressEvent 'grabs' the mouse and keyboard, annoying.
ungrabMouse();
+
+ /* hack. Sometimes the keyboard is grabbed, sometime it's not,
+ so, let's force a grab and release, to get rid of a warning. */
+ grabKeyboard();
ungrabKeyboard();
}
@@ -763,7 +786,7 @@ void Ruler::setColor(const QColor& color)
Button::Button(QObject* parent): QObject(parent), QGraphicsRectItem()
{
- icon = new QGraphicsPixmapItem(this);
+ icon = new QGraphicsPixmapItem(this);
text = new QGraphicsSimpleTextItem(this);
icon->setPos(0,0);
text->setPos(0,0);
@@ -800,3 +823,263 @@ void Button::mousePressEvent(QGraphicsSceneMouseEvent* event)
event->ignore();
emit clicked();
}
+
+DivePlannerWidget::DivePlannerWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f), ui(new Ui::DivePlanner())
+{
+ ui->setupUi(this);
+ ui->tablePoints->setModel(DivePlannerPointsModel::instance());
+ ui->tablePoints->setItemDelegateForColumn(DivePlannerPointsModel::GAS, new AirTypesDelegate(this));
+
+ connect(ui->tablePoints, SIGNAL(clicked(QModelIndex)), plannerModel, SLOT(removePoint(const QModelIndex)));
+ connect(ui->startTime, SIGNAL(timeChanged(QTime)), this, SLOT(startTimeChanged(QTime)));
+ connect(ui->ATMPressure, SIGNAL(textChanged(QString)), this, SLOT(atmPressureChanged(QString)));
+ connect(ui->bottomSAC, SIGNAL(textChanged(QString)), this, SLOT(bottomSacChanged(QString)));
+ connect(ui->decoStopSAC, SIGNAL(textChanged(QString)), this, SLOT(decoSacChanged(QString)));
+ connect(ui->highGF, SIGNAL(textChanged(QString)), this, SLOT(gfhighChanged(QString)));
+ connect(ui->lowGF, SIGNAL(textChanged(QString)), this, SLOT(gflowChanged(QString)));
+ connect(ui->highGF, SIGNAL(textChanged(QString)), this, SLOT(gfhighChanged(QString)));
+ connect(ui->lastStop, SIGNAL(toggled(bool)), this, SLOT(lastStopChanged(bool)));
+
+ QFile cssFile(":table-css");
+ cssFile.open(QIODevice::ReadOnly);
+ QTextStream reader(&cssFile);
+ QString css = reader.readAll();
+
+ ui->tablePoints->setStyleSheet(css);
+ QFontMetrics metrics(defaultModelFont());
+
+ ui->tablePoints->horizontalHeader()->setResizeMode(DivePlannerPointsModel::REMOVE, QHeaderView::Fixed);
+ ui->tablePoints->verticalHeader()->setDefaultSectionSize( metrics.height() +8 );
+ initialUiSetup();
+}
+
+void DivePlannerWidget::hideEvent(QHideEvent* event)
+{
+ QSettings s;
+ s.beginGroup("DivePlanner");
+ s.beginGroup("PointTables");
+ for (int i = 0; i < CylindersModel::COLUMNS; i++) {
+ s.setValue(QString("colwidth%1").arg(i), ui->tablePoints->columnWidth(i));
+ }
+ s.endGroup();
+ s.sync();
+}
+
+void DivePlannerWidget::initialUiSetup()
+{
+ QSettings s;
+ s.beginGroup("DivePlanner");
+ s.beginGroup("PointTables");
+ for (int i = 0; i < CylindersModel::COLUMNS; i++) {
+ QVariant width = s.value(QString("colwidth%1").arg(i));
+ if (width.isValid())
+ ui->tablePoints->setColumnWidth(i, width.toInt());
+ else
+ ui->tablePoints->resizeColumnToContents(i);
+ }
+ s.endGroup();
+}
+void DivePlannerWidget::startTimeChanged(const QTime& time)
+{
+ plannerModel->setStartTime(time);
+}
+
+void DivePlannerWidget::atmPressureChanged(const QString& pressure)
+{
+ plannerModel->setSurfacePressure(pressure.toInt());
+}
+
+void DivePlannerWidget::bottomSacChanged(const QString& bottomSac)
+{
+ plannerModel->setBottomSac(bottomSac.toInt());
+}
+
+void DivePlannerWidget::decoSacChanged(const QString& decosac)
+{
+ plannerModel->setDecoSac(decosac.toInt());
+}
+
+void DivePlannerWidget::gfhighChanged(const QString& gfhigh)
+{
+ plannerModel->setGFHigh(gfhigh.toShort());
+}
+
+void DivePlannerWidget::gflowChanged(const QString& gflow)
+{
+ plannerModel->setGFLow(gflow.toShort());
+}
+
+void DivePlannerWidget::lastStopChanged(bool checked)
+{
+ plannerModel->setLastStop6m(checked);
+}
+
+int DivePlannerPointsModel::columnCount(const QModelIndex& parent) const
+{
+ return COLUMNS;
+}
+
+QVariant DivePlannerPointsModel::data(const QModelIndex& index, int role) const
+{
+ if(role == Qt::DisplayRole){
+ divedatapoint p = divepoints.at(index.row());
+ switch(index.column()){
+ case CCSETPOINT: return 0;
+ case DEPTH: return p.depth / 1000;
+ case DURATION: return p.time / 60;
+ case GAS: return strForAir(p);
+ }
+ }
+ if (role == Qt::DecorationRole){
+ switch(index.column()){
+ case REMOVE : return QIcon(":trash");
+ }
+ }
+ return QVariant();
+}
+
+bool DivePlannerPointsModel::setData(const QModelIndex& index, const QVariant& value, int role)
+{
+ if(role == Qt::EditRole){
+ divedatapoint& p = divepoints[index.row()];
+ switch(index.column()){
+ case DEPTH: p.depth = value.toInt() * 1000; break;
+ case DURATION: p.time = value.toInt() * 60; break;
+ case CCSETPOINT: /* what do I do here? */
+ case GAS: {
+ int o2 = 0;
+ int he = 0;
+ QByteArray gasv = value.toByteArray();
+ if (validate_gas(gasv.data(), &o2, &he)) {
+ p.o2 = o2;
+ p.he = he;
+ }break;
+ }
+ }
+ editStop(index.row(), p);
+ }
+ return QAbstractItemModel::setData(index, value, role);
+}
+
+QVariant DivePlannerPointsModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role == Qt::DisplayRole && orientation == Qt::Horizontal){
+ switch(section){
+ case DEPTH: return tr("Final Depth");
+ case DURATION: return tr("Duration");
+ case GAS: return tr("Used Gas");
+ case CCSETPOINT: return tr("CC Set Point");
+ }
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags DivePlannerPointsModel::flags(const QModelIndex& index) const
+{
+ return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
+}
+
+int DivePlannerPointsModel::rowCount(const QModelIndex& parent) const
+{
+ return divepoints.count();
+}
+
+DivePlannerPointsModel::DivePlannerPointsModel(QObject* parent): QAbstractTableModel(parent)
+{
+}
+
+DivePlannerPointsModel* DivePlannerPointsModel::instance()
+{
+ static DivePlannerPointsModel* self = new DivePlannerPointsModel();
+ return self;
+}
+
+void DivePlannerPointsModel::createPlan()
+{
+
+}
+
+void DivePlannerPointsModel::setBottomSac(int sac)
+{
+ diveplan.bottomsac = sac;
+}
+
+void DivePlannerPointsModel::setDecoSac(int sac)
+{
+ diveplan.decosac = sac;
+}
+
+void DivePlannerPointsModel::setGFHigh(short int gfhigh)
+{
+ diveplan.gfhigh = gfhigh;
+}
+
+void DivePlannerPointsModel::setGFLow(short int ghflow)
+{
+ diveplan.gflow = ghflow;
+}
+
+void DivePlannerPointsModel::setSurfacePressure(int pressure)
+{
+ diveplan.surface_pressure = pressure;
+}
+
+void DivePlannerPointsModel::setLastStop6m(bool value)
+{
+}
+
+void DivePlannerPointsModel::setStartTime(const QTime& t)
+{
+ diveplan.when = t.msec();
+}
+
+bool divePointsLessThan(const divedatapoint& p1, const divedatapoint& p2){
+ return p1.time <= p2.time;
+}
+int DivePlannerPointsModel::addStop(int meters, int minutes, const QString& gas, int ccpoint)
+{
+ int row = divepoints.count();
+ // check if there's already a new stop before this one:
+ for(int i = 0; i < divepoints.count(); i++){
+ const divedatapoint& dp = divepoints.at(i);
+ if (dp.time > minutes ){
+ row = i;
+ break;
+ }
+ }
+
+ // add the new stop
+ beginInsertRows(QModelIndex(), row, row);
+ divedatapoint point;
+ point.depth = meters;
+ point.time = minutes;
+ point.o2 = 209;
+ point.he = 0;
+ point.po2 = 0;
+ divepoints.append( point );
+ std::sort(divepoints.begin(), divepoints.end(), divePointsLessThan);
+ endInsertRows();
+ return row;
+}
+
+void DivePlannerPointsModel::editStop(int row, divedatapoint newData)
+{
+ divepoints[row] = newData;
+ std::sort(divepoints.begin(), divepoints.end(), divePointsLessThan);
+ emit dataChanged(createIndex(0, 0), createIndex(rowCount()-1, COLUMNS-1));
+}
+
+divedatapoint DivePlannerPointsModel::at(int row)
+{
+ return divepoints.at(row);
+}
+
+void DivePlannerPointsModel::removePoint(const QModelIndex& index)
+{
+ if (index.column() != REMOVE)
+ return;
+
+ beginRemoveRows(QModelIndex(), index.row(), index.row());
+ divepoints.remove(index.row());
+ endRemoveRows();
+}