A LibraryBackend may be deleted while an associated LibraryModel object is using
it. An example is an async query running while a connected device is removed.
To prevent this, use a share pointer for the LibraryBackend.
This fixes one case where LibraryBackend is used after deletion. However, the
raw pointer is still passed around in several other places. These should be
evaluated on a case-by-case basis to insure that circular depencencies aren't
introduced.
Add an "Advanced Settings" option to the gpodder sign in. If selected, a fully
qualified URL must be specified as the gpodder base. Upon successful login, the
URL is saved along with username and password. If advanced settings are not
selected, an empty URL is stored and the default will be used.
It's not necessary for the PodcastSettingsPage class to have knowledge of
GPodderSync's login implementation. Handling the network reply in a single
location sightly simplifies the code. It also makes the handling order
more deterministic.
A sessionid cookie is stored when logging in to gpodder. After logging out, a
subsequent login with the same user name but incorrect password will succeed,
ignoring the authorization header. The incorrect password will be stored for
future use.
To fix this, reset the cookie jar for GPodderSync's network access manager at
logout.
A closure created by NewClosure that handles Qt signals is destroyed if the
signal object is destroyed, the slot object is destroyed, or the signal is
invoked. In the case where the sender is passed as a shared pointer, the
reference prevents the sender from being destroyed before the closure.
So for closures built to handle responses returned from ApiRequest in
GPodderSync, the closure object and the response object will only be destroyed
after the signal is invoked. In some cases, separate closures are built for
error signals as well. For these, only one closure will be destroyed. The other
closures and the response object will be leaked.
A simple fix for the success cases is to remove the unnecessary error case
closures and directly connect the signals to slots. This is low hanging fruit
and still leaves leaks in the error cases. Those cases will require a more
complete solution to properly manage the life cycle of the response object.
* Display podcast episode information.
Add an EpisodeInfoWidget with title, author, duration, date, and description fields. Include this in the PodcastInfoDialog. If exactly one episode is selected, then show both the podcast and episode widgets and display the episode's URL. Otherwise, hide the episode widget and follow the existing behavior. Note that the desription field for the EpisodeInfoWidget uses the QLabel and does not currently download embedded images.
Add an always_show_hours option to the PrettyTime methods to include hours in formatting even if the field is zero. This is less ambiguious in some cases where duration is displayed.
* Apply patch from automated formatter test.
* Add option to verify subsonic server certificate.
Defaults to true, as it is safer to have a server certificate verified,
even more so, if the server is used over an insecure WAN link.
During subsonic configuration the checkbox can be deactivated, so that
no certificate verification will occur when talking to a subsonic
server, allowing for self-signed certificates.
With the proliferation of let's encrypt certificates there's probably
less need for this option but it has been requested and hard-coding
verify-off is IMHO bad security practice.
If a valid certificate has been installed, the configuration file can be
modified manually and after a restart Clementine will perform a proper
server certificate verification.
The patch might need some UI polishing and asks for string translations
but is operational so far.
* Satisfy CLang format checker.
* Use QSettings' default value support.
* Consistently use QSettings' default value method.
Qt's QUrl parser does no longer accept pure numeric hostnames without
trying to make a dotted IPv4 address of them.
Thus current method of storing subsonic's numeric ids in the host part
of a QUrl ("subsonic://<id>") does no longer work.
Instead a query is constructed omitting the host-part entirely and using
"subsonic://?id=<id>" to store and retrieve subsonic titles.