mirror of
				https://github.com/subsurface/subsurface.git
				synced 2025-02-19 22:16:15 +00:00 
			
		
		
		
	Dive trip model: send changed signals if visibility changed in trips
To avoid having to do full filter reloads, send dive-changed signals for dives in trips when the shown-status changed. But only for trips where not all dives are hidden. Because for those, the plan is to hide the trip as a whole. Implement the signal sending in its own function so that it can be reused for top-level items and the list-view. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
		
							parent
							
								
									3cc6576913
								
							
						
					
					
						commit
						4ca65894c8
					
				
					 2 changed files with 38 additions and 4 deletions
				
			
		|  | @ -691,14 +691,43 @@ dive *DiveTripModelTree::diveOrNull(const QModelIndex &index) const | ||||||
| 	return tripOrDive(index).dive; | 	return tripOrDive(index).dive; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool calculateFilterForTrip(const std::vector<dive *> &dives, const DiveFilter *filter) | // Send data changed signals blockwise. Which entries are changed is collected
 | ||||||
|  | // in the first parameter "changed".
 | ||||||
|  | void DiveTripModelBase::sendShownChangedSignals(const std::vector<char> &changed, quintptr parentIndex) | ||||||
|  | { | ||||||
|  | 	static const QVector<int> roles { SHOWN_ROLE }; | ||||||
|  | 	for (size_t i = 0; i < changed.size(); ++i) { | ||||||
|  | 		// Find first and last block of changed items
 | ||||||
|  | 		if (!changed[i]) | ||||||
|  | 			continue; | ||||||
|  | 		size_t j; | ||||||
|  | 		for (j = i + 1; j < changed.size() && changed[j]; ++j) | ||||||
|  | 			; // Pass
 | ||||||
|  | 		dataChanged(createIndex(i, 0, parentIndex), createIndex(j - 1, 0, parentIndex), roles); | ||||||
|  | 		i = j - 1; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Applying the filter to trip-items is a bit tricky:
 | ||||||
|  | // We only want to send changed-signals if one of the dives remains visible.
 | ||||||
|  | // Because if no dive remains visible, we'll simply send a signal on the parent trip,
 | ||||||
|  | // which will then be hidden and all the dives will be hidden implicitly as well.
 | ||||||
|  | // Thus, do this in two passes: collect changed dives and only if any dive is visible,
 | ||||||
|  | // send the signals.
 | ||||||
|  | bool DiveTripModelTree::calculateFilterForTrip(const std::vector<dive *> &dives, const DiveFilter *filter, int parentIndex) | ||||||
| { | { | ||||||
| 	bool showTrip = false; | 	bool showTrip = false; | ||||||
|  | 	std::vector<char> changed; | ||||||
|  | 	changed.reserve(dives.size()); | ||||||
| 	for (dive *d: dives) { | 	for (dive *d: dives) { | ||||||
| 		bool shown = filter->showDive(d); | 		bool shown = filter->showDive(d); | ||||||
| 		filter_dive(d, shown); | 		changed.push_back(filter_dive(d, shown)); | ||||||
| 		showTrip |= shown; | 		showTrip |= shown; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	// If any dive is shown, send changed-signals
 | ||||||
|  | 	if (showTrip) | ||||||
|  | 		sendShownChangedSignals(changed, parentIndex); | ||||||
| 	return showTrip; | 	return showTrip; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -714,14 +743,15 @@ void DiveTripModelTree::recalculateFilter() | ||||||
| 		// as a consequence of the filterReset signal right after the local scope.
 | 		// as a consequence of the filterReset signal right after the local scope.
 | ||||||
| 		auto marker = diveListNotifier.enterCommand(); | 		auto marker = diveListNotifier.enterCommand(); | ||||||
| 		DiveFilter *filter = DiveFilter::instance(); | 		DiveFilter *filter = DiveFilter::instance(); | ||||||
| 		for (Item &item: items) { | 		for (size_t i = 0; i < items.size(); ++i) { | ||||||
|  | 			Item &item = items[i]; | ||||||
| 			if (item.d_or_t.dive) { | 			if (item.d_or_t.dive) { | ||||||
| 				dive *d = item.d_or_t.dive; | 				dive *d = item.d_or_t.dive; | ||||||
| 				item.shown = filter->showDive(item.d_or_t.dive); | 				item.shown = filter->showDive(item.d_or_t.dive); | ||||||
| 				filter_dive(d, item.shown); | 				filter_dive(d, item.shown); | ||||||
| 			} else { | 			} else { | ||||||
| 				// Trips are shown if any of the dives is shown
 | 				// Trips are shown if any of the dives is shown
 | ||||||
| 				item.shown = calculateFilterForTrip(item.dives, filter); | 				item.shown = calculateFilterForTrip(item.dives, filter, i); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -6,6 +6,8 @@ | ||||||
| #include "core/subsurface-qt/DiveListNotifier.h" | #include "core/subsurface-qt/DiveListNotifier.h" | ||||||
| #include <QAbstractItemModel> | #include <QAbstractItemModel> | ||||||
| 
 | 
 | ||||||
|  | struct DiveFilter; | ||||||
|  | 
 | ||||||
| // There are two different representations of the dive list:
 | // There are two different representations of the dive list:
 | ||||||
| // 1) Tree view: two-level model where dives are grouped by trips
 | // 1) Tree view: two-level model where dives are grouped by trips
 | ||||||
| // 2) List view: one-level model where dives are sorted by one out
 | // 2) List view: one-level model where dives are sorted by one out
 | ||||||
|  | @ -98,6 +100,7 @@ protected: | ||||||
| 	// Access trip and dive data
 | 	// Access trip and dive data
 | ||||||
| 	static QVariant diveData(const struct dive *d, int column, int role); | 	static QVariant diveData(const struct dive *d, int column, int role); | ||||||
| 	static QVariant tripData(const dive_trip *trip, int column, int role); | 	static QVariant tripData(const dive_trip *trip, int column, int role); | ||||||
|  | 	void sendShownChangedSignals(const std::vector<char> &changed, quintptr parentIndex); | ||||||
| 
 | 
 | ||||||
| 	virtual dive *diveOrNull(const QModelIndex &index) const = 0;	// Returns a dive if this index represents a dive, null otherwise
 | 	virtual dive *diveOrNull(const QModelIndex &index) const = 0;	// Returns a dive if this index represents a dive, null otherwise
 | ||||||
| 	virtual void clearData() = 0; | 	virtual void clearData() = 0; | ||||||
|  | @ -130,6 +133,7 @@ private: | ||||||
| 	void recalculateFilter(); | 	void recalculateFilter(); | ||||||
| 	void divesChangedTrip(dive_trip *trip, const QVector<dive *> &dives); | 	void divesChangedTrip(dive_trip *trip, const QVector<dive *> &dives); | ||||||
| 	void divesTimeChangedTrip(dive_trip *trip, timestamp_t delta, const QVector<dive *> &dives); | 	void divesTimeChangedTrip(dive_trip *trip, timestamp_t delta, const QVector<dive *> &dives); | ||||||
|  | 	bool calculateFilterForTrip(const std::vector<dive *> &dives, const DiveFilter *filter, int parentIndex); | ||||||
| 
 | 
 | ||||||
| 	// The tree model has two levels. At the top level, we have either trips or dives
 | 	// The tree model has two levels. At the top level, we have either trips or dives
 | ||||||
| 	// that do not belong to trips. Such a top-level item is represented by the "Item"
 | 	// that do not belong to trips. Such a top-level item is represented by the "Item"
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue