presentation/PlaceLookupSource.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <QList> | ||
| 4 | #include <QNetworkReply> | ||
| 5 | #include <QObject> | ||
| 6 | #include <QPointer> | ||
| 7 | #include <QString> | ||
| 8 | #include <QUrl> | ||
| 9 | |||
| 10 | class QNetworkAccessManager; | ||
| 11 | |||
| 12 | class QTimer; | ||
| 13 | |||
| 14 | // Online lookup of street addresses (Sprint 103 S103.1.9, D-10; opt-in in | ||
| 15 | // Settings › Privacy, or one confirmed request from a card). Follows the | ||
| 16 | // Nominatim usage policy: at most one request per second, one at a time, a | ||
| 17 | // MailJD User-Agent, results cached by the caller (place_cache), no bulk | ||
| 18 | // prefetching beyond the user's own addresses. Only the address text is | ||
| 19 | // sent (structured street/postalcode/city/state/country, or a free text for | ||
| 20 | // met places) — never names. No cookies, credentials or redirects. | ||
| 21 | // | ||
| 22 | // The server is an https base URL ("/search" is appended); plain http is | ||
| 23 | // accepted only for loopback hosts (tests). Fetched by C++ only. | ||
| 24 | class PlaceLookupSource final : public QObject { | ||
| 25 | 2 | Q_OBJECT | |
| 26 | |||
| 27 | public: | ||
| 28 | static constexpr int IntervalMs = 1000; | ||
| 29 | static constexpr qint64 MaxReplyBytes = 256 * 1024; | ||
| 30 | |||
| 31 | struct Query { | ||
| 32 | QString street; | ||
| 33 | QString postalCode; | ||
| 34 | QString locality; | ||
| 35 | QString region; | ||
| 36 | QString country; | ||
| 37 | QString text; // free text (a met place) when the fields are empty | ||
| 38 | }; | ||
| 39 | struct Result { | ||
| 40 | bool answered = false; // false: offline, refused or unreadable (retry later) | ||
| 41 | bool found = false; | ||
| 42 | double latitude = 0; | ||
| 43 | double longitude = 0; | ||
| 44 | QString precision; // "exact", "city", "region", "country" | ||
| 45 | QString placeName; | ||
| 46 | }; | ||
| 47 | |||
| 48 | explicit PlaceLookupSource(QObject *parent = nullptr); | ||
| 49 | ~PlaceLookupSource() override; | ||
| 50 | |||
| 51 | // https://nominatim.openstreetmap.org | ||
| 52 | static QString defaultServer(); | ||
| 53 | // "" when `server` is usable, else why not (for the settings field). | ||
| 54 | static QString validate(const QString &server); | ||
| 55 | // The request for `query` (also the example in the consent text). | ||
| 56 | static QUrl requestUrl(const QString &server, const Query &query); | ||
| 57 | // Nominatim's jsonv2 answer → a result (exposed for tests). | ||
| 58 | static Result parse(const QByteArray &json); | ||
| 59 | |||
| 60 | void setServer(const QString &server); | ||
| 61 | 42 | QString server() const { return m_server; } | |
| 62 | // Queues a lookup; `id` identifies it in `finished` (a queued id is not added twice). | ||
| 63 | void lookup(const QString &id, const Query &query); | ||
| 64 | void cancelAll(); | ||
| 65 | // S106-284: drops the queued and the running lookups whose id starts with | ||
| 66 | // `prefix` (the background ones on opt-out); the others stay queued. | ||
| 67 | void cancelMatching(const QString &prefix); | ||
| 68 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 9 times.
|
9 | int queued() const { return int(m_queue.size()) + (m_active ? 1 : 0); } |
| 69 | 3 | int requestsStarted() const { return m_requestsStarted; } | |
| 70 | |||
| 71 | signals: | ||
| 72 | // A request left for the server (the moment the usage policy paces). | ||
| 73 | void requestStarted(const QString &id); | ||
| 74 | void finished(const QString &id, const PlaceLookupSource::Result &result); | ||
| 75 | |||
| 76 | private: | ||
| 77 | struct Pending { | ||
| 78 | QString id; | ||
| 79 | Query query; | ||
| 80 | }; | ||
| 81 | void pump(); | ||
| 82 | void done(QNetworkReply *reply, const QString &id); | ||
| 83 | |||
| 84 | QNetworkAccessManager *m_network = nullptr; | ||
| 85 | QTimer *m_pace = nullptr; | ||
| 86 | QString m_server; | ||
| 87 | QList<Pending> m_queue; | ||
| 88 | QPointer<QNetworkReply> m_active; | ||
| 89 | QString m_activeId; | ||
| 90 | int m_requestsStarted = 0; | ||
| 91 | }; | ||
| 92 |