aboutsummaryrefslogtreecommitdiffstats
path: root/qt-models/filtermodels.h
AgeCommit message (Collapse)Author
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>
2017-12-24Fold MultiFilterInterface into FilterModelBaseGravatar Berthold Stoeger
There were two classes, MultiFilterInterface and FiterModelBase. The latter derives from the former and from QStringListModel. The former was not used anywhere else. Moreover, in contradiction to its name, MultiFilterInterface is not an interface (in the Java sense), because it actually has (non-virtual) data members. All in all, the data model is very weird. Merge these two classes, since there seems to be no gain whatsoever from keeping MultiFilterInterface separate. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-11-26Inform LocationFilterModel of added dive site nameGravatar Berthold Stoeger
If the user implicitly adds a dive site by editing a dive, and a location filter is active, check the new dive site in the location filter. This is done by informing the LocationFilterModel of the new dive site name prior to repopulation. The LocationFilterModel then adds a corresponding entry and marks it as checked. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-11-26Inform LocationFilterModel of changed dive site nameGravatar Berthold Stoeger
Since commit 01d961086c1d175732c597dc9acdba7cc4cd2d26, the location filter list is updated if a dive site is edited. The problem is that if the name of a selected dive site is changed, the selection is lost. Therefore, before repopulating, inform the location filter that a dive site changed its name. The location filter then internally changes the name and can properly transfer the old selection on repopulate. This is performed via the new LocationInformationWidget::nameChanged signal, which is connected to the new LocationFilterModel::changeName slot. A special case to be handled is the following: [ ] Site 1 [x] Site 2 and "Site 2" being renamed to "Site 1", i.e. both sites being merged. Here, the merging is detected and "Site 1" will likewise be checked: [x] Site 1 [x] Site 1 No merging is performed, as the list will be repopulated anyway. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-11-25Update filters on refreshDisplay and remember old selecttionsGravatar Berthold Stoeger
Update the filters if the list of dives is updated by calling MultiFilterSortModel::instance()->myInvalidate(); This had the side effect of clearing all selections. Thus, in the repopulate() methods of the FilterModels, check those entries that were checked previously. Since all the filter models use the same code, introduce a base class FilterModelBase. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-11-25Replace bool * array by std::vector<char> in MultiFilterInterfaceGravatar Berthold Stoeger
This replaces a dynamically allocated array of bool by std::vector<char>. 1) This makes the code shorter and less error prone, because memory management has not to be done by hand. 2) It fixes a bug in the old code: memset(checkState, false, list.count()) is wrong, because bool is not guaranteed to be the same size as char! Two notes: 1) QMap<>, QVector<>, etc. are used numerous times in the code, so this doesn't introduce a new C++ concept. Here, the std:: version is used, because there is no need for reference counting, COW semantics, etc. 2) std::vector<char> is used instead of std::vector<bool>, because the latter does a pessimization where a bitfield is used! Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-04-29Add SPDX header to Qt modelsGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2015-05-29Move the models to its own folderGravatar Tomaz Canabrava
This is an attempt to help share code between the desktop version of Subsurface and the mobile version. More code will be moved around and the models will be split in a way that will help recompile times and also creation of different interfaces for different form-factors. Signed-off-by: Tomaz Canabrava <tomaz.canabrava@intel.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>