summaryrefslogtreecommitdiffstats
path: root/desktop-widgets/divelistview.cpp
AgeCommit message (Collapse)Author
2018-10-28Dive list: remove rememberSelection() without restoreSelection()Gravatar Berthold Stoeger
Remove three cases of rememberSelection() which did not possess the corresponding restoreSelection() twins. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-28Dive list: remember/restore selection only on view changeGravatar Berthold Stoeger
The selection was remembered/restored anytime the sort-order changed. Yet, this is only necessary if the view (tree, list) changes. Therefore, handle the selection only if this is the case. This automatically fixes the problem of the trip-selection not being remembered if the view doesn't change. If the view does change, trip selection is lost. But since the list view doesn't have trips to start with, losing trip-selection seems like an understandable behavior. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-28Dive list: show sort indicatorGravatar Berthold Stoeger
On desktop, show the a sort indicator to give a visual feedback on changes of the sort order. This is trivially done by calling the setSortIndicatorShown() function in DiveListView's constructor. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-28Dive list: switch to a default sort order on column-header clickGravatar Berthold Stoeger
On desktop, clicking on a column header sorts the dive-list. This has the interesting property that every click reverses the sort order (unless changing from list to tree-mode). The much more common idiom seems to be to define a default sort order for each column and switch to that when changing sort-column. Switch order after clicking the same column again. Implement this more common behavior. For now, sort # and date in descending, all other columns in ascending order. While doing this, use the proper enum (NR) for setting the default sort-column instead of its integer representation (0). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-25Dive list: emit selectionChanged signal in filterFinished()Gravatar Berthold Stoeger
In commit 9829e49815de1b81b5c9848b71eaa810faab2bcf the dive selection code was moved from the filter to the dive list. As a consequence of that change, the selectionChanged signal was not emitted anymore and therefore the map widget was not informed of the new dive site list. This had funky effects on the dive-site editing. Notably, changing the location would move the map, but not update the flag. Explicitly emit selectionChanged in filterFinished() to fix dive site editing. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-21Dive list: remove three unnecessary instances of qobject_cast<>.Gravatar Berthold Stoeger
In DiveListView, the result of model() was dynamically cast to QSortFilterProxyModel. But then, only the virtual match() function was used. The whole point of virtual functions is that you can cast them on the base-class and it will execute the function of the derived class. Thus, remove these casts and operate directly on the QAbstractItemModel base class. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-21Dive list: move dive-selection code from filter to listGravatar Berthold Stoeger
After invalidating the filter, the dive-selection was modified to ensure that at least one dive is selected. This was done in the filter code, but it seems preferrable to do this in the dive-list code, which has direct access to the selection-model. Therefore, move the code from MultiFilterSortModel to DiveListView. While doing so, split the code in DiveListView into more functions to: 1) Get the index of the first dive (if any). 2) Select the first dive (if any). This allows a distinct size reduction of conditional compilation in MultiFilterSortModel (accesses to MainWindow are not possible in mobile code). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Dive list: propagate current-item to frontendGravatar Berthold Stoeger
The command-objects select a current item, but this selection was not propagated to the front-end. The current item is the base for keyboard-navigation through the dive-list and therefore should be set correctly. It took some experimentation to get the flags right: QItemSelectionModel::Current Hopefully, these are the correct flags across all supported Qt versions! Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Dive list: expand trips if dives are selectedGravatar Berthold Stoeger
If dives are deleted, the trip(s) containing the dives are expanded. Thus, on undo it seems natural to re-expand the trip. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Undo: select dives after add, remove, merge, split dive commandsGravatar Berthold Stoeger
Select the proper dives after the add, remove, split and merge dives commands on undo *and* redo. Generally, select the added dives. For undo of add, remember the pre-addition selection. For redo of remove, select the closest dive to the first removed dive. The biggest part of the commit is the signal-interface between the dive commands and the dive-list model and dive-list view. This is done in two steps: 1) To the DiveTripModel in batches of trips. The dive trip model transforms the dives into indices. 2) To the DiveListView. The DiveListView has to translate the DiveTripModel indexes to actual indexes via its QSortFilterProxy- model. For code-reuse, derive all divelist-changing commands from a new base-class, which has a flag that describes whether the divelist changed. The helper functions which add and remove dives are made members of the base class and set the flag is a selected dive is added or removed. To properly detect when the current dive was deleted it became necessary to turn the current dive from an index to a pointer, because indices are not stable. Unfortunately, in some cases an index was expected and these places now have to transform the dive into an index. These should be converted in due course. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Dive list view: replace signal-magic by flagGravatar Berthold Stoeger
In DiveListView, we have a very fundamental problem: When On the one hand, we get informed of user-selection in the DiveListView::selectionChanged() slot. This has to set the correct flags in the C-backend. On the other hand, sometimes we have to set the selection programatically, e.g. when selecting a trip. This is done by calling QItemSelectionModel::select(). But: this will *also* call into the above slot, in which we can't tell whether it was a user interaction or an internal call. This can lead to either infinite loops or very inefficient behavior, because the current dive is set numerous times. The current code is aware of that and disconnects the corresponding signal. This is scary, as these signals are set internally by the model and view. Replace this by a global "command executing" flag in DiveListNotifier. The flag is set using a "marker" class, which resets the flag once it goes out of scope (cf. RAII pattern). In DiveListView, only process a selection if the flag is not set. Otherwise simply call the QTreeView base class, to reflect the new selection in the UI. To have a common point for notifications of selection changes, add such a signal to DiveListNotifier. This signal will be used by the DiveListView as well as the Command-objects. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Dive list: remember selected divesGravatar Berthold Stoeger
Don't delesect dives, when unregistering them from the backend. If a previously selected dive is added, select it in the dive-list. For this purpose introduce a SELECTED_ROLE to query the DiveTripModel for selected dives. Unfortunately, when adding multiple selected dives, current_dive_changed is called for each of them, making this very slow. This will have to be fixed in subsequent commits. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Dive list: implement proper Qt-model semantics for DiveTripModelGravatar Berthold Stoeger
Previously, each dive-list modifying function would lead to a full model reset. Instead, implement proper Qt-model semantics using beginInsertRows()/endInsertRows(), beginRemoveRows()/ endRemoveRows(), dataChange(). To do so, a DiveListNotifer singleton is generatated, which broadcasts all changes to the dive-list. Signals are sent by the commands and received by the DiveTripModel. Signals are batched by dive-trip. This seems to be an adequate compromise for the two kinds of list-views (tree and list). In the common usecase mostly dives of a single trip are affected. Thus, batching of dives is performed in two positions: - At command-level to batch by trip - In DiveTripModel to feed batches of contiguous elements to Qt's begin*/end*-functions. This is conceptually simple, but rather complex code. To avoid repetition of complex loops, the batching is implemented in templated-functions, which are passed lambda-functions, which are called for each batch. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Undo: isolate undo-commandsGravatar Berthold Stoeger
This refactors the undo-commands (which are now only "commands"). - Move everything in namespace Command. This allows shortening of names without polluting the global namespace. Moreover, the prefix Command:: will immediately signal that the undo-machinery is invoked. This is more terse than UndoCommands::instance()->... - Remove the Undo in front of the class-names. Creating an "UndoX" object to do "X" is paradoxical. - Create a base class for all commands that defines the Qt-translation functions. Thus all translations end up in the "Command" context. - Add a workToBeDone() function, which signals whether this should be added to the UndoStack. Thus the caller doesn't have to check itself whether this any work will be done. Note: Qt5.9 introduces "setObsolete" which does the same. - Split into public and internal header files. In the public header file only export the function calls, thus hiding all implementation details from the caller. - Split in different translation units: One for the stubs, one for the base classes and one for groups of commands. Currently, there is only one class of commands: divelist-commands. - Move the undoStack from the MainWindow class into commands_base.cpp. If we want to implement MDI, this can easily be moved into an appropriate Document class. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Undo: make diverse trip-related operations undo-ableGravatar Berthold Stoeger
AddDivesToTrip, CreateTrip, AutogroupDives, RemoveAutogenTrips and MergeTrips basically all did the same thing as RemoveDivesFromTrip, which was already implemented. Thus, factor our the common functionality and hook it up to make all these functions undo-able. Don't do the autogroup-call everytime the dive-list is rebuilt (that would create innumberable undo-actions), but only on dive-load / import or if expressly asked by the user [by switching the autogroup flag]. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Undo: implement rudimentary support for undo of dive-mergingGravatar Berthold Stoeger
For this, an output-parameter was added to the backend merge_dives() function. When non-zero, instead of adding the merged dive to the preferred trip, the preferred trip is returned to the caller. Since the new UndoObject, just like the delete-dives UndoObject, needs to remove/readd a set of dives, the corresponding functionality was split-off in a helper function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Undo: implement rudimentary support for undo of dive-splittingGravatar Berthold Stoeger
For this, the core functionality of the split_dive() and split_dive_at_time() functions were split out into new split_dive_dont_insert() and split_dive_at_time_dont_insert(), which do not add the new dives to the log. Thus, the undo-command can take ownership of these dives, without having to remove them first. The split-dive functionality is temporarily made desktop-only until mobile also supports "UndoObjects". Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-11Undo: fix multi-level undo of delete-dive and remove-dive-from-tripGravatar Berthold Stoeger
The original undo-code was fundamentally broken. Not only did it leak resources (copied trips were never freed), it also kept references to trips or dives that could be changed by other commands. Thus, anything more than a single undo could lead to crashes. Two ways of fixing this were considered 1) Don't store pointers, but unique dive-ids and trip-ids. Whereas such unique ids exist for dives, they would have to be implemented for trips. 2) Don't free objects in the backend. Instead, take ownership of deleted objects in the undo-object. Thus, all references in previous undo-objects are guaranteed to still exist (unless the objects are deleted elsewhere). After some contemplation, the second method was chosen, because it is significantly less intrusive. While touching the undo-objects, clearly separate backend from ui-code, such that they can ultimately be reused for mobile. Note that if other parts of the code delete dives, crashes can still be provoked. Notable examples are split/merge dives. These will have to be fixed later. Nevertheless, the new code is a significant improvement over the old state. While touching the code, implement proper translation string based on Qt's plural-feature (using %n). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-09-15Update the dive list context menu to reflect new media interfaceGravatar willemferguson
A minor change to the UI. The wording of the two items in the dive list context menu "Load image(s) from file(s)" and "Load image from web" are updated since we now deal with both images and videos. So it becomes "Load media from file(s)".... etc. Signed-off-by: willemferguson <willemferguson@zoology.up.ac.za> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2018-09-04Desktop: buddies in the dive listGravatar Jan Mulder
As proposed in RFC #1587, now also alllow buddies to be shown in the divelist. Fixes: #1587 Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2018-09-01Cleanup: make DiveTripModel a global objectGravatar Berthold Stoeger
DiveTripModel (the model describing the dive-list) was destroyed and recreated on every reset of the list. This seems excessive. Instead - in analogy to most other models - make it a single global object. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-29Dive trips: don't crash on repeated trip-removalGravatar Berthold Stoeger
In the UI it is possible to remove a dive from a trip twice, which leads to a crash, because trip is NULL (obviously). Instead of doing a proper fix (don't show the "remove from trip" entry in the first place), ignore dives without a trip, since a rewrite of the undo-code is planned for the medium future anyway. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-08-26divelistview: always show at least one columnGravatar Lubomir I. Ivanov
Currently it is possible to hide all columns by unchecking them in the context menu that appears by right clicking the header of the divelist. But once all are hidden the header disappears. This can cause a situation where the user cannot show any columns and the only fix for that is to edit the application configuration. To avoid this sutuation prevent the last column from being hidden. Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2018-07-30Cleanup: remove DiveListView::fixMessyQtModelBehaviour()Gravatar Berthold Stoeger
The function DiveListView::fixMessyQtModelBehaviour() was used to expand the first columns of dive-trips in the dive-list view. This function was called everytime that the dive-list was modified. It is kind of ludicrous that external callers would have to tell the DiveListView, when it has to update its column headers. Instead, place this functionality in the overriden reset() and rowsInserted() functions, as these are the only ways that rows can be added. Change the DiveTripModel to use the proper beginResetModel()/endResetModel() pair instead of the previous full deletion and full repopulation using the beginRemoveRows()/ endRemoveRows() and beginInsertRows()/endInsertRows(). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-30Cleanup: remove parameter from currentDiveChanged signalGravatar Berthold Stoeger
The currentDiveChanged signal was emitted by the DiveListView to inform the MainWindow of a change of current dive. The new current dive was passed as a parameter. The slot in MainWindow then called select_dive() on the dive. This seems pointless because: 1) In both emits, selected_dive dive was passed as argument. But MainWindow can read this global variable itself. 2) Calling select_dive() again is a no-op, because obviously, this already *was* the selected dive. Moreover it seems conceptually wrong to set the current dive in the slot that is informed of the change of the current dive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-30Cleanup: remove DiveListView::testSlot()Gravatar Berthold Stoeger
This debugging-slot was not linked anywhere. And especially in the light of the impending refactoring of DiveListView/DiveTreeModel it seems pointless to keep old debugging code. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-27Dive list view: setup columns in constructorGravatar Berthold Stoeger
The column-widths must only be set once the source-model is that. The old code realized this with a rather complicated logic. Instead, simply set the source-model in the constructor and set the column widths after that. Rename the corresponding function from "setupUi" to "setColumnWidths". Moreover, the setupUi function had different code-paths for the first and other calls. Since it is only called once, remove the other code paths. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-27Dive list view: move column width logic back from DiveTripModelGravatar Berthold Stoeger
Conceptually, the width of the columns should probably reside in the view not the model. But much more severly, the old code didn't work: Columns were set in a DiveTripModel, which was deleted right away. Therefore, move the logic back to the DiveListView. Introduce a QVector<int> of the initial column widths, so that they can be erased from the setting if unchanged. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-15For media file open dialog add different file filtersGravatar Stefan Fuchs
On top of the file filter for all media files add a file filter for images only, one for videos only and one for all files. Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
2018-07-15UI change of "images"/"photo" to "media" or "media files"Gravatar Stefan Fuchs
This changes the above mentioned terms everywhere in the UI to reflect the fact that Subsurface now also supports video files on top of image files. Signed-off-by: Stefan Fuchs <sfuchs@gmx.de>
2018-07-04Dive pictures: remove hashesGravatar Berthold Stoeger
In the last commits, the canonical-to-local filename map was made independent from the image hashes and the location of moved images was based on filename not hashes. The hashes are now in principle unused (except for conversion of old-style local filename lookups). Therefore, remove the hashes in this commit. This makes addition of images distinctly faster. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-07-04Dive pictures: index local file name by canonical filnameGravatar Berthold Stoeger
The connection canonical filename to local filename was done via two maps: 1) canonical filename -> hash 2) hash -> local filename But the local filename was always queried from the canonical filename. Therefore, directly index the former with the latter. On startup, convert the old map to the new one. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-06-04Cleanup: fold core/helpers.h into core/qthelper.hGravatar Berthold Stoeger
helpers.h included qthelper.h and all functions declared in helpers.h were defined in qthelper.h. Therefore fold the former into the latter, since the split seems completely arbitrary. While doing so, change the return-type of get_dc_nichname from "const QString" to "QString". Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-05-25Cleanup: Don't defer deletion of oldModel in DiveListView::reload()Gravatar Berthold Stoeger
There seems to be no point in using deleteLater() of the previous model. Set the new model and delete the old one. This fixes a crash with Qt 5.11. Tested-by: Gaetan Bisson <bisson@archlinux.org> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-05-24desktop-widgets: replace (void) with no parameter nameGravatar jan Iversen
Unused parameters in C++ are "silenced" by removing the name. Signed-off-by: Jan Iversen <jani@apache.org>
2018-05-23Fix includes for building against Qt-5.11.0Gravatar Gaetan Bisson
Signed-off-by: Gaetan Bisson <bisson@archlinux.org>
2018-05-21desktop-widgets: Change Q_UNUSED to no parameter nameGravatar jan Iversen
C++ permits use of parameters without name, which signals unused Signed-off-by: Jan Iversen <jani@apache.org>
2018-04-04Add "Tags" column in Desktop app's dive list viewGravatar Jeremie Guichard
Add DiveItem::displayTags helper method to return Tags as a QString New Tags column is by default inserted before "Photos" column by default disabled Signed-off-by: Jeremie Guichard <djebrest@gmail.com>
2018-03-14Cleanup: introduce copy_qstring() functionGravatar Berthold Stoeger
strdup(qPrintable(s)) and copy_string(qPrintable(s)) were such common occurrences that they seem worthy of a short helper-function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-03-14Cleanup: consistently use qPrintable()Gravatar Berthold Stoeger
Replace constructs of the kind s.toUtf8().data(), s.toUtf8().constData(), s.toLocal8Bit().data(), s.toLocal8Bit.constData() or qUtf8Printable(s) by qPrintable(s). This is concise, consistent and - in principle - more performant than the .data() versions. Sadly, owing to a suboptimal implementation, qPrintable(s) currently is a pessimization compared to s.toUtf8().data(). A fix is scheduled for new Qt versions: https://codereview.qt-project.org/#/c/221331/ Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-03-05Cleanup: Fold add_hash() call into learnHash() functionGravatar Berthold Stoeger
learnHash() was always called in conjunction with add_hash(). The pattern was that a local filename and a hash were connected in the hash-to-filename and the filename-to-hash maps. Then, the original picture-filename or url were registered in the filename-to-hash map. This commit changes learnHash() to take three parameters (original-filename, local-filename and hash) and do all of the above. The new code is simpler because no dummy picture struct has to be generated in DiveListView::loadImageFromURL(). The tests were extended to check for all hash<->filename associations. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-04Use QDir::exists() instead of QDir::setCurrent() to check for existenceGravatar Berthold Stoeger
Don't change into a directory just to see if it exists. Remove unnecessary braces of one of the changed if statements. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-12-04Fix typo "LastIamgeDir"->"LastImageDir"Gravatar Berthold Stoeger
This fixes an actual bug, where the current image dir would only be remembered on closing the program. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2017-10-26Divelistview: use report_error to report and errorGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-10-23Fix broken multi selected dive to tripGravatar Jan Mulder
See referenced issue number. It leads back to an ancient (3 year old) commit 512c42e. Not sure this issue is introduced there, but that's not relevant. Key in reproducing this is the location where the context menu is requested (using the right mouse button). When it is the row next to the trip, the add-to-trip succeeds correctly, otherwise it is a no-op. The solution is rather trivial (in hindsight). Just loop over the selected dives, and try to find the trip we want to add to. Fixes: #522 Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2017-10-03dive-list: maintain a single instance of DiveTripModelGravatar Lubomir I. Ivanov
A weird crash occurs if DiveListView creates another local instance of DiveTripModel inside reload(). Re-use the member variable tripModel and assign it a new instance of DiveTripModel. Reported-by: Gaetan Bisson <bisson@archlinux.org> Tested-by: Gaetan Bisson <bisson@archlinux.org> Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2017-10-03divelist: prevent a crash for missing column widthGravatar Lubomir I. Ivanov
The `static int defaultWidth[]` definition in divelistview.cpp could potentially end up missing an element which can later result in out-of-bounds access when iterating through the list of columns and updating their widths. Add a couple of methods in DiveTripModel for setting and getting the widths and use those. The default values are now pre-set in a QVector in the DiveTripModel() constructor. Throw warnings if out-of-bounds columns are requested. Reported-by: Gaetan Bisson <bisson@archlinux.org> Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2017-05-06File selector should filter images we can actually handle.Gravatar Robert C. Helling
So better ask Qt about image formats known to it. Signed-off-by: Robert C. Helling <helling@atdotde.de>
2017-04-29Fix call to tr in order to create translation stringsGravatar Dirk Hohndel
Fixes #365 Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2017-04-29Add SPDX header to desktop widgetsGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>