Places Backend

Überblick

Die Schnittstelle QPlaceManager, die den Clients den Zugriff auf Ortsinformationen ermöglicht, hängt direkt von einer Implementierung von QPlaceManagerEngine ab. Die Engine stellt die Backend-Funktionsimplementierungen bereit, die vom Manager aufgerufen werden.

Ein Backend-Implementierer muss von QPlaceManagerEngine ableiten und Implementierungen für die virtuellen Funktionen bereitstellen, die für sein Backend relevant sind. Die meisten dieser Funktionen sind asynchron und daher müssen die Implementierer auch die entsprechenden Antwortklassen ableiten. Die Antwortobjekte sind für die Verwaltung einer asynchronen Anfrage verantwortlich; sie werden verwendet, um zu benachrichtigen, wenn eine Anfrage abgeschlossen ist, und um die Ergebnisse dieser Anfrage zu speichern. QPlaceManagerEngine bietet eine Standardimplementierung für alle virtuellen Funktionen. Die Standardimplementierungen für die asynchronen Funktionen geben eine Antwort zurück, die bei der nächsten Iteration durch die Ereignisschleife die Signale errorOccurred() und finished() ausgeben wird.

Implementieren/Verererben von Antwort-Objekten

Ein Antwort-Objekt würde wie folgt vererbt werden:

class SearchReply : public QPlaceSearchReply
{
public:
    explicit SearchReply(ManagerEngine *engine)
        : QPlaceSearchReply(engine), m_engine(engine){}

    ~SearchReply();
    void setResults(const QList<QPlaceSearchResult> &results);
    void setRequest(const QPlaceSearchRequest &request);
    ...
    void triggerDone(QPlaceReply::Error error = QPlaceReply::NoError,
                     const QString &errorString = QString());

    ManagerEngine *m_engine;
};

Die Implementierung eines QPlaceManagerEngine muss sicherstellen, dass alle Signale, die von den Antwortobjekten ausgegeben werden, verzögert werden, bis die Anforderungsfunktionen zurückgekehrt sind und der Anwendungscode die Möglichkeit hat, diese Signale mit Slots zu verbinden. Der typische Ansatz ist die Verwendung von QMetaObject::invokeMethod() mit einem Qt::QueuedConnection, um die Signale auszusenden.

void SearchSuggestionReply::triggerDone(QPlaceReply::Error error,
                         const QString &errorString)
{
    if (error != QPlaceReply::NoError) {
        this->setError(error,errorString);
        QMetaObject::invokeMethod(m_engine, "errorOccurred", Qt::QueuedConnection,
                                  Q_ARG(QPlaceReply *,this),
                                  Q_ARG(QPlaceReply::Error, error),
                                  Q_ARG(QString, errorString));
        QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
                                  Q_ARG(QPlaceReply::Error, error),
                                  Q_ARG(QString, errorString));
    }

    this->setFinished(true);
    QMetaObject::invokeMethod(m_engine, "finished", Qt::QueuedConnection,
                              Q_ARG(QPlaceReply *,this));
    QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}

Beachten Sie, dass die finished -Signale immer ausgegeben werden sollten, wenn eine Antwort abgeschlossen ist, auch wenn ein Fehler aufgetreten ist, d. h. wenn ein Fehler vorliegt, sollten sowohl die error - als auch die finished -Signale ausgegeben werden, während, wenn kein Fehler vorliegt, nur die finished -Signale ausgegeben werden.

Die geschützten Funktionen von QPlaceSearchReply::setResults() und QPlaceSearchReply::setRequest() werden öffentlich zugänglich gemacht, damit das Plugin Ergebnisse und Anforderungen zuweisen kann. Da diese Funktionen nicht öffentlich exportiert werden, ist die Zugänglichkeit nicht so sehr ein Problem. Eine Alternative wäre gewesen, eine Freundesklasse in SearchReply zu deklarieren.

Typischerweise würde die Engine-Instanz zur parent der Antwort gemacht werden. Wenn der Entwickler die Antworten nicht verwirft, wenn er fertig ist, kann die Engine diese bei der Zerstörung bereinigen. Üblicherweise hat die Antwort auch einen Zeiger auf die Engine, der verwendet werden kann, um die Signale QPlaceManagerEngine::finished() und QPlaceManagerEngine::error() auszusenden. Dies ist nur eine von vielen Möglichkeiten, wie die Antwort implementiert werden kann.

Icon-URLs

Icon-URLs werden durch die Funktion QPlaceManagerEngine::constructIconUrl() bereitgestellt. Das erwartete Verhalten ist, dass die Engine die Funktion QPlaceIcon::parameters() verwendet, um eine geeignete URL zu konstruieren. Wenn ein QPlace Objekt vom Manager zurückgegeben wird, entweder von einer Suche oder einer Abfrage, um Ortsdetails zu erhalten, wird erwartet, dass die Engine die Parameter wie erforderlich korrekt ausfüllt.

Das Backend kann den Schlüssel und die Werte der Parameter frei wählen. Wenn ein Backend jedoch nur eine URL pro Symbol hat, wird empfohlen, die QPlaceIcon::SingleUrl als Schlüssel zu verwenden.

Kategorien

Die Kategorien einer Manager-Engine sind relativ statische Einheiten; für Engines, die auf entfernte Ortsdatenbanken zugreifen, kann es wünschenswert sein, die Kategoriestruktur zwischenzuspeichern, anstatt bei jedem Aufruf von QPlaceManagerEngine::initializeCategories() einen Server abzufragen. Je nachdem, wie dynamisch die Kategorien sind, kann es sinnvoller sein, immer den aktuellsten Satz von Kategorien herunterzuladen.

Speichern von Orten im Manager

Ein Ort kann im Allgemeinen nicht direkt zwischen Managern gespeichert werden, da er managerspezifische Daten wie Symbole und Kategorien enthält. Um das Speichern im eigenen Manager zu erleichtern, sollten Engine-Implementierer die Funktion QPlaceManagerEngine::compatiblePlace() implementieren. Diese Funktion gibt eine Kopie des Eingabeplatzes zurück, deren Eigenschaften nach Bedarf beschnitten oder geändert wurden, so dass die Kopie im Manager gespeichert werden kann.

Die Erstellung eines kompatiblen Ortes kann das Ignorieren bestimmter Eigenschaften des ursprünglichen Ortes beinhalten, z. B. wenn Kontaktangaben nicht unterstützt werden, werden diese im kompatiblen Ort weggelassen. In anderen Fällen kann es erforderlich sein, bestimmte Eigenschaften zu ändern, z. B. die Parameter des Symbols zu ändern, um das Kopieren oder Herunterladen des Symbols des ursprünglichen Ortes an einen Ort zu erleichtern, auf den das Backend zugreifen kann.

Kreuzreferenzierung von Orten zwischen Managern

Manchmal kann eine Situation eintreten, in der wir Orte zwischen Managern mit Querverweisen versehen und abgleichen möchten. Eine solche Situation kann eintreten, wenn ein Manager einen Nur-Lese-Zugriff auf Orte bietet (Ursprungsmanager), während ein anderer, zweiter R/W-Manager (Zielmanager) verwendet wird, um ausgewählte Favoriten aus dem ersten Manager zu speichern. Während einer Suche im Ursprungsmanager möchten wir vielleicht wissen, welche Orte im Zielmanager "favorisiert" wurden, und vielleicht den angepassten Favoritennamen anstelle des ursprünglichen Namens anzeigen.

Querverweise auf alternative Bezeichner

Um einen Querverweis zu ermöglichen, muss eine Verbindung zwischen dem ursprünglichen Ort und dem favorisierten Ort bestehen, was in der Regel über ein alternatives Bezeichner-Attribut erfolgt. Der favorisierte Ort enthält ein alternatives Bezeichner-Attribut, das den Bezeichner des ursprünglichen Ortes enthält.

origin R/O manager(here)       destination R/W manager (places_jsondb)
                        Save
Place id: ae246         --->    Place id: 0001
Attribute type: x_provider      Attribute type: x_id_here
Attribute value: here           Attribute text value: ae246

Es gibt 3 Voraussetzungen für die Implementierung von Querverweisen durch alternative Bezeichner. Die erste ist, dass der Herkunftsmanager das Attribut x_provider bereitstellen muss, wobei der Wert der Name des Managers QGeoServiceProvider ist. Die Attributbezeichnung sollte leer bleiben, um anzuzeigen, dass das Attribut den Benutzern nicht angezeigt werden soll.

Anmerkung: Es wird allgemein erwartet, dass alle Manager das Attribut x_provider setzen.

Die zweite Möglichkeit ist, dass QPlaceManager::compatiblePlace() des Zielmanagers das Attribut x_provider des Ausgangsortes verwendet und ein alternatives Bezeichnerattribut des zu speichernden Ortes setzt. Der Schlüssel des alternativen Bezeichnerattributs ist x_id_<provider name> und der Textwert ist der Bezeichner des Ausgangsortes. Das Attribut x_provider sollte nicht an den kompatiblen Ort weitergegeben werden. Beim Speichern wird der x_provider des gespeicherten Ortes als Zielmanager betrachtet.

Die dritte Möglichkeit besteht darin, dass QPlaceManager::matchingPlaces() des Zielmanagers QPlaceMatchRequest::AlternativeId als Parameterschlüssel und den Schlüssel des alternativen Bezeichners als Wert akzeptiert, in diesem Fall wäre x_id_<provider name> der erwartete Wert. Dies bedeutet, dass die Bezeichner der Orte in QPlaceMatchRequest mit den x_id_<provider name> alternativen Bezeichnerattributen abgeglichen werden sollten.

Beachten Sie, dass der Ziel-Manager, wenn er das Speichern und Querverweisen von beliebigen Managern erleichtern soll, intern das Speichern beliebiger Schlüssel-Wert-Paare ermöglichen muss, da wir weder die Namen der Anbieter im Voraus kennen, noch wissen können, welche Struktur die Kennungen haben werden.

Andere Methoden der Verknüpfung

Wenn ein Herkunftsmanager keine Ortskennung zur Verfügung stellt, kann es notwendig sein, andere Mittel für Querverweise/Übereinstimmungen bereitzustellen. Ein Ansatz könnte sein, dies über die Ortskoordinaten zu tun. Wenn die Koordinate eines Ortes im Herkunftsmanager mit der eines Ortes im Zielmanager identisch ist oder ihr sehr nahe kommt, besteht eine hohe Wahrscheinlichkeit, dass es sich um denselben Ort handelt. In diesem Fall könnte der Manager QPlaceManager::matchingPlaces() implementieren, um eine QPlaceMatchRequest mit dem Parameterschlüssel "Nähe" und dem Parameterwert der Entfernung, die zwei Orte haben müssen, um eine Übereinstimmung zu erkennen, zu akzeptieren. Wenn beispielsweise ein Ursprungs- und ein Zielort innerhalb von 50 m voneinander entfernt sind, können sie als derselbe Ort betrachtet werden.

Im Allgemeinen wird jedoch empfohlen, Querverweise über alternative Identifikatoren wie oben erwähnt zu implementieren.

Vom Benutzer lesbare vs. nicht vom Benutzer lesbare erweiterte Attribute

Wenn ein Attribut nicht für Endbenutzer lesbar sein soll, sollte das Bezeichnungsfeld leer bleiben, um diese Tatsache zu verdeutlichen.

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.