aboutsummaryrefslogtreecommitdiffstats
path: root/desktop-widgets
AgeCommit message (Collapse)Author
2021-04-02desktop: query DivePlannerPointsModel for planner stateGravatar Berthold Stoeger
MainTab::updateDiveInfo() is not executed when in the planner. To decide whether the application is in the planner state, it queried the profile. Instead, query the DivePlannerPointsModel. Currently, there is no autoritative carrier of that flag. However, the MainTab has a dependency on DivePlannerPointsModel anyway, and therefore this removes a dependency on the profile. This brings us closer to a state where we can have multiple profiles. Ultimately, it is hoped that the whole check can be removed at this place, making the point moot. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: set profile to planner state in main windowGravatar Berthold Stoeger
Remove mainwindow-access from the planner, by setting the profile to planner state in the owner of the profile, viz. the MainWindow. The MainWindow sets the application state to planner, so it seems legit that it also sets the profile state. This removes a further interdependency. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02desktop: remove check for editMode in maintabGravatar Berthold Stoeger
The accept / reject message is only shown in edit-mode, no need to check it. This is a step in simplification / removal of the edit mode. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02profile: display arbitrary diveGravatar Berthold Stoeger
So far the profile operated on the global displayed_dive. Instead, take the dive to be displayed as a parameter to the plotDive() functions. This is necessary if we want to have multiple concurrent profile objects. Think for example for printing or for mobile where multiple dive objects are active at the same time. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: remove displayed_dive from DivePlannerModelGravatar Berthold Stoeger
To remove global state, make the dive that DivePlannerModel works on a member variable. Pass the dive in createSimpleDive() and loadFromDive(). Moreover, this should pave the way to more fine-grained undo in the planner. Ultimately, the planner should not be modal. Attention: for now, the dive must still be displayed_dive, because of the convoluted way in which the profile and the planner work on the same dive. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: move clearing of model into loadFromDive() functionGravatar Berthold Stoeger
Both loadFromDive() callers were clearing the model before calling loadFromDive(). Move the clearing into that function since it makes no sense to load into a non-cleared model. Apparently this changes the way that no-cylinder dives are treated and the code in ProfileWidget2::repositionDiveHandlers() must now explicitly check for that condition. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02profile: pass DivePlannerPointsModel at construction timeGravatar Berthold Stoeger
This model is only needed when in plan mode. To enable multiple profilewidgets at the same time (e.g. for the mobile app or for printing), make the pointer to DivePlannerPointsModel a member variable that is initialized at construction time. Moreover, allow passing null as the DivePlannerPointsModel, in which case planning will be disabled. This will be useful for simple printing. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02cleanup: add DivePlannerPointsModel::addDefaultStop() functionGravatar Berthold Stoeger
When clicking on "+" in the planner, a default stop point was added using a signal/slot connection. This used the archaic string-based connect syntax, because it was realized with default parameters passed to "addStop()". Instead, add a "addDefaultStop()" slot, which passes the default parameters. Since all other callers do not use callbacks, unslotify "addStop()". The slot was the only user of the default parameters, so they can be removed alltogether. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02printing: use sensible font-size in profilesGravatar Berthold Stoeger
The font-size in printed profiles is based on the size of the profile in the main window. This makes no sense. Why should changing the window size change the font-size on printouts? Matter of fact, when making shrinking the height of the window to its minimum, comical printouts are obtained (font way too big). Therefore use an arbitrary rule: Say that profiles 600 pixels high look reasonable and then scale up to the actual size on the printout. This may need some tweaking for high-DPI mode. But that seems not to be supported on desktop anyway? Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-03-31stats: fix visibility check of the statistics tab on desktopGravatar Berthold Stoeger
Apparently, the visibility flag of the view is not inherited from the statistics widget. Therefore, the statistics is redrawn on every action even if not visible. Set the visibility explicitly in the show- and hide-events. This is crazy. 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-17planner: pass in_planner down to TemplateLayoutGravatar Berthold Stoeger
The TemplateLayout prints different dives depending on whether the planner is active. Instead of accessing a global variable, pass the status down from the MainWindow. That's all quite convoluted, since there are multiple layers involved. On the positive side, the in_planner() function has now no users an can be removed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-17cleanup: remove unused includes in mainwindow.cppGravatar Berthold Stoeger
The printing code moved elsewhere, so these includes are not needed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13statistics: implement primitive "restrict to selection" featureGravatar Berthold Stoeger
Allow the user to restrict the analyzed dives based on the current selection. One button restricts to the current selection and one button resets the restriction. Thus, the user can for example select bars in the bar chart or a range in the scatter plot and perform statistics on these sets. The restriction works on top of the filter. The UI can certainly be improved, but it is a start. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-13printing: "fix" progress indicatorGravatar Berthold Stoeger
In TemplateLayout, there was a progress indication, which reported the progress - not of the actual rendering - but of adding the dives to the "to render" list. Which is of course done in less than a ms, making the whole thing completely pointless. Instead, emit progress when actually looping over the dives or statistics. Nobody ever noticed the problem because even rendering is done in fractions of a second and indeed is accounted to only one fifth of the total progress. The real purpose of this "fix" is to get rid of the getTotalWork() function, which was just insane. Instead of asking the TemplateLayout how many dives it rendered, this number was extracted from global state. Simply store the number of dives in the TemplateLayout object instead. Moreover, fix two coding style issues: - "Page" variable identifier starting with a capital - The Printer::render() being defined (as opposed to declared) with a default parameter. This is not how C++'s default parameters work, sorry. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-10desktop: disable animation when selecting multiple divesGravatar Berthold Stoeger
Selecting many dives when the animation was active was increadibly slow, so disable it. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-06desktop: improve splitter defaultsGravatar Berthold Stoeger
On first startup, use the splitter values suggested by Dirk: Top/Bottom: 60/40 Info/Profile: 50/50 List/Map: 60/40 Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-02-06profile: detect dive-mode change in profileGravatar Berthold Stoeger
The profile must be replotted when the dive mode changes. Weirdly, this was routed via the dive-information tab (making it inherently non-mobile compatible). Detect such a change directly in the profile. 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: don't access profile directly to redraw itGravatar Berthold Stoeger
The MainWindow has a function to replot the profile. Use that instead of accessing the profile directly. 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-20planner: remove DivePlannerPointsModel::startTimeChanged signalGravatar Berthold Stoeger
The way the starting time of a new plan was set was bonkers: 1) PlannerWidgets::planDive() invokes DivePlannerPointsModel:: createSimpleDive(). 2) createSimpleDive() calls DivePlannerPointsModel:: setupStartTime() 3) setupStartTime() emits a signal startTimeChanged() 4) startTimeChanged is caught by PlannerWidget and sets the UI field 5) change of the UI field emits a timeChanged() signal which is connected to DivePlannerPointsModel::setStartTime() 6) setStartTime() sets the time of the plan and displayed_dive and emits dataChanged() 7) dataChanged() replots the dive() 8) Back in DivePlannerPointsModel::createSimpleDive() the diveplan start time is overwritten with displayed_dive (the value are equal owing to 6) Wow! But it gets worse: 9) The initial dive plan is set up in createSimpleDive(). Since the profile is drawn in 7) after clearing the displayed_dive and before constructing the initial plan, the profile is shown on a dive without samples. It therefore generates a dummy profile. To make this somewhat less insane, remove the startTimeChanged() signal in 3), explicitly set the start time of plan and dive to the one calculated by setupStartTime() and explicitly set the UI filed in the plannerWidget. This still indirectly draws the profile via signals in a convoluted way, but at it straightens out things somewhat. Most importantly, the profile doesn't have to generate a fake DC. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: don't replot chart when changing featuresGravatar Berthold Stoeger
Up to now, when the user changed the visibility of chart features (legend, quartiles, labels, etc.) the whole chart was replot. Instead, only change the visibility status of these items. After all, this modularity is one of the things the conversion to QSG was all about. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-20statistics: turn ChartGrid into QSGNodesGravatar Berthold Stoeger
Turn the background grid into QSGNodes. Each grid line is represented by a QSG line item. An alternative would be drawing the grid into a QImage and blasting that onto the screen. It is unclear which one is preferred. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-19mobile: add GF fields for ceiling calculationGravatar Doug Junkins
Adds fields to the advanced preferences page to modify GFLow and GFHigh for the Buhlmann decompression model for calculating ceilings. Updated preferences code to set the Buhlmann parameters in core/deco.c when the GF prefs are updated. Signed-off-by: Doug Junkins <douglas.junkins@gmail.com>
2021-01-11undo: remove invalidate_dive_cache call from MainTabGravatar Berthold Stoeger
When creating the RenumberDive undo command, the MainTab would manually call invalidate_dive_cache(). However, this is done on undo/redo, therefore the call can (should) be removed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10profile: remove ProfileWidget2::dateTimeChanged()Gravatar Berthold Stoeger
This function sent a signal and the only listener was removed in the previous commit. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-10statistics: convert chart to QQuickItemGravatar Berthold Stoeger
It turns out that the wrong base class was used for the chart. QQuickWidget can only be used on desktop, not in a mobile UI. Therefore, turn this into a QQuickItem and move the container QQuickWidget into desktop-only code. Currently, this code is insane: The chart is rendered onto a QGraphicsScene (as it was before), which is then rendered into a QImage, which is transformed into a QSGTexture, which is then projected onto the device. This is performed on every mouse move event, since these events in general change the position of the info-box. The plan is to slowly convert elements such as the info-box into QQuickItems. Browsing the QtQuick documentation, this will not be much fun. Also note that the rendering currently tears, flickers and has antialiasing artifacts, most likely owing to integer (QImage) to floating point (QGraphicsScene, QQuickItem) conversion problems. The data flow is QGraphicsScene (float) -> QImage (int) -> QQuickItem (float). Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-01-06desktop/update-check: fix logic when to ask about update checkGravatar Dirk Hohndel
Checking a field that we intentionally don't store to disk is obviously wrong. It's been this way for a long time and it has annoyed me many times, but somehow I never spent the time to track down why this was happening. It makes much more sense to use the presence of either the don't check flag or a next check date as an indication that we have already asked this question. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-06desktop/UI: move statistics to View menuGravatar Dirk Hohndel
It seems to make more sense to have it there with the 'Yearly Statistics' and not in the Log menu. Interestingly enough, both locations were clearly considered when first adding this in commit 106f7a8e0e ("desktop: add statistics widget dummy and application state") as you can tell by the never implemented actionViewStats. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-06dekstop/UI: remove duplicate resourceGravatar Dirk Hohndel
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-06desktop/UI: add shortcut for 'Open cloud storage'Gravatar Dirk Hohndel
This seems like a logical extension of the shortcuts we already have. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-03desktop: rename Statistics tab to SummaryGravatar Dirk Hohndel
We now have three different things that are kinda like statistics: - the summary tab (reasonably useful when looking at selected dives) - the yearly statistics (Ctrl/CMD-Y) - the full statistics (Ctrl/CMD-T) I'd argue that's at least one too many. But I'm sure some people will disagree. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-01-03statistics: reverse chart selection logicGravatar Berthold Stoeger
The old ways was to select the chart first, then depending on the chart choose the binning. Willem says that it should work the other way round: select the binning (or operation) and make the charts depend on that. I'm not arguing one way or the other, just note that the new way is much more tricky, because it is easy to get unsupported combinations. For example, there is no chart where the first variable is unbinned, but the second axis is binned or has an operation. This makes things distinctly more tricky and this code still needs a thorough audit. Since this is all more tricky, implement a "invalid" chart state. Ideally that should be never shown to the user, but let's try to be defensive. 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-03statistics: implement a statistics widget on desktopGravatar Berthold Stoeger
Implement a widget that shows the statistics state as comboboxes and the statistics chart. Calls into the statistics code if any of the comboboxes changes. The hardest part here is the formatting of the charts list with its icons and with headings. Sadly, it is not trivial to arrange icons horizontally. Therefore we would have to fully reimplement the ComboBox view, which is probably not fun. 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-29cleanup: remove getDivesInTrip() in qthelper.cppGravatar Berthold Stoeger
This function was not used anywhere. Moreover, remove a few unused includes from qthelper.h. Surprisingly, a number of users of qthelper.h depend on these, so readd them at the appropriate places. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17printing: remove CylinderObjectHelperGravatar Berthold Stoeger
With the removal of grantlee, this became pointless glue code. Call the formatting functions directly. Since the printing code was the only user of CylinderObjectHelper, remove the whole thing. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17printing: remove DiveObjectHelper from printing codeGravatar Berthold Stoeger
At this point (post grantlee), DiveObjectHelper is just pointless glue code. Let's remove it from the printing code and call the formatting functions directly. If necessary, move these functions to core/string-format.cpp. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17printing: remove DiveObjectHelperGrantleeGravatar Berthold Stoeger
This was a weird helper object, needed for grantlee. Instead of storing this object, loop over cylinders and dives directly. The actual accessor function is unchanged and now generates a DiveObjectHelper or DiveCylinderHelper for every variable access. Obviously, this is very inefficient. However, this will be replaced in future commits by direct calls to formatting functions. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17cleanup: remove QPointer instancesGravatar Berthold Stoeger
QPointer is a strange "smart" pointer class, which resets itself when the pointed-to QObject is deleted. It does this by listening to the corresponding signal and therefore is surprisingly heavy for a plain pointer. A cynic would say that the existence of QPointer is an expression of Qt's broken ownership model. In any case, QPointer was only used at two places, were it was 100% useless: As a parameter to a function and as a locally scoped pointer. It only makes sense if a) there is a chance that the object disappears during the pointer's lifetime and b) it is actually checked for null before use None of which was the case here. Remove. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17printing: move #includes from headers to source filesGravatar Berthold Stoeger
To decrease include-file interdependencies. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17printing: remove YearInfo structureGravatar Berthold Stoeger
This is a wrapper around "stats *" used to pass statistics through Qt's weird metatype system. Not needed anymore. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17printing: refactor if and loop codeGravatar Berthold Stoeger
The loop code was buggy: the current position was only increased inside when executing the loop once. This would obviously fail for empty lists. Moreover, the whole thing was quite difficult to reason about, since a reference to the current position was passed down in the call hierarchy. Instead, pass from and to values to the parse function and create a generic function that can search for the end of loop and if blocks. This function handles nested if and for loops. The if-code now formats the block only if the condition is true. The old code would format the block and throw it away if not needed. This should now provide better diagnostics for mismatched tags. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17printing: remove objects QVariant mapGravatar Berthold Stoeger
An artifact from the old grantlee code: the whole parser state was kept in an untyped QVariant map. One case was particularly bizarre: the options were a class member and yet added to the weird map. Replace this by a strongly typed state structure. Ultimately, this will allow us to replace the "dive object helper". Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2020-12-17cleanup: make templateOptions and printOptions reference typesGravatar Berthold Stoeger
These two structs describe options used during printing. They are passed through numerous classes as pointer. In this case, reference semantics are preferred, as references: - can never be null - can not change during their lifetime This not only helps the compiler, as it can optimize away null checks, but also your fellow coder. Moreover, it prevents unintentional creation of uninitialized references: one can't create an instance of a class without initializing a reference member. It does not prevent references from going dangling. However, pointers have the same disadvantage. Contains a few whitespace cleanups. 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>