aboutsummaryrefslogtreecommitdiffstats
path: root/qt-models/filtermodels.h
AgeCommit message (Collapse)Author
2020-05-07cleanup: invert control-flow when resetting the core structuresGravatar Berthold Stoeger
To reset the core data structures, the mobile and desktop UIs were calling into the dive-list models, which then reset the core data structures, themselves and the unrelated locationinformation model. The UI code then reset various other things, such as the TankInformation model or the map. . This was unsatisfying from a control-flow perspective, as the models should display the core data, not act on it. Moreover, this meant lots of intricate intermodule-dependencies. Thus, straighten up the control flow: give the C core the possibility to send a "all data reset" event. And do that in those functions that reset the core data structures. Let each module react to this event by itself. This removes inter-module dependencies. For example, the MainWindow now doesn't have to reset the TankInfoModel or the MapWidget. Then, to reset the core data structures, let the UI code simply directly call the respective core functions. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-11Grammar: replaces 'indexes' by 'indices'Gravatar Robert C. Helling
Grammar-nazi ran git grep -l 'indexes' | xargs sed -i '' -e 's/indexes/indices/g' to prevent future wincing when reading the source code. Unfortunatly, Qt itself is infected as in QModelIndexList QItemSelection::indexes() const Signed-off-by: Robert C. Helling <helling@atdotde.de>
2019-12-10Dive list: remove global pointer to DiveTrip modelGravatar Berthold Stoeger
This part of the code had that horrible pattern, where reseting the model would invalidate all pointers to the DiveTrip model. Internalize these complexities in the MultiFilterSortModel. All accesses are now performed via that proxy model. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-10Dive list: clear dive data via the filter modelGravatar Berthold Stoeger
The UI talks to the filter model. Therefore route clearing of data through that model instead of accessing the source model directly. This will allow us to remove the DiveTripModel::instance() function and makes control flow less "jumpy". Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-12-04Selection: move translation of indexes to filter modelGravatar Berthold Stoeger
The DiveListView caught signals from the DiveTripModel with the corresponding indexes. However, the DiveListView is actually connected to the MultiFilterSortModel and thus has to translate the indexes. Instead, catch the signals in the MultiFilterSortModel, transform them and resend. Let the DiveListView get its signal from the MultiFilterSortModel. Yes, this makes things less efficient because there is an extra signal. On the upside, the makes data-flow much more logical. Selection will have to be fixed anyway. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: move recalculation of filter from FilterModel to TripModelGravatar Berthold Stoeger
The way this was accessed via Qt's model semantics was horrible. This gives arguably more readable code, since we don't have to shoehorn things through QVariants. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: split out filter from modelGravatar Berthold Stoeger
Split out the actual filtering from the MultiFilterSortModel. Create a DiveFilter class that does the actual filtering. Currently, mobile and desktop have their own version of this class, though ultimately we may want to merge them. The idea here is that the trip-model and undo-commands have direct access to the filter-function and thus can take care of keeping track of the number of shown dives, etc. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: move calculation of shown dives to undo commandGravatar Berthold Stoeger
The filter-model was catching dives-added / dives-deleted signals from the models to keep track of the number of shown dives. To simplify the data flow, do this directly in the undo-command. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Filter: move number of shown dives to coreGravatar Berthold Stoeger
We mark hidden/shown dives in the core but store the number of shown dives in the MultiFilterSortModel. Move this datum to the core for improved locality. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Cleanup: remove MultiFilterSortModel::filterChanged()Gravatar Berthold Stoeger
Nobody was calling this function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-11-19Cleanup: remove MultiFilterSortModel::clearFilterGravatar Berthold Stoeger
Nobody was using that function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-05-11Filter: add reference counting for dive-site modeGravatar Berthold Stoeger
The dive-site-edit and dive-site-table tabs both put the filter into a special dive-site mode. When switching between both, it could happen that the one got its show befor the other got its hide event. Thus, the first would start dive-site filtering and the second stop it. Now the app was not in filter mode even though it should. To solve this problem, add reference counting for the filter's dive-site mode. In both tabs call the enter/exit functions on show/hide. In the dive-site-table tab, when the selection changes, use a set function that doesn't modify the reference count. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-05-11Map: in dive-site-edit mode, select those maps we filter forGravatar Berthold Stoeger
When dive sites are edited, we shouldn't highlight the sites of the current dive, but the currently edited site(s). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-05-11Map: show all dive sites when in dive-site filter modeGravatar Berthold Stoeger
When on the dive site tab or editing a dive site, we want to show all dive sites so that the user can related different dive sites. Therefore export a "in dive site mode" flag from the filter model and don't filter in that case in MapWidgetHelper. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-12Filter: allow filtering multiple dive sitesGravatar Berthold Stoeger
In the edit-dive-site tab the filter is switched to a particular mode where only dives at that site are shown. If we want to reuse this for the dive-site tab the mode has to be extended to allow for multiple dive sites. This is trivially done by replacing a pointer by a vector of pointers. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-12Filter: call update title directly in filter modelGravatar Berthold Stoeger
Instead of sending a signal when counts change, catching them in the filter widget and update the window title there, directly update the window title in the model. This removes a signal/slot pair. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-12Undo: update filter flag when dives changeGravatar Berthold Stoeger
The filter code is strange: it actually only checks the dive->hidden_by_filter flag. Thus, before propagating the dive changed signal, this flag has to be updated. Do this in the DiveTripModel. Ultimately, this should be refactored. Moreover, if the filter-flag changed notify the frontend of a changed trip so that the trip is hidden / unhidden. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-02-28Filter panel: add suit and notes search fieldsGravatar Willem Ferguson
All the field in the Notes Panel of the main window are now supported. This needs some testing especially for the Notes field that may contain markup. It appears ok to me for single term searches. One would like to think about the default search option for the Notes. There is a vertical spacer in the Filter panel that I moved downwards and whose function I am not quite sure of. [Dirk Hohndel: small adjustments] Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-02-20Filter: change default mode for location to any-ofGravatar Berthold Stoeger
Since a dive has only one location all-of makes little sense. It *can* make sense if the user enters two substrings (e.g. Tofo and Reef), but generally it won't. Therefore change the default to any-of. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-02-19Filter: implement any-of modeGravatar Berthold Stoeger
Add an additional mode to the tags, people and location filters: any_of. Replace the original invert-bool by an enum. Move the common code into a distinct function. Reported-by: Willem Ferguson <willemferguson@zoology.up.ac.za> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-26Filter: quick implementation of negationGravatar Berthold Stoeger
Add negate buttons to the Tags, People, Location and Equipment filters. Currently, if nothing is entered the filter is ignored whether negate is on or off. One might think about filtering all dives without tags, etc. instead. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-26Filter: implement reset filterGravatar Berthold Stoeger
Move initialization to a separate function and connect that to the reset button. Two points of note: 1) Reseting the text-fields causes signals. Thus, signals have to be ignored during reset. Do this with a new flag. 2) To make reset of the from-date work, the from-date has to be initialized to a distinct value. Setting a default-constructed QDateTime leaves the widget unchanged. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-26Filter: update counts if dives added / removedGravatar Berthold Stoeger
Update the filter counts if dives were added removed by the undo commands. The undo commands call into the filter model at the right time so that hidden_by_filter is already set. The filter model keeps track of the counts and emits a signal, which is caught by the widget. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-22Filter: extend range of allowed temperaturesGravatar Berthold Stoeger
The temperature range 0-100 was inadequate in both supported scales (Celsius and Fahrenheit). Extend the range to encompass all physically meaningful values in both scales. Use the default-values to set the minimum and maximum of the UI-fields. Thus, these values are configurable in a single place. In the future we should use a scale-independent representation (e.g. mkelvin as in the rest of the code base). But this would mean implementing a custom widget with a conversion function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-21Desktop, Filter UI: make date/time consistentGravatar Jan Mulder
On all (most?) places we use separate date/time fields for the time of a dive, and we follow the setting from the preferences to format those. Make the new filter widget consistent, with respect to the to and from interval. Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2019-01-19Filter: update filterData directly without copyingGravatar Berthold Stoeger
In FilterWidget2::updateFilter() a new FilterData object is generated and then copied onto the filterData member variable. Instead, modify filterData directly. This seems also more logical from a semantic point of view: Do we want to reset fields that were not set by the user? Contains trivial whitespace fix. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-08Filter for logged/planned divesGravatar Robert C. Helling
Add filter for dives having a planned dive computer or a logged dive computer. Signed-off-by: Robert C. Helling <helling@atdotde.de>
2019-01-07Dive list: split DiveTripModel into distinct models (tree and list)Gravatar Berthold Stoeger
The DiveTripModel was used to represent both, trip and list views. Thus many functions had conditionals checking for the current mode and both modes had to be represented by the same data structure. Instead, split the model in two and derive them from a base class, which implements common functions and defines an interface. The model can be switched by a call to resetModel(), which invalidates any pointer obtained by instance(). This is quite surprising behavior. To handle it, straighten out the control flow: DiveListView --> MultiFilterSortModel --> DiveTripModelBase Before, DiveListView accessed DiveTripModelBase directly. A goal of this commit is to enable usage of the same model by mobile and desktop. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-07Cleanup: Remove MultiFilterSortModel::modelGravatar Berthold Stoeger
The source-model was cached in MultiFilterSortModel. For simplicity, remove that and simply access via DiveTripModel::instance(). There is only one instance where the cached model was used: when comparing items for sorting. Thus, in indirection is added in a "hot" path. Nevertheless, this will dwarf against the cost of string comparison. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-12-14Drop old filter codeGravatar Tomaz Canabrava
Drop tons of now-unused-code. Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
2018-12-14Struct FilterDataGravatar Tomaz Canabrava
The idea is that this struct will have all the needed data that will be passed to the filter model. Everything that happens on the filterwidget will fill out this struct, then forward it to the model, that in turn will activate the filter hiding some of the dives that matches on your divelist. Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
2018-11-01Dive list: implement custom lessThan functionGravatar Berthold Stoeger
The dive list was sorted using the default-sorter of QSortFilterProxy model. This is mighty inflexible as it considers only one column. This has the funky effect that for rows with identical elements, the sort order depends on the previous sorting. Implement a lessThan() function in the MultiFilterSortModel, which simply hands the sorting down to the actual model. This might be considered a layering violation, but it makes things so much easier. Sadly, it seems like the column-to-be-sorted is transported in the provided indices. Therefore, the comparison is chosen using a switch for *every* comparison. It would seem much more logical to set a function pointer once and use that. Further investigations are necessary. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-11-01Dive list: make filter model aware of its sourceGravatar Berthold Stoeger
The data-flow from C-core to list-view is as follows: C-core --> DiveTripModel --> MultiSortFilterModel --> DiveListView The control-flow, on the other hand, differs as DiveListView accesses both MultiSortFilterModel and DiveTripModel, whereas MultiSortFilterModel is mostly unaware of its source model. This is in principle legitimate, as the MultiSortFilterModel might be used for different sources. In our particular case, this is not so. MultiSortFilterModel is written for a particular use case. Therefore, model control-flow follow after data-flow: Let MultiSortFilterModel set its own source model and DiveListView access the MultiSortFilterModel, which then manages its source model. This is not bike-shedding, but will enable a more flexible and higher-performance sorting. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-29Dive site: remove [start|stop]FilterDiveSite signalsGravatar Berthold Stoeger
This is another case of a weird pattern where an object would connect it's own signal to the slot of a different object. There seems to be no reason why the former couldn't simply call the latter. Remove the [start|stop]FilterDiveSite signals of LocationInformationWidget and call the corresponding functions of MultiFilterSortModel directly. While doing so, replace the UUID argument by a pointer-to-divesite. It will be converted anyway right at the beginning of the function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Filter: reload only when checkstate changedGravatar Berthold Stoeger
Currently, the filter is recalculated if a filter-entry is changed. This also happens if the counts of a filter-entry changes. This is to be avoided, as it causes unnecessary churn. Therefore, send the proper role with the dataChanged() signal and add a new slot, which invalidates only if a field with the Qt::CheckStateRole is changed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Filter: Make filters aware of added / removed divesGravatar Berthold Stoeger
Instead of reloading all the filter, only increment / decrement the count of the entries of added / removed dives. Originally, this was planned to be done via the signals from the divelist, but it turned out that this was suboptimal, because if the filter decides that the new item is selected, this has to be done *before* adding the dive. Otherwise, it wouldn't be shown. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-09-29Cleanup: reinstate override modifiersGravatar Berthold Stoeger
This reverts commit 1c4a859c8d0b37b2e938209fe9c4d99e9758327a, where the override modifiers were removed owing to the noisy "inconsistent override modifiers" which is default-on in clang. This warning was disabled in 77577f717f5aad38ea8c4c41c10c181486c4337f, so we can reinstate the overrides. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-08-31Filter: sort filter items in FilterModelBase::updateList()Gravatar Berthold Stoeger
All callers of FilterModelBase::updateList() sorted the items (except the last one). Thus we can do the sorting inside the function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-31Filter: Make FilterModelBase a proper Qt model (mostly)Gravatar Berthold Stoeger
Since FilterModelBase now contains complex data (counts and checked), we might just as well make it a full model and keep track of the name as well. I.e. do not derive from QStringListModel but from QAbstractListModel and add the name to the item structure. Implement proper reset / add / rename semantics. This is overkill at the moment, as after all any modification the model will be reset, but ultimately it will allow us to be smarter and only update rows when needed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-28Filter: cache number of dives fulfilling filter rulesGravatar Berthold Stoeger
Currently, in FilterModelBase::data() the number of dives is recalculated. This happens for every mouse-over event! Calculate the number of dives only on recalculation and store the count in the items-struct. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-28Filter: replace checked-state by structGravatar Berthold Stoeger
In the future, we might be smarter about the dive-counts and calculate them only once and incrementally (if e.g. new dives are added). Prepare for more complex caching by turning the checked boolean into a struct, which can then be extended by a count and other things (e.g. the name). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-16Filter: separate backend from frontend logicGravatar Berthold Stoeger
The filter code was an unholy intermixture of backend and frontend logic, which made it hard to access it from outside of the UI. Notably, it expected that Qt would call filterAcceptsRow on all rows. For trip-view, apparently the filter functions were called twice (once for filtering the trip, then for filtering the individual dives). Make the filtering explicit, by calling showDive() for all dives in MultiFilterSortModel::myInvalidate(), setting the hidden_by_filter flags accordingly and ultimately invalidating the filter. The UI code only accesses the hidden_by_filter flag set previously. The "justCleared" flag can then be removed, since accessing the filter does not have side effects. Moreover, there is no noticeable performance gain by returning out early. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-14Filter: break out showDive() function from filterAcceptsRow()Gravatar Berthold Stoeger
To make dive-filtering accessible from other parts of the code, break out the actual dive-filtering code into a function that takes a pointer-to-dive instead of QModelIndex. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-14Filter: constify doFilter() argumentGravatar Berthold Stoeger
Conceptually, the doFilter() functions shouldn't modify the dive they test. Therefore, make the argument const. To do this, constify the parameter of get_dive_location(), which likewise seems to be the right thing to do. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-14Filter: remove unused parameters from doFilter functionsGravatar Berthold Stoeger
Change the signature from of the virtual doFilter() functions from bool doFilter(struct dive *d, QModelIndex&, QAbstractItemModel*) const; to bool LocationFilterModel::doFilter(struct dive *d) const; as the QModelIndex and QAbstractItemModel parameters were not used. This makes this functions independent from Qt's model/view framework. This is in preparation for making the undo-machinery compatible with the filtering. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-01Cleanup: remove all override modifiersGravatar Berthold Stoeger
Commit df156a56c08a56eb380711a507ef739d8150a71f replaced "virtual" by "override" where appropriate. Unfortunately, this had the unintended consequence of producing numerous clang warnings. If clang finds a override-modified function in a class definition, it warns for *all* overriden virtual functions without the override modifier. To solve this, go the easy route and remove all overrides. At least it is consistent. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-31Cleanup: replace virtual by override where appropriateGravatar Berthold Stoeger
The keyword "virtual" signalizes that the function is virtual, i.e. the function of the derived class is called, even if the call is on the parent class. It is not necessary to repeat the "virtual" keyword in derived classes. To highlight derived virtual functions, the keyword "override" should be used instead. It results in a hard compile- error, if no function is overridden, thus avoiding subtle bugs. Replace "virtual" by "override" where appropriate. Moreover, replace Q_DECL_OVERRIDE by override, since we require reasonably recent compilers anyway. Likewise, replace /* reimp */ by "override" for consistency and compiler support. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-26Introduce negate-toggle buttons to filter listsGravatar Berthold Stoeger
Introduce toggle buttons which mean "filter all dives except those fulfilling the selected criteria". The old code used to check for rowCount() == 0. This should never happen, because there is always a row "empty field". This check was moved into the preamble of the functions to seperate it from the actual logic. Fixes #435 Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-24Add select-all, deselect-all and invert-selection options to filtersGravatar Berthold Stoeger
To every filter list add a menu button that allows selection of all, selection of none or inversion of selection. Implements #435. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-24Move *FilterModel functions into base classGravatar Berthold Stoeger
The *FilterModels had a number of of virtual functions, which only accessed members of the base class. Moreover, these functions were identical and generated with macros. Therefore, move these functions to the base class. The one excption is data(), which uses different count functions (passed as a macro parameter). Thus, introduce a virtual countDives() function and likewise move data() to the base class. A function pointer might be even more clear, but since the rest of the code/Qt relies heavily on runtime polymorphism, let's do the same here. The only macros left are those creating the singleton accessors. This could be more clearly realized by templates, but let's likewise keep it the way is. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>