aboutsummaryrefslogtreecommitdiffstats
path: root/desktop-widgets
AgeCommit message (Collapse)Author
2021-07-23cleanup: replace membuffer by membufferpp in C-codeGravatar Berthold Stoeger
Thus, the membuffer data is automatically freed when going out of scope - one thing less to worry about. This fixes one use-after-free bug in uploadDiveLogsDE.cpp and one extremely questionable practice in divetooltipitem.cpp: The membuffer was a shared instance across all instances of the DiveToolTipItem. Remves unnecessary #include directives in files that didn't even use membuffer. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-07-23desktop: explicitly enable shortcutsGravatar Dirk Hohndel
The changes in commit 4daf687876 ("profile: remove [disable|enable]Shortcuts() signals") resulted in us no longer enabling the shortcuts on the desktop (at least on macOS where I debugged this). This placement of the call feels like a bit of overkill, but at least it shouldn't be wrong. Fixes #3293 Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-07-07cleanup: remove Printer::dpi member variableGravatar Berthold Stoeger
This variable is not used outside a single function, where it is reset every time the function runs. This can be realized by a function-local variable just as well. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-07-03Handle dives with no samplesGravatar Robert C. Helling
This occurs upon importing dives for example via CSV. Make sure the profile display is cleared when selecting such a dive rather than showing a different dive. Allow editing the profile for such a dive. Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-07-03profile: rename ADD state to EDIT stateGravatar Berthold Stoeger
The ADD state is not used for adding dives since adding dives was made undoable. Therefore, rename it to EDIT state, since that is what it is used for. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-07-03cleanup: update copyrightsGravatar Dirk Hohndel
That should have been done six months ago. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-07-03cleanup: remove long obsolete codeGravatar Dirk Hohndel
We have stopped playing with beta versions many many years ago. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-06-04desktop: add numerus translation for dive context menuGravatar Mark Stiebel
Add numerus translation lookup for the right-click context menu in the dive list to show proper singular/plural text. Fixes #3256 Signed-off-by: Mark Stiebel <mark@aretha.stiebel.me> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-05-19desktop: Add the capability to copy / paste dive number and date / time.Gravatar mikeller
This is adding the capability to select 'Dive number' and 'Date / Time' in the 'Copy dive components' dialog, and then copy them into the clipboard. When using 'Paste dive components, these values will then be pasted into the selected dive(s). This is intended to help with workflows that import dive information from two different sources, like general information from another logging program, and CCR ppO2 sensor readings from a unit log, and then stitch them together into one cohesive entry with all data per dive. Copied data is also output into formatted text when pasting the clipboard outside of the application: ``` Dive number: 401 Date / time: Sun 2 May 2021 12:00 AM ``` No translations have been added as of now - I could not find any information on how strings are translated for this project. Signed-off-by: Michael Keller <github@ike.ch>
2021-05-17cleanup: remove double layout name in statswidget.uiGravatar Berthold Stoeger
This gave an annoying warning. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-05-13Translate header strings for APDGravatar Robert C. Helling
We are matching translated header names. Thus, when composing a header line for APD, make sure it contains translations. This mechanism is quite brittle. Our German translations had two different translations for "Sample time" and this already broke it. This is why this patch also includes a fix for a translation string (should be fixed in transiflex as well of course). Fixes #3246 Signed-off-by: Robert C. Helling <helling@atdotde.de>
2021-05-06cleanup: free print dialog in plannerGravatar Berthold Stoeger
When printing the plan, a print-dialog was created with "new", but not freed later. Strictly speaking, this is not a leak, because the dialog is attached to the main-window in Qt's object hierarchy. Thus it is freed on application exit. On the other hand, it is a leak in the sense that resources are pointlessly hogged until application exit. Let's just turn it into a stack-allocated object. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-05-06export: show progress dialog for profile exportsGravatar Berthold Stoeger
Simply reuse QProgressDialog interface for the TeX exports. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-05-06export: show progress dialog for TeX exportsGravatar Berthold Stoeger
The TeX exports may hang the UI for a long time. Show a progress-dialog that is updated after every exported dive and allows the user to cancel the export. This is pretty lame, because it is synchronous (export still runs in UI thread) and therefore the UI still is sluggish. But it is an improvement. Since the TeX-exporting code is in a shared directory (desktop and mobile), this uses a slim interface class. Mobile does not yet use TeX export, but you never know. Better than #ifdefs sprinkled all around, I reckon. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-05-06export: remove redundant QString::isNull() checksGravatar Berthold Stoeger
If QString::isEmpty() is false, QString::isNull() is likewise false, so these tests are redundant. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-25profile: ignore animation-speed setting when printingGravatar Berthold Stoeger
When printing, the animation speed was set to 0 by the caller and later reset to the original value. Instead of modifying global state, set it internally (in the profile-code) to zero when in print mode. This is another small step in making the printing independent from the shown profile. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-21cleanup: remove MainWindow::turnOffNdlTts()Gravatar Berthold Stoeger
This flag is handled directly by the profile code since 2015 (000c9cc21c8991682169987ae8f348243ec5008b). The function therefore can be removed. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-19cloudstorage: try to pick between multiple cloud serversGravatar Dirk Hohndel
The backend infrastructure will soon be able to support more than one cloud server which automagically stay in sync with each other. One critical requirement for that to work is that once a session was started with one of the servers, the complete session happens with that server - we must not switch from server to server while doing a git transaction. To make sure that's the case, we aren't trying to use DNS tricks to make this load balancing scheme work, but instead try to determine at program start which server is the best one to use. Right now this is super simplistic. Two servers, one in the US, one in Europe. By default we use the European server (most of our users appear to be in Europe), but if we can figure out that the client is actually in the Americas, use the US server. We might improve that heuristic over time, but as a first attempt it seems not entirely bogus. The way this is implemented is a simple combination of two free webservices that together appear to give us a very reliable estimate which continent the user is located on. api.ipify.org gives us our external IP address ip-api.com gives us the continent that IP address is on If any of this fails or takes too long to respond, we simply ignore it since either server will work. One oddity is that if we decide to change servers we only change the settings that are stored on disk, not the runtime preferences. This goes back to the comment above that we have to avoid changing servers in mid sync. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
2021-04-19cloudstorage: some cleanup of cloud url handlingGravatar Dirk Hohndel
We know the preference is never empty, so stop testing for this. But don't maintain two different preferences with basically the same content. Instead add the '/git' suffix where needed and keep this all in one place. Simplify the extraction of the branch name from the cloud URL. Also a typo fix and a new comment. Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
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 force parameter from ProfileWidget2::plotDive()Gravatar Berthold Stoeger
The last user was removed in 2789bb05b133a7cf54081d58d4f5c51c8977e951. 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-04-02profile: populate dive handlers when switching to edit/plan modeGravatar Berthold Stoeger
The dive handlers are only updated by signals. This means that switching into edit-mode has to be done in steps: 1) initialize the DivePointsPlannerModel 2) switch profile mode 3) load dive into DivePointsPlannerModel 2) and 3) cannot be exchanged, or the dive handlers are not initialized. To avoid this sandwitching of profile- and model-initialization, populate the dive handlers when switching the profile mode. Thus, the profile can be switched into edit/plan mode when the DivePointsPlannerModel is fully initialized. This will be important in upcoming commits, when the initialization of the dive is moved from the profile to the DivePointsPlannerModel. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
2021-04-02planner: remove DivePlannerPointsModel::setRecalc()Gravatar Berthold Stoeger
The only external user of setRecalc() was turning recalculation on. In fact, this happened when constructing the planner-widget. However, for example editing of the profile only works when the recalc flag is on. This is all very confusing, let's just turn the flag on by default and remove the accessor. Internally, the planner can simply use the std::exchange function to set and reset the recalc flag. Perhaps the setting/resetting can be replaced by simple recalc = true; ... recalc = false; pairs. It is unclear whether there is need for recursion. Something to be investigated. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>