mirror of
				https://github.com/subsurface/subsurface.git
				synced 2025-02-19 22:16:15 +00:00 
			
		
		
		
	Merge branch 'addDiveGasFix'
This commit is contained in:
		
						commit
						487efb1ee9
					
				
					 8 changed files with 113 additions and 68 deletions
				
			
		
							
								
								
									
										14
									
								
								dive.c
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								dive.c
									
										
									
									
									
								
							|  | @ -195,6 +195,20 @@ struct dive *alloc_dive(void) | |||
| 	return dive; | ||||
| } | ||||
| 
 | ||||
| /* only copies events from the first dive computer */ | ||||
| void copy_events(struct dive *s, struct dive *d) | ||||
| { | ||||
| 	struct event *ev; | ||||
| 	if (!s || !d) | ||||
| 		return; | ||||
| 	ev = s->dc.events; | ||||
| 	d->dc.events = NULL; | ||||
| 	while (ev != NULL) { | ||||
| 		add_event(&d->dc, ev->time.seconds, ev->type, ev->flags, ev->value, ev->name); | ||||
| 		ev = ev->next; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void copy_cylinders(struct dive *s, struct dive *d) | ||||
| { | ||||
| 	int i; | ||||
|  |  | |||
							
								
								
									
										1
									
								
								dive.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								dive.h
									
										
									
									
									
								
							|  | @ -653,6 +653,7 @@ extern unsigned int dc_airtemp(struct divecomputer *dc); | |||
| extern struct dive *merge_dives(struct dive *a, struct dive *b, int offset, bool prefer_downloaded); | ||||
| extern struct dive *try_to_merge(struct dive *a, struct dive *b, bool prefer_downloaded); | ||||
| extern void renumber_dives(int nr); | ||||
| extern void copy_events(struct dive *s, struct dive *d); | ||||
| extern void copy_cylinders(struct dive *s, struct dive *d); | ||||
| extern void copy_samples(struct dive *s, struct dive *d); | ||||
| 
 | ||||
|  |  | |||
|  | @ -233,6 +233,7 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error | |||
| 		int time = dp->time; | ||||
| 		int depth = dp->depth; | ||||
| 
 | ||||
| #if 0 // the new planner doesn't use that any more
 | ||||
| 		if (time == 0) { | ||||
| 			/* special entries that just inform the algorithm about
 | ||||
| 			 * additional gases that are available */ | ||||
|  | @ -241,6 +242,7 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error | |||
| 			dp = dp->next; | ||||
| 			continue; | ||||
| 		} | ||||
| #endif | ||||
| 		if (!o2 && !he) { | ||||
| 			o2 = oldo2; | ||||
| 			he = oldhe; | ||||
|  | @ -256,14 +258,14 @@ struct dive *create_dive_from_plan(struct diveplan *diveplan, const char **error | |||
| 		/* Create new gas, and gas change event if necessary;
 | ||||
| 		 * Sadly, we inherited our gaschange event from libdivecomputer which only | ||||
| 		 * support percentage values, so round the entries */ | ||||
| 		if (o2 != oldo2 || he != oldhe) { | ||||
| 		if (time == 0 || o2 != oldo2 || he != oldhe) { | ||||
| 			int plano2 = (o2 + 5) / 10 * 10; | ||||
| 			int planhe = (he + 5) / 10 * 10; | ||||
| 			int value; | ||||
| 			if (add_gas(dive, plano2, planhe) < 0) | ||||
| 				goto gas_error_exit; | ||||
| 			value = (plano2 / 10) | ((planhe / 10) << 16); | ||||
| 			add_event(dc, lasttime, 25, 0, value, "gaschange"); // SAMPLE_EVENT_GASCHANGE2
 | ||||
| 			add_event(dc, time, 25, 0, value, "gaschange"); // SAMPLE_EVENT_GASCHANGE2
 | ||||
| 			oldo2 = o2; oldhe = he; | ||||
| 		} | ||||
| 		/* Create sample */ | ||||
|  | @ -614,7 +616,8 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b | |||
| 	for (stopidx = 0; stopidx < sizeof(decostoplevels) / sizeof(int); stopidx++) | ||||
| 		if (decostoplevels[stopidx] >= depth) | ||||
| 			break; | ||||
| 	stopidx--; | ||||
| 	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 | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ extern int validate_po2(const char *text, int *mbar_po2); | |||
| extern timestamp_t current_time_notz(void); | ||||
| extern void show_planned_dive(char **error_string_p); | ||||
| extern void set_last_stop(bool last_stop_6m); | ||||
| extern void get_gas_from_events(struct divecomputer *dc, int time, int *o2, int *he); | ||||
| 
 | ||||
| extern struct diveplan diveplan; | ||||
| extern struct dive *planned_dive; | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ QStringListModel *airTypes() { | |||
| } | ||||
| 
 | ||||
| QString strForAir(const divedatapoint& p) { | ||||
| 	return p.o2 == 209 ? QObject::tr("AIR") | ||||
| 	return is_air(p.o2, p.he) ? QObject::tr("AIR") | ||||
| 		: p.o2 == 320 ? QObject::tr("EAN32") | ||||
| 		: p.o2 == 360 ? QObject::tr("EAN36") | ||||
| 		: QObject::tr("Choose Gas"); | ||||
|  | @ -412,17 +412,16 @@ void DivePlannerGraphics::mouseDoubleClickEvent(QMouseEvent* event) | |||
| 
 | ||||
| 	int minutes = rint(timeLine->valueAt(mappedPos)); | ||||
| 	int milimeters = rint(depthLine->valueAt(mappedPos) / M_OR_FT(1,1)) * M_OR_FT(1,1); | ||||
| 	plannerModel->addStop(milimeters, minutes * 60, tr("Air"), 0); | ||||
| 	plannerModel->addStop(milimeters, minutes * 60, O2_IN_AIR, 0, 0); | ||||
| } | ||||
| 
 | ||||
| void DivePlannerPointsModel::createSimpleDive() | ||||
| { | ||||
| 	plannerModel->addStop(M_OR_FT(15,45), 1 * 60, tr("Air"), 0); | ||||
| 	plannerModel->addStop(M_OR_FT(15,45), 40 * 60, tr("Air"), 0); | ||||
| //	plannerModel->addStop(9000, 26 * 60, tr("Air"), 0);
 | ||||
| //	plannerModel->addStop(9000, 41 * 60, tr("Air"), 0);
 | ||||
| 	plannerModel->addStop(M_OR_FT(5,15), 42 * 60, tr("Air"), 0); | ||||
| 	plannerModel->addStop(M_OR_FT(5,15), 45 * 60, tr("Air"), 0); | ||||
| 	plannerModel->addStop(0, 0, O2_IN_AIR, 0, 0); | ||||
| 	plannerModel->addStop(M_OR_FT(15,45), 1 * 60, O2_IN_AIR, 0, 0); | ||||
| 	plannerModel->addStop(M_OR_FT(15,45), 40 * 60, O2_IN_AIR, 0, 0); | ||||
| 	plannerModel->addStop(M_OR_FT(5,15), 42 * 60, O2_IN_AIR, 0, 0); | ||||
| 	plannerModel->addStop(M_OR_FT(5,15), 45 * 60, O2_IN_AIR, 0, 0); | ||||
| } | ||||
| 
 | ||||
| void DivePlannerPointsModel::loadFromDive(dive* d) | ||||
|  | @ -431,14 +430,22 @@ void DivePlannerPointsModel::loadFromDive(dive* d) | |||
| 	 * as soon as the model is modified, it will | ||||
| 	 * remove all samples from the current dive. | ||||
| 	 * */ | ||||
| 	struct dive *backupDive = alloc_dive(); | ||||
| 	backupDive->when = current_dive->when; // do we need anything else?
 | ||||
| 	copy_samples(current_dive, backupDive); | ||||
| 	copy_cylinders(current_dive, backupDive); | ||||
| 	copy_events(current_dive, backupDive); | ||||
| 	backupSamples.clear(); | ||||
| 	for(int i = 1; i < d->dc.samples-1; i++){ | ||||
| 	for(int i = 0; i < d->dc.samples-1; i++){ | ||||
| 		backupSamples.push_back( d->dc.sample[i]); | ||||
| 	} | ||||
| 
 | ||||
| 	save_dive(stdout, current_dive); | ||||
| 	save_dive(stdout, backupDive); | ||||
| 	Q_FOREACH(const sample &s, backupSamples){ | ||||
| 		// we need to use the correct gas
 | ||||
| 		plannerModel->addStop(s.depth.mm, s.time.seconds, tr("Air"), 0); | ||||
| 		int o2 = 0, he = 0; | ||||
| 		get_gas_from_events(&backupDive->dc, s.time.seconds, &o2, &he); | ||||
| 		qDebug() << "time / depth" << s.time.seconds << s.depth.mm << "o2/he" << o2 << he; | ||||
| 		plannerModel->addStop(s.depth.mm, s.time.seconds, o2, he, 0); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -466,6 +473,10 @@ void DivePlannerGraphics::drawProfile() | |||
| 	plannerModel->createTemporaryPlan(); | ||||
| 	struct diveplan diveplan = plannerModel->getDiveplan(); | ||||
| 	struct divedatapoint *dp = diveplan.dp; | ||||
| 	if (!dp) { | ||||
| 		plannerModel->deleteTemporaryPlan(); | ||||
| 		return; | ||||
| 	} | ||||
| 	while(dp->next) | ||||
| 		dp = dp->next; | ||||
| 
 | ||||
|  | @ -476,16 +487,16 @@ void DivePlannerGraphics::drawProfile() | |||
| 	} | ||||
| 
 | ||||
| 	// Re-position the user generated dive handlers
 | ||||
| 	for (int i = 0; i < plannerModel->rowCount(); i++) { | ||||
| 	for (int i = 1; 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)); | ||||
| 		QPointF p1 = (i == 0) ? QPointF(timeLine->posAtValue(0), depthLine->posAtValue(0)) : handles[i-1]->pos(); | ||||
| 		QPointF p1 = handles[i-1]->pos(); | ||||
| 		QPointF p2 = handles[i]->pos(); | ||||
| 		QLineF line(p1, p2); | ||||
| 		QPointF pos = line.pointAt(0.5); | ||||
| 		gases[i]->setPos(pos); | ||||
| 		gases[i]->setText( strForAir(dp)); | ||||
| 		gases[i]->setText(strForAir(plannerModel->at(i-1))); | ||||
| 	} | ||||
| 
 | ||||
| 	// (re-) create the profile with different colors for segments that were
 | ||||
|  | @ -953,10 +964,15 @@ 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 p.po2; | ||||
| 			case DEPTH: return rint(get_depth_units(p.depth, NULL, NULL)); | ||||
| 			case DURATION: return p.time / 60; | ||||
| 			case GAS: return strForAir(p); | ||||
| 		case CCSETPOINT: return p.po2; | ||||
| 		case DEPTH: return rint(get_depth_units(p.depth, NULL, NULL)); | ||||
| 		case DURATION: return p.time / 60; | ||||
| 		case GAS: | ||||
| 			if (index.row() > 0) { | ||||
| 				p = divepoints.at(index.row() - 1); | ||||
| 				return strForAir(p); | ||||
| 			} | ||||
| 			return ""; | ||||
| 		} | ||||
| 	} else if (role == Qt::DecorationRole) { | ||||
| 		switch(index.column()) { | ||||
|  | @ -973,23 +989,30 @@ bool DivePlannerPointsModel::setData(const QModelIndex& index, const QVariant& v | |||
| 	if(role == Qt::EditRole) { | ||||
| 		divedatapoint& p = divepoints[index.row()]; | ||||
| 		switch(index.column()) { | ||||
| 			case DEPTH: p.depth = units_to_depth(value.toInt()); break; | ||||
| 			case DURATION: p.time = value.toInt() * 60; break; | ||||
| 			case CCSETPOINT:{ | ||||
| 				int po2 = 0; | ||||
| 				QByteArray gasv = value.toByteArray(); | ||||
| 				if (validate_po2(gasv.data(), &po2)) | ||||
| 					p.po2 = po2; | ||||
| 			} break; | ||||
| 			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; | ||||
| 		case DEPTH: p.depth = units_to_depth(value.toInt()); break; | ||||
| 		case DURATION: p.time = value.toInt() * 60; break; | ||||
| 		case CCSETPOINT: { | ||||
| 			int po2 = 0; | ||||
| 			QByteArray gasv = value.toByteArray(); | ||||
| 			if (validate_po2(gasv.data(), &po2)) | ||||
| 				p.po2 = po2; | ||||
| 			} | ||||
| 			break; | ||||
| 		case GAS: { | ||||
| 			if (index.row() == 0) { | ||||
| 				qDebug() << "how can index.row be 0???"; | ||||
| 				return false; | ||||
| 			} | ||||
| 			divedatapoint& pp = divepoints[index.row() - 1]; | ||||
| 			int o2 = 0; | ||||
| 			int he = 0; | ||||
| 			QByteArray gasv = value.toByteArray(); | ||||
| 			if (validate_gas(gasv.data(), &o2, &he)) { | ||||
| 				pp.o2 = o2; | ||||
| 				pp.he = he; | ||||
| 			} | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
| 		editStop(index.row(), p); | ||||
| 	} | ||||
|  | @ -1076,23 +1099,32 @@ bool divePointsLessThan(const divedatapoint& p1, const divedatapoint& p2) | |||
| 	return p1.time <= p2.time; | ||||
| } | ||||
| 
 | ||||
| int DivePlannerPointsModel::addStop(int milimeters, int minutes, const QString& gas, int ccpoint) | ||||
| int DivePlannerPointsModel::addStop(int milimeters, int minutes, int o2, int he, int ccpoint) | ||||
| { | ||||
| 	int row = divepoints.count(); | ||||
| 	if(milimeters == 0 && minutes == 0) { | ||||
| 		if(row == 0) { | ||||
| 			milimeters = M_OR_FT(10,30); | ||||
| 			minutes = 600; | ||||
| 		} else { | ||||
| 			divedatapoint p = at(row-1); | ||||
| 			milimeters = p.depth; | ||||
| 			minutes = p.time + 600; | ||||
| 		} | ||||
| 	if(row == 0) { | ||||
| 		beginInsertRows(QModelIndex(), row, row); | ||||
| 		divedatapoint point; | ||||
| 		point.depth = 0; | ||||
| 		point.time = 0; | ||||
| 		point.o2 = o2; | ||||
| 		point.he = he; | ||||
| 		point.po2 = ccpoint; | ||||
| 		divepoints.append( point ); | ||||
| 		endInsertRows(); | ||||
| 		row++; | ||||
| 	} | ||||
| 
 | ||||
| 	// check if there's already a new stop before this one:
 | ||||
| 	for (int i = 0; i < divepoints.count(); i++) { | ||||
| 	for (int i = 0; i < row; i++) { | ||||
| 		const divedatapoint& dp = divepoints.at(i); | ||||
| 		if (dp.time == minutes) { | ||||
| 			row = i; | ||||
| 			beginRemoveRows(QModelIndex(), row, row); | ||||
| 			divepoints.remove(row); | ||||
| 			endRemoveRows(); | ||||
| 			break; | ||||
| 		} | ||||
| 		if (dp.time > minutes ) { | ||||
| 			row = i; | ||||
| 			break; | ||||
|  | @ -1104,16 +1136,9 @@ int DivePlannerPointsModel::addStop(int milimeters, int minutes, const QString& | |||
| 	divedatapoint point; | ||||
| 	point.depth = milimeters; | ||||
| 	point.time = minutes; | ||||
| 	if (row == 0) { | ||||
| 		point.o2 = 209; | ||||
| 		point.he = 0; | ||||
| 		point.po2 = 0; | ||||
| 	} else { | ||||
| 		divedatapoint before = at(row-1); | ||||
| 		point.o2 = before.o2; | ||||
| 		point.he = before.he; | ||||
| 		point.po2 = 0; | ||||
| 	} | ||||
| 	point.o2 = o2; | ||||
| 	point.he = he; | ||||
| 	point.po2 = ccpoint; | ||||
| 	divepoints.append( point ); | ||||
| 	std::sort(divepoints.begin(), divepoints.end(), divePointsLessThan); | ||||
| 	endInsertRows(); | ||||
|  | @ -1185,8 +1210,8 @@ void DivePlannerPointsModel::createTemporaryPlan() | |||
| 	// Get the user-input and calculate the dive info
 | ||||
| 	// Not sure if this is the place to create the diveplan...
 | ||||
| 	// We just start with a surface node at time = 0
 | ||||
| 	struct divedatapoint *dp = create_dp(0, 0, 209, 0, 0); | ||||
| 	dp->entered = TRUE; | ||||
| 	struct divedatapoint *dp = NULL; // create_dp(0, 0, 209, 0, 0);
 | ||||
| //	dp->entered = TRUE;
 | ||||
| 	diveplan.dp = dp; | ||||
| 	int lastIndex = -1; | ||||
| 	for (int i = 0; i < rowCount(); i++) { | ||||
|  | @ -1205,6 +1230,7 @@ void DivePlannerPointsModel::createTemporaryPlan() | |||
| 	if (mode == ADD) { | ||||
| 		copy_samples(tempDive, current_dive); | ||||
| 		copy_cylinders(tempDive, current_dive); | ||||
| 		copy_events(tempDive, current_dive); | ||||
| 	} | ||||
| #if DEBUG_PLAN | ||||
| 	dump_plan(&diveplan); | ||||
|  | @ -1215,7 +1241,9 @@ void DivePlannerPointsModel::undoEdition() | |||
| { | ||||
| 	clear(); | ||||
| 	Q_FOREACH(const sample &s, backupSamples){ | ||||
| 		plannerModel->addStop(s.depth.mm, s.time.seconds, tr("Air"), 0); | ||||
| 		int o2, he; | ||||
| 		get_gas_from_events(¤t_dive->dc, s.time.seconds, &o2, &he); | ||||
| 		plannerModel->addStop(s.depth.mm, s.time.seconds, o2, he, 0); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ public: | |||
| 	int size(); | ||||
| 	struct diveplan getDiveplan(); | ||||
| public slots: | ||||
| 	int addStop(int meters = 0, int minutes = 0,const QString& gas = QString(), int ccpoint = 0 ); | ||||
| 	int addStop(int meters = 0, int minutes = 0, int o2 = 0, int he = 0, int ccpoint = 0 ); | ||||
| 	void setGFHigh(short gfhigh); | ||||
| 	void setGFLow(short ghflow); | ||||
| 	void setSurfacePressure(int pressure); | ||||
|  |  | |||
|  | @ -539,14 +539,13 @@ void MainTab::rejectChanges() | |||
| 	if (mainWindow() && mainWindow()->dive_list()->selectedTrips.count() == 1){ | ||||
| 		ui.notes->setText(notesBackup[NULL].notes ); | ||||
| 		ui.location->setText(notesBackup[NULL].location); | ||||
| 	}else{ | ||||
| 	} else { | ||||
| 		if (editMode == ADD) { | ||||
| 			// clean up
 | ||||
| 			delete_single_dive(selected_dive); | ||||
| 			DivePlannerPointsModel::instance()->cancelPlan(); | ||||
| 		} | ||||
| 		else if (editMode == MANUALLY_ADDED_DIVE ){ | ||||
| 			DivePlannerPointsModel::instance()->undoEdition(); | ||||
| 		} else if (editMode == MANUALLY_ADDED_DIVE ) { | ||||
| 			DivePlannerPointsModel::instance()->undoEdition(); // that's BOGUS... just copy the original dive back and be done with it...
 | ||||
| 		} | ||||
| 		struct dive *curr = current_dive; | ||||
| 		ui.notes->setText(notesBackup[curr].notes ); | ||||
|  |  | |||
|  | @ -94,7 +94,6 @@ private: | |||
| 	 * dive to this structure, making all editions there, | ||||
| 	 * then applying the changes on the other dives.*/ | ||||
| 	struct dive multiEditEquipmentPlaceholder; | ||||
| 
 | ||||
| 	Completers completers; | ||||
| 	void resetPallete(); | ||||
| 	void saveTags(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue