diff --git a/planner.c b/planner.c
index 9df5c89..95ac025 100644
--- a/planner.c
+++ b/planner.c
@@ -13,7 +13,7 @@
 #include "planner.h"
 #include "gettext.h"
 
-unsigned int decostoplevels[] = { 0, 3000, 6000, 9000, 12000, 15000, 18000, 21000, 24000, 27000,
+int decostoplevels[] = { 0, 3000, 6000, 9000, 12000, 15000, 18000, 21000, 24000, 27000,
 				  30000, 33000, 36000, 39000, 42000, 45000, 48000, 51000, 54000, 57000,
 				  60000, 63000, 66000, 69000, 72000, 75000, 78000, 81000, 84000, 87000,
 				  90000, 100000, 110000, 120000, 130000, 140000, 150000, 160000, 170000,
@@ -99,6 +99,18 @@ void get_gas_string(int o2, int he, char *text, int len)
 		snprintf(text, len, "(%d/%d)", (o2 + 5) / 10, (he + 5) / 10);
 }
 
+double interpolate_transition(struct dive *dive, int t0, int t1, int d0, int d1, const struct gasmix *gasmix, int ppo2)
+{
+	int j;
+	double tissue_tolerance;
+
+	for (j = t0; j < t1; j++) {
+		int depth = interpolate(d0, d1, j - t0, t1 - t0);
+		tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0, gasmix, 1, ppo2, dive);
+	}
+	return tissue_tolerance;
+}
+
 /* returns the tissue tolerance at the end of this (partial) dive */
 double tissue_at_end(struct dive *dive, char **cached_datap)
 {
@@ -133,43 +145,13 @@ double tissue_at_end(struct dive *dive, char **cached_datap)
 		}
 		if (i > 0)
 			lastdepth = psample->depth.mm;
-		for (j = t0; j < t1; j++) {
-			int depth = interpolate(lastdepth, sample->depth.mm, j - t0, t1 - t0);
-			tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0,
-						       &dive->cylinder[gasidx].gasmix, 1, sample->po2, dive);
-		}
+		tissue_tolerance = interpolate_transition(dive, t0, t1, lastdepth, sample->depth.mm, &dive->cylinder[gasidx].gasmix, sample->po2);
 		psample = sample;
 		t0 = t1;
 	}
 	return tissue_tolerance;
 }
 
-/* how many seconds until we can ascend to the next stop? */
-static int time_at_last_depth(struct dive *dive, int o2, int he, unsigned int next_stop, char **cached_data_p)
-{
-	int depth, gasidx;
-	double surface_pressure, tissue_tolerance;
-	int wait = 0;
-	struct sample *sample;
-
-	if (!dive)
-		return 0;
-	surface_pressure = dive->dc.surface_pressure.mbar / 1000.0;
-	tissue_tolerance = tissue_at_end(dive, cached_data_p);
-	sample = &dive->dc.sample[dive->dc.samples - 1];
-	depth = sample->depth.mm;
-	gasidx = get_gasidx(dive, o2, he);
-	if (gasidx == -1) {
-		fprintf(stderr, "cannot find gas (%d/%d), using first gas\n", o2, he);
-		gasidx = 0;
-	}
-	while (deco_allowed_depth(tissue_tolerance, surface_pressure, dive, 1) > next_stop) {
-		wait++;
-		tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0,
-					       &dive->cylinder[gasidx].gasmix, 1, sample->po2, dive);
-	}
-	return wait;
-}
 
 /* if a default cylinder is set, use that */
 void fill_default_cylinder(cylinder_t *cyl)
@@ -196,6 +178,7 @@ void fill_default_cylinder(cylinder_t *cyl)
 		if (ti->psi)
 			cyl->type.size.mliter = cuft_to_l(ti->cuft) * 1000 / bar_to_atm(psi_to_bar(ti->psi));
 	}
+	cyl->depth.mm = 1600 * 1000 / O2_IN_AIR * 10 - 10000; // MOD of air
 }
 
 static int add_gas(struct dive *dive, int o2, int he)
@@ -389,18 +372,18 @@ struct divedatapoint *plan_add_segment(struct diveplan *diveplan, int duration,
 }
 
 struct gaschanges {
-	unsigned int depth;
+	int depth;
 	int gasidx;
 };
 
-static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive *dive, int *gaschangenr)
+static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive *dive, int *gaschangenr, int depth)
 {
 	int nr = 0;
 	struct gaschanges *gaschanges = NULL;
 	struct divedatapoint *dp = diveplan->dp;
 
 	while (dp) {
-		if (dp->time == 0) {
+		if (dp->time == 0 && dp->depth <= depth) {
 			int i = 0, j = 0;
 			nr++;
 			gaschanges = realloc(gaschanges, nr * sizeof(struct gaschanges));
@@ -436,15 +419,15 @@ static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive
 }
 
 /* sort all the stops into one ordered list */
-static unsigned int *sort_stops(unsigned int *dstops, int dnr, struct gaschanges *gstops, int gnr)
+static unsigned int *sort_stops(int *dstops, int dnr, struct gaschanges *gstops, int gnr)
 {
 	int i, gi, di;
 	int total = dnr + gnr;
-	unsigned int *stoplevels = malloc(total * sizeof(unsigned int));
+	int *stoplevels = malloc(total * sizeof(int));
 
 	/* no gaschanges */
 	if (gnr == 0) {
-		memcpy(stoplevels, dstops, dnr * sizeof(unsigned int));
+		memcpy(stoplevels, dstops, dnr * sizeof(int));
 		return stoplevels;
 	}
 	i = total - 1;
@@ -586,17 +569,29 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive)
 }
 #endif
 
+int ascend_velocity(int depth)
+{
+	/* We need to make this configurable */
+	return 10000/60;
+}
+
 void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, bool add_deco)
 {
 	struct dive *dive;
 	struct sample *sample;
 	int wait_time, o2, he, po2;
 	int transitiontime, gi;
-	unsigned int stopidx, depth, ceiling;
+	int current_cylinder;
+	unsigned int stopidx;
+	int depth, ceiling;
 	double tissue_tolerance;
 	struct gaschanges *gaschanges = NULL;
 	int gaschangenr;
-	unsigned int *stoplevels = NULL;
+	int *stoplevels = NULL;
+	char *trial_cache = NULL;
+	bool stopping = false;
+	bool clear_to_ascend;
+	int clock, previous_point_time;
 
 	set_gf(diveplan->gflow, diveplan->gfhigh, default_prefs.gf_low_at_maxdepth);
 	if (!diveplan->surface_pressure)
@@ -614,6 +609,10 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
 	he = dive->cylinder[0].gasmix.he.permille;
 	get_gas_from_events(&dive->dc, sample->time.seconds, &o2, &he);
 	po2 = dive->dc.sample[dive->dc.samples - 1].po2;
+	if ((current_cylinder = get_gasidx(dive, o2, he)) == -1) {
+		report_error(translate("gettextFromC", "Can't find gas %d/%d"), (o2 + 5) / 10, (he + 5) / 10);
+		current_cylinder = 0;
+	}
 	depth = dive->dc.sample[dive->dc.samples - 1].depth.mm;
 
 	/* if all we wanted was the dive just get us back to the surface */
@@ -629,90 +628,102 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
 	}
 
 	tissue_tolerance = tissue_at_end(dive, cached_datap);
-	ceiling = deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, dive, 1);
+
 #if DEBUG_PLAN & 4
 	printf("gas %d/%d\n", o2, he);
 	printf("depth %5.2lfm ceiling %5.2lfm\n", depth / 1000.0, ceiling / 1000.0);
 #endif
-	if (depth < ceiling) /* that's not good... */
-		depth = ceiling;
-	if (depth == 0 && ceiling == 0) /* we are done here */
-		goto done;
+
+	gaschanges = analyze_gaslist(diveplan, dive, &gaschangenr, depth);
 	for (stopidx = 0; stopidx < sizeof(decostoplevels) / sizeof(int); stopidx++)
-		if (decostoplevels[stopidx] >= ceiling)
+		if (decostoplevels[stopidx] >= depth)
 			break;
 	if (stopidx > 0)
 		stopidx--;
-
-	/* so now we know the first decostop level above us
-	 * NOTE, this could be the surface or a long list of potential stops
-	 * we do NOT start only at the ceiling, as the ceiling may come down
-	 * further during the ascent.
-	 * Next we need to figure out if there are better gases available
-	 * and at which depths we are supposed to switch to them */
-	gaschanges = analyze_gaslist(diveplan, dive, &gaschangenr);
 	stoplevels = sort_stops(decostoplevels, stopidx + 1, gaschanges, gaschangenr);
+	stopidx += gaschangenr;
 
+	clock = previous_point_time = dive->dc.sample[dive->dc.samples - 1].time.seconds;
 	gi = gaschangenr - 1;
-	stopidx += gaschangenr;
-	if (depth > stoplevels[stopidx]) {
-		/* right now all the transitions are at 30ft/min - this needs to be configurable */
-		transitiontime = (depth - stoplevels[stopidx]) / 150;
-#if DEBUG_PLAN & 2
-		printf("transitiontime %d:%02d to depth %5.2lfm\n", FRACTION(transitiontime, 60), stoplevels[stopidx] / 1000.0);
-#endif
-		plan_add_segment(diveplan, transitiontime, stoplevels[stopidx], o2, he, po2, false);
-		/* re-create the dive */
-		delete_single_dive(dive_table.nr - 1);
-		*divep = dive = create_dive_from_plan(diveplan);
-		if (!dive)
-			goto error_exit;
-		record_dive(dive);
-	}
-	while (stopidx > 0) { /* this indicates that we aren't surfacing directly */
-		/* if we are in a double-step, eg, when 3m/10ft stop is disabled,
-		 * just skip the first stop at that depth */
-		if (stoplevels[stopidx] == stoplevels[stopidx - 1]) {
-			stopidx--;
-			continue;
-		}
+
+	while (1) {
+		/* We will break out when we hit the surface */
+		do {
+			/* Ascend in one second steps to next stop depth */
+			int deltad = ascend_velocity(depth);
+			if (depth - deltad < stoplevels[stopidx])
+				deltad = depth - stoplevels[stopidx];
+
+			tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0, &dive->cylinder[current_cylinder].gasmix, 1, po2, dive);
+			++clock;
+			depth -= deltad;
+		} while (depth > stoplevels[stopidx]);
+
+		if (depth <= 0)
+			break;	/* We are at the surface */
+
+
 		if (gi >= 0 && stoplevels[stopidx] == gaschanges[gi].depth) {
-			o2 = dive->cylinder[gaschanges[gi].gasidx].gasmix.o2.permille;
-			he = dive->cylinder[gaschanges[gi].gasidx].gasmix.he.permille;
+			plan_add_segment(diveplan, clock - previous_point_time, depth, o2, he, po2, false);
+			previous_point_time = clock;
+			stopping = true;
+
+			current_cylinder = gaschanges[gi].gasidx;
+			o2 = dive->cylinder[current_cylinder].gasmix.o2.permille;
+			he = dive->cylinder[current_cylinder].gasmix.he.permille;
 #if DEBUG_PLAN & 16
 			printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx,
-			       (o2 + 5) / 10, (he + 5) / 10, gaschanges[gi].depth / 1000.0);
+				       (o2 + 5) / 10, (he + 5) / 10, gaschanges[gi].depth / 1000.0);
 #endif
 			gi--;
 		}
-		wait_time = time_at_last_depth(dive, o2, he, stoplevels[stopidx - 1], cached_datap);
-		/* typically deco plans are done in one minute increments; we may want to
-		 * make this configurable at some point */
-		wait_time = ((wait_time + 59) / 60) * 60;
-#if DEBUG_PLAN & 2
-		tissue_tolerance = tissue_at_end(dive, cached_datap);
-		ceiling = deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, dive, 1);
-		printf("waittime %d:%02d at depth %5.2lfm; ceiling %5.2lfm\n", FRACTION(wait_time, 60),
-		       stoplevels[stopidx] / 1000.0, ceiling / 1000.0);
-#endif
-		if (wait_time)
-			plan_add_segment(diveplan, wait_time, stoplevels[stopidx], o2, he, po2, false);
-		/* right now all the transitions are at 30ft/min - this needs to be configurable */
-		transitiontime = (stoplevels[stopidx] - stoplevels[stopidx - 1]) / 150;
-#if DEBUG_PLAN & 2
-		printf("transitiontime %d:%02d to depth %5.2lfm\n", FRACTION(transitiontime, 60), stoplevels[stopidx - 1] / 1000.0);
-#endif
-		plan_add_segment(diveplan, transitiontime, stoplevels[stopidx - 1], o2, he, po2, false);
-		/* re-create the dive */
-		delete_single_dive(dive_table.nr - 1);
-		*divep = dive = create_dive_from_plan(diveplan);
-		if (!dive)
-			goto error_exit;
-		record_dive(dive);
-		stopidx--;
-	}
 
-done:
+		/* trial ascend */
+		--stopidx;
+		int trial_depth = depth;
+		cache_deco_state(tissue_tolerance, &trial_cache);
+		while(1) {
+			/* Try to ascend to next stop, go back and wait if we hit the ceiling on the way */
+			clear_to_ascend = true;
+			while (trial_depth > stoplevels[stopidx]) {
+				int deltad = ascend_velocity(trial_depth);
+				tissue_tolerance = add_segment(depth_to_mbar(trial_depth, dive) / 1000.0, &dive->cylinder[current_cylinder].gasmix, 1, po2, dive);
+				if (deco_allowed_depth(tissue_tolerance, diveplan->surface_pressure / 1000.0, dive, 1) > trial_depth - deltad){
+					/* We should have stopped */
+					clear_to_ascend = false;
+					break;
+				}
+				trial_depth -= deltad;
+			}
+			restore_deco_state(trial_cache);
+			/* The next stop is clear */
+			if(clear_to_ascend)
+				break;
+
+			/* Wait a minute */
+			if (!stopping) {
+				plan_add_segment(diveplan, clock - previous_point_time, depth, o2, he, po2, false);
+				previous_point_time = clock;
+				stopping = true;
+			}
+			tissue_tolerance = add_segment(depth_to_mbar(depth, dive) / 1000.0, &dive->cylinder[current_cylinder].gasmix, 60, po2, dive);
+			cache_deco_state(tissue_tolerance, &trial_cache);
+			clock += 60;
+			trial_depth = depth;
+		}
+		if (stopping) {
+			plan_add_segment(diveplan, clock - previous_point_time, depth, o2, he, po2, false);
+			previous_point_time = clock;
+			stopping = false;
+		}
+
+	}
+	plan_add_segment(diveplan, clock - previous_point_time, 0, o2, he, po2, false);
+	delete_single_dive(dive_table.nr - 1);
+	*divep = dive = create_dive_from_plan(diveplan);
+	if (!dive)
+		goto error_exit;
+	record_dive(dive);
 
 #if DO_WE_WANT_THIS_IN_QT
 	add_plan_to_notes(diveplan, dive);
diff --git a/qt-ui/diveplanner.cpp b/qt-ui/diveplanner.cpp
index 5c89732..cc4565e 100644
--- a/qt-ui/diveplanner.cpp
+++ b/qt-ui/diveplanner.cpp
@@ -41,135 +41,6 @@ QString dpGasToStr(const divedatapoint &p)
 	return gasToStr(p.o2, p.he);
 }
 
-static DivePlannerDisplay *plannerDisplay = DivePlannerDisplay::instance();
-
-DivePlannerDisplay::DivePlannerDisplay(QObject *parent) : QAbstractTableModel(parent)
-{
-}
-
-DivePlannerDisplay *DivePlannerDisplay::instance()
-{
-	static QScopedPointer<DivePlannerDisplay> self(new DivePlannerDisplay());
-	return self.data();
-}
-
-int DivePlannerDisplay::size()
-{
-	return computedPoints.size();
-}
-
-int DivePlannerDisplay::columnCount(const QModelIndex &parent) const
-{
-	return COLUMNS;
-}
-
-QVariant DivePlannerDisplay::data(const QModelIndex &index, int role) const
-{
-	if (role == Qt::DisplayRole) {
-		computedPoint p = computedPoints.at(index.row());
-		switch (index.column()) {
-		case COMPUTED_DEPTH:
-			return rint(get_depth_units(p.computedDepth, NULL, NULL));
-		case COMPUTED_DURATION:
-			return p.computedTime / 60;
-		}
-	} else if (role == Qt::DecorationRole) {
-		switch (index.column()) {
-		case REMOVE:
-			return QIcon(":trash");
-		}
-	} else if (role == Qt::FontRole) {
-		return defaultModelFont();
-	}
-	return QVariant();
-}
-
-bool DivePlannerDisplay::setData(const QModelIndex &index, const QVariant &value, int role)
-{
-	if (role == Qt::EditRole) {
-		computedPoint &p = computedPoints[index.row()];
-		switch (index.column()) {
-		case COMPUTED_DEPTH:
-			p.computedDepth = units_to_depth(value.toInt());
-			break;
-		case COMPUTED_DURATION:
-			p.computedTime = value.toInt() * 60;
-			break;
-		}
-	}
-	return QAbstractItemModel::setData(index, value, role);
-}
-
-QVariant DivePlannerDisplay::headerData(int section, Qt::Orientation orientation, int role) const
-{
-	if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
-		switch (section) {
-		case COMPUTED_DEPTH:
-			return tr("Comp. Depth");
-		case COMPUTED_DURATION:
-			return tr("Comp. Duration");
-		}
-	} else if (role == Qt::FontRole) {
-		return defaultModelFont();
-	}
-	return QVariant();
-}
-
-Qt::ItemFlags DivePlannerDisplay::flags(const QModelIndex &index) const
-{
-	return QAbstractItemModel::flags(index);
-}
-
-int DivePlannerDisplay::rowCount(const QModelIndex &parent) const
-{
-	return computedPoints.size();
-}
-
-struct computedPoint DivePlannerDisplay::at(int row)
-{
-	return computedPoints.at(row);
-}
-
-void DivePlannerDisplay::clear()
-{
-	if (rowCount() > 0) {
-		beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
-		computedPoints.clear();
-		endRemoveRows();
-	}
-}
-
-void DivePlannerDisplay::removeStops()
-{
-	if (rowCount() > 0) {
-		beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
-		endRemoveRows();
-	}
-}
-
-void DivePlannerDisplay::addStops()
-{
-	int rows = computedPoints.size();
-	if (rows > 0) {
-		beginInsertRows(QModelIndex(), 0, rows - 1);
-		endInsertRows();
-	}
-}
-
-void DivePlannerDisplay::insertPoint(const struct computedPoint &p)
-{
-	computedPoints.append(p);
-}
-
-void DivePlannerDisplay::remove(const QModelIndex &index)
-{
-	if (index.column() != REMOVE)
-		return;
-
-	beginRemoveRows(QModelIndex(), index.row(), index.row());
-	endRemoveRows();
-}
-
 static DivePlannerPointsModel *plannerModel = DivePlannerPointsModel::instance();
 
 DivePlannerGraphics::DivePlannerGraphics(QWidget *parent) : QGraphicsView(parent),
@@ -311,7 +182,8 @@ void DivePlannerGraphics::pointInserted(const QModelIndex &parent, int start, in
 	gasChooseBtn->setZValue(10);
 	gasChooseBtn->setFlag(QGraphicsItem::ItemIgnoresTransformations);
 	gases << gasChooseBtn;
-	drawProfile();
+	if(plannerModel->recalcQ())
+		drawProfile();
 }
 
 void DivePlannerGraphics::keyDownAction()
@@ -585,6 +457,8 @@ QStringList &DivePlannerPointsModel::getGasList()
 
 void DivePlannerGraphics::drawProfile()
 {
+	if(!plannerModel->recalcQ())
+		return;
 	qDeleteAll(lines);
 	lines.clear();
 
@@ -598,7 +472,7 @@ void DivePlannerGraphics::drawProfile()
 		return;
 	}
 	while (dp->next) {
-		if (dp->depth > max_depth)
+		if (dp->time && dp->depth > max_depth)
 			max_depth = dp->depth;
 		dp = dp->next;
 	}
@@ -639,7 +513,16 @@ void DivePlannerGraphics::drawProfile()
 	QPolygonF poly;
 	poly.append(QPointF(lastx, lasty));
 
-	plannerDisplay->clear();
+	bool oldRecalc = plannerModel->setRecalc(false);
+	QVector<int> computedPoints;
+	for (int i = 0; i < plannerModel->rowCount(); i++)
+		if (!plannerModel->at(i).entered)
+			computedPoints.push_back(i);
+	plannerModel->removeSelectedPoints(computedPoints);
+
+	int lastdepth = 0;
+	int lasto2 = 0;
+	int lasthe = 0;
 	for (dp = diveplan.dp; dp != NULL; dp = dp->next) {
 		if (dp->time == 0) // magic entry for available tank
 			continue;
@@ -648,21 +531,22 @@ void DivePlannerGraphics::drawProfile()
 		if (!dp->entered) {
 			QGraphicsLineItem *item = new QGraphicsLineItem(lastx, lasty, xpos, ypos);
 			item->setPen(QPen(QBrush(Qt::red), 0));
+
 			scene()->addItem(item);
 			lines << item;
 			if (dp->depth) {
-				qDebug() << "Time: " << dp->time / 60 << " depth: " << dp->depth / 1000;
-				computedPoint p(dp->time, dp->depth);
-				plannerDisplay->insertPoint(p);
+				if (dp->depth == lastdepth || dp->o2 != dp->next->o2 || dp->he != dp->next->he)
+					plannerModel->addStop(dp->depth, dp->time, dp->o2, dp->he, 0, false);
+				lastdepth = dp->depth;
+				lasto2 = dp->o2;
+				lasthe = dp->he;
 			}
 		}
 		lastx = xpos;
 		lasty = ypos;
 		poly.append(QPointF(lastx, lasty));
 	}
-
-	qDebug() << " ";
-	plannerDisplay->addStops();
+	plannerModel->setRecalc(oldRecalc);
 
 	diveBg->setPolygon(poly);
 	QRectF b = poly.boundingRect();
@@ -1069,9 +953,8 @@ DivePlannerWidget::DivePlannerWidget(QWidget *parent, Qt::WindowFlags f) : QWidg
 	ui.setupUi(this);
 	ui.tableWidget->setTitle(tr("Dive Planner Points"));
 	ui.tableWidget->setModel(DivePlannerPointsModel::instance());
+	DivePlannerPointsModel::instance()->setRecalc(true);
 	ui.tableWidget->view()->setItemDelegateForColumn(DivePlannerPointsModel::GAS, new AirTypesDelegate(this));
-	ui.tableWidgetComp->setTitle(tr("Computed Waypoints"));
-	ui.tableWidgetComp->setModel(DivePlannerDisplay::instance());
 	ui.cylinderTableWidget->setTitle(tr("Available Gases"));
 	ui.cylinderTableWidget->setModel(CylindersModel::instance());
 	QTableView *view = ui.cylinderTableWidget->view();
@@ -1090,9 +973,14 @@ DivePlannerWidget::DivePlannerWidget(QWidget *parent, Qt::WindowFlags f) : QWidg
 		GasSelectionModel::instance(), SLOT(repopulate()));
 	connect(CylindersModel::instance(), SIGNAL(rowsRemoved(QModelIndex, int, int)),
 		GasSelectionModel::instance(), SLOT(repopulate()));
+	connect(CylindersModel::instance(), SIGNAL(dataChanged(QModelIndex, int, int)),
+		plannerModel, SLOT(drawProfile()));
+	connect(CylindersModel::instance(), SIGNAL(rowsInserted(QModelIndex, int, int)),
+		plannerModel, SLOT(drawProfile()));
+	connect(CylindersModel::instance(), SIGNAL(rowsRemoved(QModelIndex, int, int)),
+		plannerModel, SLOT(drawProfile()));
 
 	ui.tableWidget->setBtnToolTip(tr("add dive data point"));
-	ui.tableWidgetComp->setBtnToolTip(tr("This does nothing, and should be removed"));
 	connect(ui.startTime, SIGNAL(timeChanged(QTime)), plannerModel, SLOT(setStartTime(QTime)));
 	connect(ui.ATMPressure, SIGNAL(textChanged(QString)), this, SLOT(atmPressureChanged(QString)));
 	connect(ui.bottomSAC, SIGNAL(textChanged(QString)), this, SLOT(bottomSacChanged(QString)));
@@ -1156,6 +1044,18 @@ bool DivePlannerPointsModel::isPlanner()
 	return mode == PLAN;
 }
 
+bool DivePlannerPointsModel::setRecalc(bool rec)
+{
+	bool old = recalc;
+	recalc = rec;
+	return old;
+}
+
+bool DivePlannerPointsModel::recalcQ()
+{
+	return recalc;
+}
+
 int DivePlannerPointsModel::columnCount(const QModelIndex &parent) const
 {
 	return COLUMNS;
@@ -1170,9 +1070,15 @@ QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
 			return (double)p.po2 / 1000;
 		case DEPTH:
 			return rint(get_depth_units(p.depth, NULL, NULL));
-		case DURATION:
+		case RUNTIME:
 			return p.time / 60;
+		case DURATION:
+			if (index.row())
+				return (p.time - divepoints.at(index.row() -1).time) / 60;
+			else
+				return p.time / 60;
 		case GAS:
+
 			return dpGasToStr(p);
 		}
 	} else if (role == Qt::DecorationRole) {
@@ -1181,7 +1087,13 @@ QVariant DivePlannerPointsModel::data(const QModelIndex &index, int role) const
 			return QIcon(":trash");
 		}
 	} else if (role == Qt::FontRole) {
-		return defaultModelFont();
+		if (divepoints.at(index.row()).entered) {
+			return defaultModelFont();
+		} else {
+			QFont font = defaultModelFont();
+			font.setBold(true);
+			return font;
+		}
 	}
 	return QVariant();
 }
@@ -1196,9 +1108,15 @@ bool DivePlannerPointsModel::setData(const QModelIndex &index, const QVariant &v
 		case DEPTH:
 			p.depth = units_to_depth(value.toInt());
 			break;
-		case DURATION:
+		case RUNTIME:
 			p.time = value.toInt() * 60;
 			break;
+		case DURATION:
+			if (index.row())
+				p.time = value.toInt() * 60 + divepoints[index.row() - 1].time;
+			else
+				p.time = value.toInt() * 60;
+			break;
 		case CCSETPOINT: {
 			int po2 = 0;
 			QByteArray gasv = value.toByteArray();
@@ -1224,6 +1142,8 @@ QVariant DivePlannerPointsModel::headerData(int section, Qt::Orientation orienta
 		switch (section) {
 		case DEPTH:
 			return tr("Final Depth");
+		case RUNTIME:
+			return tr("Run time");
 		case DURATION:
 			return tr("Duration");
 		case GAS:
@@ -1239,7 +1159,10 @@ QVariant DivePlannerPointsModel::headerData(int section, Qt::Orientation orienta
 
 Qt::ItemFlags DivePlannerPointsModel::flags(const QModelIndex &index) const
 {
-	return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
+	if(index.column() !=  DURATION)
+		return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
+	else
+		return QAbstractItemModel::flags(index);
 }
 
 int DivePlannerPointsModel::rowCount(const QModelIndex &parent) const
@@ -1317,6 +1240,10 @@ bool DivePlannerPointsModel::addGas(int o2, int he)
 			fill_default_cylinder(cyl);
 			cyl->gasmix.o2.permille = o2;
 			cyl->gasmix.he.permille = he;
+			if(!o2)
+				cyl->depth.mm = 1600 * 1000 / O2_IN_AIR * 10 - 10000;
+			else
+				cyl->depth.mm = 1600 * 1000 / o2 * 10 - 10000;
 			CylindersModel::instance()->setDive(stagingDive);
 			return true;
 		}
@@ -1327,12 +1254,20 @@ bool DivePlannerPointsModel::addGas(int o2, int he)
 	return false;
 }
 
+int DivePlannerPointsModel::lastEnteredPoint()
+{
+	for (int i = divepoints.count()-1; i >= 0; i--)
+		if (divepoints.at(i).entered)
+			return i;
+	return -1;
+}
+
 int DivePlannerPointsModel::addStop(int milimeters, int seconds, int o2, int he, int ccpoint, bool entered)
 {
 	int row = divepoints.count();
 	if (seconds == 0 && milimeters == 0 && row != 0) {
 		/* this is only possible if the user clicked on the 'plus' sign on the DivePoints Table */
-		struct divedatapoint &t = divepoints.last();
+		const divedatapoint t = divepoints.at(lastEnteredPoint());
 		milimeters = t.depth;
 		seconds = t.time + 600; // 10 minutes.
 		o2 = t.o2;
@@ -1386,6 +1321,15 @@ int DivePlannerPointsModel::addStop(int milimeters, int seconds, int o2, int he,
 			}
 		}
 	}
+	bool oldRecalc = setRecalc(false);
+	if (oldRecalc){
+		QVector<int> computedPoints;
+		for (int i = 0; i < plannerModel->rowCount(); i++)
+			if (!plannerModel->at(i).entered)
+				computedPoints.push_back(i);
+		plannerModel->removeSelectedPoints(computedPoints);
+	}
+	setRecalc(oldRecalc);
 	// add the new stop
 	beginInsertRows(QModelIndex(), row, row);
 	divedatapoint point;
@@ -1478,6 +1422,8 @@ bool DivePlannerPointsModel::tankInUse(int o2, int he)
 		divedatapoint &p = divepoints[j];
 		if (p.time == 0) // special entries that hold the available gases
 			continue;
+		if (!p.entered) // removing deco gases is ok
+			continue;
 		if ((p.o2 == o2 && p.he == he) ||
 		    (is_air(p.o2, p.he) && is_air(o2, he)))
 			return true;
@@ -1552,8 +1498,8 @@ void DivePlannerPointsModel::createTemporaryPlan()
 		divedatapoint p = at(i);
 		int deltaT = lastIndex != -1 ? p.time - at(lastIndex).time : p.time;
 		lastIndex = i;
-		p.entered = true;
-		plan_add_segment(&diveplan, deltaT, p.depth, p.o2, p.he, p.po2, true);
+		if (p.entered)
+			plan_add_segment(&diveplan, deltaT, p.depth, p.o2, p.he, p.po2, true);
 	}
 	char *cache = NULL;
 	tempDive = NULL;
@@ -1626,10 +1572,14 @@ void DivePlannerPointsModel::createPlan()
 		// FIXME: The epic assumption that all the cylinders after the first is deco
 		int sac = i ? diveplan.decosac : diveplan.bottomsac;
 		cyl->start.mbar = cyl->type.workingpressure.mbar;
-		int consumption = ((depth_to_mbar(mean[i], tempDive) * duration[i] / 60) * sac) / (cyl->type.size.mliter / 1000);
-		cyl->end.mbar = cyl->start.mbar - consumption;
+		if(cyl->type.size.mliter) {
+			int consumption = ((depth_to_mbar(mean[i], tempDive) * duration[i] / 60) * sac) / (cyl->type.size.mliter / 1000);
+			cyl->end.mbar = cyl->start.mbar - consumption;
+		} else {
+			/* Cylider without a proper size are easily emptied */
+			cyl->end.mbar = 0;
+		}
 	}
-
 	mark_divelist_changed(true);
 
 	// Remove and clean the diveplan, so we don't delete
diff --git a/qt-ui/diveplanner.h b/qt-ui/diveplanner.h
index 4d3f0cb..8352d6a 100644
--- a/qt-ui/diveplanner.h
+++ b/qt-ui/diveplanner.h
@@ -12,48 +12,6 @@
 class QListView;
 class QModelIndex;
 
-struct computedPoint {
-	int computedTime;
-	unsigned int computedDepth;
-	computedPoint(int computedTime_, unsigned int computedDepth_) {
-		computedTime = computedTime_;
-		computedDepth = computedDepth_;
-	};
-	computedPoint() {};
-};
-
-class DivePlannerDisplay : public QAbstractTableModel {
-	Q_OBJECT
-private:
-	explicit DivePlannerDisplay(QObject *parent = 0);
-	QVector<computedPoint> computedPoints;
-
-public:
-	static DivePlannerDisplay *instance();
-	enum Sections {
-		REMOVE,
-		COMPUTED_DEPTH,
-		COMPUTED_DURATION,
-		COLUMNS
-	};
-	virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
-	virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
-	virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
-	virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
-	virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
-	virtual Qt::ItemFlags flags(const QModelIndex &index) const;
-	void clear();
-	computedPoint at(int row);
-	int size();
-	void removeStops();
-	void addStops();
-	void insertPoint(const struct computedPoint &p);
-
-public
-slots:
-	void remove(const QModelIndex &index);
-};
-
 class DivePlannerPointsModel : public QAbstractTableModel {
 	Q_OBJECT
 public:
@@ -62,6 +20,7 @@ public:
 		REMOVE,
 		DEPTH,
 		DURATION,
+		RUNTIME,
 		GAS,
 		CCSETPOINT,
 		COLUMNS
@@ -83,6 +42,8 @@ public:
 	void createSimpleDive();
 	void clear();
 	Mode currentMode() const;
+	bool setRecalc(bool recalc);
+	bool recalcQ();
 	void tanksUpdated();
 	void rememberTanks();
 	bool tankInUse(int o2, int he);
@@ -96,6 +57,8 @@ public:
 	struct diveplan getDiveplan();
 	QStringList &getGasList();
 	QVector<QPair<int, int> > collectGases(dive *d);
+	int lastEnteredPoint();
+	static bool addingDeco;
 
 public
 slots:
@@ -115,6 +78,7 @@ slots:
 	void deleteTemporaryPlan();
 	void loadFromDive(dive *d);
 	void restoreBackupDive();
+
 signals:
 	void planCreated();
 	void planCanceled();
@@ -124,6 +88,7 @@ private:
 	bool addGas(int o2, int he);
 	struct diveplan diveplan;
 	Mode mode;
+	bool recalc;
 	QVector<divedatapoint> divepoints;
 	struct dive *tempDive;
 	struct dive backupDive;
diff --git a/qt-ui/diveplanner.ui b/qt-ui/diveplanner.ui
index 986f1b9..558be06 100644
--- a/qt-ui/diveplanner.ui
+++ b/qt-ui/diveplanner.ui
@@ -142,7 +142,7 @@
          </property>
         </widget>
        </item>
-       <item row="8" column="0" colspan="1">
+       <item row="8" column="0" colspan="2">
         <widget class="TableView" name="tableWidget" native="true">
          <property name="sizePolicy">
           <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
@@ -158,22 +158,6 @@
          </property>
         </widget>
        </item>
-       <item row="8" column="1" colspan="1">
-	<widget class="TableView" name="tableWidgetComp" native="true">
-	 <property name="sizePolicy">
-	  <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
-	   <horstretch>0</horstretch>
-	   <verstretch>0</verstretch>
-	  </sizepolicy>
-	 </property>
-	 <property name="minimumSize">
-	  <size>
-	   <width>0</width>
-	   <height>50</height>
-	  </size>
-	 </property>
-	</widget>
-       </item>
        <item row="9" column="0" colspan="2">
         <widget class="QDialogButtonBox" name="buttonBox">
          <property name="standardButtons">
diff --git a/qt-ui/models.cpp b/qt-ui/models.cpp
index 5b011d7..6d64da4 100644
--- a/qt-ui/models.cpp
+++ b/qt-ui/models.cpp
@@ -253,6 +253,7 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
 	case O2:
 		if (CHANGED()) {
 			cyl->gasmix.o2 = string_to_fraction(vString.toUtf8().data());
+			cyl->depth.mm = 1600 * 1000 / cyl->gasmix.o2.permille * 10 - 10000;
 			changed = true;
 		}
 		break;
