aboutsummaryrefslogtreecommitdiffstats
path: root/desktop-widgets/mainwindow.h
AgeCommit message (Collapse)Author
2021-04-10profile: remove enableToolbar() signalGravatar Berthold Stoeger
When showing the "empty-state", the profile toolbar was disabled. This was done via a "reverse" signal from the profile to the MainWindow. Instead control the toolbar in the MainWindow directly. Break out the plot-dive functionality into a member function and there test whether a dive is shown or not. The signal makes no sense in the context of mobile or printing. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-10profile: remove [disable|enable]Shortcuts() signalsGravatar Berthold Stoeger
When switching to the "plan" or "add" (which should rather be called "edit", by the way) mode of the profile, the "shortcuts" for copy&paste, undo&redo, etc. are disabled. When switching to "profile" mode, they are reenabled. This was done in a most convoluted way: - The MainWindow calls the set*State() function of the profile. - The Profile emits [disable|enable]Shortcuts() signals. - The MainWindow catches these signals and does the enabling or disabling. Not only is this very hard to reason about, it is also in contradiction to the profile being part of the display layer. Moreover, in editCurrentDive() the MainWindow disabled the shortcuts itself, so this was all redundant. For the sake of sanity, let's just move this logic to the MainWindow, unslotify the [disable|enable]Shortcuts() functions and make them private. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-17desktop: fold ApplicationState into MainWindowGravatar Berthold Stoeger
The application state is a desktop-only thing. The mobile UI also has its application state, but that is something completely different. The last remaining user of the application state was to flag whether the planner is active. Since this has all been unglobalized, the ApplicationState structure can be moved from core to the desktop UI. And there it can be made local to the MainWindow class. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-06desktop: be smarter about filling splittersGravatar Berthold Stoeger
On state change, the splitters were completely emptied and refilled. Instead try to reuse already existing splitter slots. This reduces annoying flickering. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-06desktop: do own memory management of quadrant widgetsGravatar Berthold Stoeger
The memory management of the quadrant widgets is a total mess: When setting the widget, the QSplitters take ownership, which means that they will delete the widget in their destructor. This is inherently incompatible with singletons, which must not be deleted. To avoid all these troubles, remove the widgets from the QSplitters in the desctructor of the MainWindow. This of course means that we now have to take care about deletion of the widgets. For local widgets use std::unique_ptr, for singletons use a static variable that is deleted on application exit. Sadly, for the map widget we can't use a normal singleton, because the QML MapWidget's memory management is buggy. Add a comment in the source code explaining this. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-06desktop: don't allow view change in plannerGravatar Berthold Stoeger
When in planner mode, don't allow the user to change the application state. This brought us nothing but troubles and inconsistencies. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-06desktop: remove the view-stateGravatar Berthold Stoeger
There was the "application state", which decided what to show in the "quadrants" and the "view state" which decided which quadrant to show. These interacted in a hard-to-grasp way. The "view state" is used to show the map or dive list in full screen. I simply couldn't get these two orthogonal states to interact properly. Moreover the thing was buggy: If a quadrant was hidden, the user could still show it, by dragging from the side of the window, at least under KDE. To solve these woes, merge the two states into a single application state. If the widget of a quadrant is set to null, don't show it. So the four "view states" are now "application states" where three of the four quadrants are not shown. This also changes the memory management of the widgets: widgets that are not shown are now removed from the QSplitter objects. This makes it possible that the same widget is shown in *different* quadrants. While writing this, I stumbled upon a Qt bug, which is known since 2014: https://forum.qt.io/topic/43176/qsplitter-sizes-return-0 When restoring the quadrant sizes there was a test whether the quadrant size is 0. If that was the case, a default size was set. This seems not to work if the widgets were recently added. Since this test now always fails, make the quadrants non-collapsible and thus guarantee that 0 is never saved as a size. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-03desktop: add statistics widget dummy and application stateGravatar Berthold Stoeger
Add a new "statistics" application state. In the statistics state show the statistics widget and the filter in the top quadrants. The idea is to allow filtering and doing statistics at the same time. Sadly, we can't use the filter-widget in different quadrants, because Qt's ownership model is completely broken / inflexible. It does not support a widget having different parents and thus a widget can only belong to one QStackedWidget. Hiding the map in the statistics view is quite hacky: Since the view of the quadrants is not determined by the "ApplicationState", we have to restore the original quadrant visibility when exiting the stats mode. Therefore, set the original visibility-state when changing application state. The MainWindow-quadrant code really needs to be rewritten! Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-01cleanup: remove "GpsLocation *locationProvider" from MainWindowGravatar Berthold Stoeger
This is mobile only and not used on desktop. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-13cleanup: remove MainWindow::stateBeforeEdit memberGravatar Berthold Stoeger
The last user was removed in accf1fcc8f6ad. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-13cleanup: remove unused typedefsGravatar Berthold Stoeger
Last users removed in ca6aa3813956b5e8be68b86ed36a5786b3ee746f. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-12desktop: move planner-code to diveplanner.cppGravatar Berthold Stoeger
Around 2015 there was a push to move planner UI code from mainwindow.cpp to diveplanner.cpp. That never was completed, presumably because the planner is actually three widgets. Collect these widgets in one PlannerWidgets class and move the code there. This is not a full dis-entanglement, as the plannerwidgets have to access the profile via the mainwindow. But at least it collects the planner UI code at a single place. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25cleanup: remove MainWindow::setFileClean()Gravatar Berthold Stoeger
This function was used to unify both methods of tracking unsaved changes. Since desktop now only uses the undo system, it can be replaced by a single call to "Command::setClean()". Arguably, the UI is the wrong place to do this and the appropriate calls should be done by the core. However, let's play it safe for now and avoid any breaking change. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-10-25desktop: remove DiveComputerManagementDialogGravatar Berthold Stoeger
This is now done in a TabWidget with undo-support. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-09-29cleanup: rename FilterWidget2 to FilterWidgetGravatar Berthold Stoeger
The name "FilterWidget2" is historical and has no meaning anymore, since the current version has little to nothing to do with the "second" version of the widget. Rename the class and source files accordingly. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-07desktop: don't update models in MainWindow::refreshDisplay()Gravatar Berthold Stoeger
The models should now properly reset themselves if data in the core changes. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-04Planner: fold MainWindow::setupForAddAndPlan into createSimpleDive()Gravatar Berthold Stoeger
There was only one caller of MainWindow::setupForAddAndPlan() left and that caller immediately called DivePlannerPointsModel::createSimpleDive(). Thus, we might just as fold the former in the latter and thus concentrate all the prepare-dive-for-plan business in one place. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-04planner: send plan in calculatedPlanNotesGravatar Berthold Stoeger
Thus, the MainWindow doesn't have to extract the plan from displayed_dive. This is a tiny step in an attempt to detangle the interfaces. The bigger goal will be to make displayed_dive local to the planner. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-05-04planner: update variations in planner not mainwindowGravatar Berthold Stoeger
When calculating variations, they were sent to the mainwindow, which updated displayed_dive accordingly. Do this directly in the planner-model. The idea is to detangle interdependencies and to make the code reusable (planner on mobile?). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-04-19desktop: remove user surveyGravatar Dirk Hohndel
We have never made good use of the results. Let's just remove it. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2020-04-07desktop: remove EDIT modeGravatar Berthold Stoeger
The only way to enter edit mode is to edit the profile. However, that means that the profile is already visible, so there is no need to change the mode. Simply remove the EDIT mode. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-03-07debug: try to capture changes that don't invalidate git cacheGravatar Dirk Hohndel
At least in those cases where we are sending a divesChanged signal we can easily check if the cache was properly invalidated. Of course this won't help in cases where we don't notify the dive list about changes, either. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-11-19Cleanup: remove MainWindow::recreateDiveList() functionGravatar Berthold Stoeger
The function had only one line and had only one caller. We might just as well fold that line into the caller. 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-16Cleanup: fold cleanUpEmpty() into closeCurrentFile()Gravatar Berthold Stoeger
The latter was the only caller of the former and there seems to be no clear separation between the two. By making a single function out of this the code is easier to follow and duplicate code can be more easily detected. Matter of fact, the profile was cleared twice. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-09-27Revert the singleton PRGravatar Dirk Hohndel
It turns out that this isn't working the way it was intended to. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-09-25Cleanup: unify idiosyncratic singletonsGravatar Berthold Stoeger
The way we handle singletons in QML, QML insists on allocating the objects. This leads to a very idiosyncratic way of handling singletons: The global instance pointer is set in the constructor. Unify all these by implementing a "SillySingleton" template. All of the weird singleton-classes can derive from this template and don't have to bother with reimplementing the instance() function with all the safety-checks, etc. This serves firstly as documentation but also improves debugging as we will now see wanted and unwanted creation and destruction of these weird singletons. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-08-08Cleanup: move error reporting function declarations to errorhelper.hGravatar Berthold Stoeger
Move the declarations of the "report_error()" and "set_error_cb()" functions and the "verbose" variable to errorhelper.h. Thus, error-reporting translation units don't have to import the big dive.h header file. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-05-12Mainwindow: simplify application-state codeGravatar Berthold Stoeger
The way the application state would enable/disable widgets was very "dynamic". A property-list would be generated and put in a set of arrays. Very hard to figure out what is going on. Replace these property-list by flags and explicit old-fashioned boolean expressions. Join the two arrays (widget- and property-lists) into an array of a unified data structure. Replace the macro that sets the widgets by a simple static function. Factor out the four loops that added widgets to the quadrants into a simple static function. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-05-12Turn application state into enumGravatar Berthold Stoeger
The application state was encoded in a QByteArray. Thus, there was no compile-time checking. Typos would lead to silent failures. Turn the application state into an enum. Use the enum-class construct, so that the values don't polute the global namespace. Moreover, this makes them strongly typed, i.e. they don't auto-convert to integers. A disadvantage is that the enums now have to be cast to int explicitly when used to index an array. Replace two hash-maps in MainWindow to arrays of fixed sizes. Move the application-state details into their own files. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-05-06Add "Import dive sites" menu to mainwindowGravatar Doug Junkins
Adds "Import->Import dive sites" menu to mainwindow.cpp and adds the on_actionImportDiveSites_triggered() method to prompt for the filename to import from. The files are parsed and then any dive and trip data is cleared before opening a dialog box to select which sites are to be imported. Signed-off-by: Doug Junkins <junkins@foghead.com>
2019-04-14Desktop: destroy maintab before destructing mainwindowGravatar Berthold Stoeger
Apparently, in some Qt-versions the destructor of the base class calls hide on child-objects (according to Qt's object hierarchy). This is obviously called after the derived class has been destructed. In a concrete case, the base class of the destructed MainWindow would hide the TabDiveSite object. That would reset the filtering if a dive site was selected, which would indirectly access the MainWindow, which is already partially destroyed. Therefore, destroy the MainTab before destroying the MainWindow. Do this by keeping it as a std::unique_ptr subobject. Thus, it will be destroyed before the MainWindow and remove itself from Qt's object hierarchy. Reported-by: Dirk Hohndel <dirk@hohndel.org> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-12Undo: use QUndoStack::isClean() to determine unsaved changesGravatar Berthold Stoeger
Properly implement the unsaved-changes flag(s). Since we currently have two kinds of changes, there are two flags: 1) dive_list_changed in divelist.c marks non-undoable changes. This flag is only cleared on save or load. 2) QUndoStack::isClean() is used to determine the state of undoable changes. Every time the user returns to the state where they saved, this flag is cleared. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-12Cleanup: remove unnecessary signalGravatar Berthold Stoeger
The edit dive site button was connected to a *signal* of MainWindow, which was connected to a slot of MainWindow. Remove the unnecessary intermediate signal. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-04-12Dive site: add edit field to dive site tableGravatar Berthold Stoeger
Add an edit column that calls the new editDiveSite() function of MainWindow. The calling code is in DiveSiteSortedModel. Quite illogical, but that's how TableView works, for now. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-02-11Desktop: show filter panel with maximized dive listGravatar Dirk Hohndel
This way we can filter both in the default layout and in the dive list layout. Fixes #1951 Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2019-02-01facebook: remove the featute from the code baseGravatar Lubomir I. Ivanov
Remove from: - unit tests - desktop widgets - preferences - core intergration - cmakefiles - build scripts - icons - docs Also remove the plugins and social network integration. Signed-off-by: Lubomir I. Ivanov <neolit123@gmail.com>
2019-01-26Cleanup: remove unused function setCheckedActionFilterTags()Gravatar Berthold Stoeger
Last caller was removed in e0f473fcb49c8121a0a9c52bf0536049b0f342ed Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2019-01-19Desktop: Make filterWidget2 a subobject of MainWindowGravatar Berthold Stoeger
In commit b0556abdd35f96b816ba11e40bf5707abe0c3ebf, the filter-widget and the filter were connected by a direct function call. This led to a rather obscure crash on application-close with Qt 5.12. The crash is due to the Ui::MainWindow class being a sub-object of MainWindow, but the FilterWidget2 being *not* a subobject. What happens is that after calling the MainWindow destructor, the subobjects are destructed, notably the Ui class. Then the base-class destructor is called (which makes sense, as destructors are called in reverse order of constructors). But: the QObject destructor calls hide() on all still existing child-objects according to Qt's object hierarchy, notably the visible FilterWidget2. Now the FilterWidget2, on hiding, updates the MainWindow, which has already destructed all its subobjects. Crash. Prevent this crash by making FilterWidget2 a subobject of MainWindow and thus have it destructed before running the QObject destructor. Alternative ways would be: 1) Use signal/slot() instead of function calls, as these are automatically removed if an object is destroyed. 2) Make the FilterWidget2 subobject a smart-pointer. Thus, we probably wouldn't have to include the corresponding header. 3) Make the FilterWidget2 subobject a plain pointer and delete it explicitly in the constructor. Reported-by: Jan Mulder <jlmulder@xs4all.nl> 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-14Start the FilterDive stateGravatar Tomaz Canabrava
Register the new FilterDive widget on the mainwindow so we can trigger a shortcut to display it. The shortcut currently doesn't exists. Signed-off-by: Tomaz Canabrava <tcanabrava@kde.org>
2018-10-14Desktop: Enable next/prev DCs only for applicable divesGravatar Jan Mulder
Does not solve any problem, but might help users that are confused about the next/prev DC menu items, to select a different profile for the currently selected dive. So, enable these menu items only for dives where more than one DC is used. Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
2018-10-13Cleanup: rename MainWindow member variablesGravatar Berthold Stoeger
Instead of the weirdly named "information" and the inconsistent "dive_list" use the logical "mainTab" and the camel-cased "diveList", respectively. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-13Cleanup: Turn widget accessor-functions into simple pointersGravatar Berthold Stoeger
The keeps track of different sub widgets needed by other parts of the code, notably: MainTab PlannerDetails PlannerSettingsWidget ProfileWidget2 DivePlannerWidget DiveListView Access to these widgets was provided with accessor functions. Now these functions were very weird: instead of simply returning pointers that were stored in the class, they accessed a data structure which describes the different application states. But this data structure was "duck-typed", so there was an implicit agreement at which position the pointers to the widgets were put inside. The widgets were then down-cast by the accessor functions. This might make sense if the individual widgets could for some reason be replaced by other widgets [dynamic plugins?], but even then it would be strange, as one would expect to get a pointer to some base class. Therefore, directly store the properly typed pointers to the widgets and simply remove the accessor functions. Why bother? Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-10-13Dive site: explicitly init displayed_dive_site on show widgetGravatar Berthold Stoeger
The global object "displayed_dive_site" is used to store the old dive site data for the edit-dive-site widget. The fields of the widget were initialized from this object in the show event. Therefore the object was updated in numerous parts of the code to make sure that it was up-to-date. Instead, move the initialization of the object to the function that also initiatlizes the fields. Call this function explicitly before showing the widget. This makes the data-fow distinctly easier to understand. 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-11Undo: disable undo- and redo-actions in edit modeGravatar Berthold Stoeger
We have to avoid that undo/redo removes the currently edited dive from under our feet. This code can be removed once proper undo/redo (including editing) is implemented. 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-04Import: import Poseidon MkVI logs via DiveLogImportDialogGravatar Berthold Stoeger
Poseidon MkVI logs (.txt) were special cased in MainWindow.cpp, which led to a user-interface inconsistency. In some cases [user chooses ".txt" (non-Poseidon) and ".csv"], *two* import-dialogs were shown. Move handling of Poseidon MkVI logs into DiveLogImportDialog. There are already other "special" cases handled in this dialog. At the moment, this shows the first 10 depth-values, which is kind of useless, as this will all be at surface level. We might think about something more useful. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2018-09-14Desktop: remove "edit dive" from log menuGravatar Jan Mulder
Nowadays, we edit dives just by starting to enter data for the dive. There is no need to explicitly ask to start editing the dive, using the now removed menu option. This was a left-over of a long past history. This is fallout from PR #1673. Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>