このページでは

場所のバックエンド

概要

場所情報へのアクセスをクライアントに提供するためのQPlaceManager インターフェースは、QPlaceManagerEngine の実装に直接依存しています。エンジン側は、マネージャーによって呼び出されるバックエンド関数の実装を提供します。

場所バックエンドの実装者は、QPlaceManagerEngine を継承し、そのバックエンドに関連する仮想関数の実装を提供する必要があります。これらの関数のほとんどは非同期であるため、実装者は適切な応答クラスも派生させる必要があります。 返信オブジェクトは、非同期リクエストの管理を担当します。これらは、リクエストが完了したことを通知するために使用され、そのリクエストの結果を保持します。QPlaceManagerEngine は、すべての仮想関数に対してデフォルトの実装を提供します。非同期関数のデフォルト実装は、次のイベントループの反復時にerrorOccurred()およびfinished()シグナルを発火させる返信を返します。

Reply オブジェクトの実装と継承

Replyオブジェクトは次のように継承されます:

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;
};

QPlaceManagerEngine の実装では、リクエスト関数が返り、アプリケーションコードがそれらのシグナルをスロットに接続する機会を得るまで、Reply オブジェクトによって発火されるすべてのシグナルを遅延させる必要があります。一般的なアプローチは、Qt::QueuedConnection と共にQMetaObject::invokeMethod() を使用してシグナルを発火させることです。

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);
}

なお、finished のシグナルは、エラーが発生した場合であっても、応答が完了した時点で常に発火される必要があります。つまり、エラーが発生した場合はerror とfinished の両方のシグナルが発火され、エラーがない場合はfinished のシグナルのみが発火されます。

QPlaceSearchReply::setResults() およびQPlaceSearchReply::setRequest() のプロテクト関数は、プラグインが結果やリクエストを割り当てられるように、パブリックにアクセス可能になっています。これらの関数はパブリックにエクスポートされていないため、アクセス権限に関する問題はそれほど深刻ではありません。別の方法としては、SearchReply クラス内でフレンドクラスを宣言することも考えられました。

通常、エンジンインスタンスがレスポンスのparent として設定されます。開発者が処理終了後にレスポンスを破棄し忘れた場合でも、エンジンは破棄時にそれらをクリーンアップできます。 通常、リプライにはエンジンへのポインタ参照も含まれており、これを使用してQPlaceManagerEngine::finished()やQPlaceManagerEngine::error()といったシグナルを発火させることができます。これは、リプライを実装する多くの方法のうちの1つに過ぎません。

アイコンのURL

アイコンのURLは、QPlaceManagerEngine::constructIconUrl() 関数を通じて提供されます。期待される動作として、エンジンはQPlaceIcon::parameters() を使用して適切なURLを構築する必要があります。検索や場所の詳細を取得するためのクエリの結果として、マネージャーからQPlace オブジェクトが返された場合、エンジンは必要に応じてパラメータを正しく設定することが期待されます。

バックエンドはパラメータのキーや値を自由に選択できますが、アイコンごとにURLが1つしかないバックエンドの場合は、キーとして「QPlaceIcon::SingleUrl 」を使用することを推奨します。

カテゴリ

マネージャーエンジンのカテゴリは比較的静的なエンティティです。リモートの場所データストアにアクセスするエンジンでは、QPlaceManagerEngine::initializeCategories() が呼び出されるたびにサーバーにクエリを送信するのではなく、カテゴリ構造をキャッシュしておく方が望ましい場合があります。カテゴリの動的な性質によっては、常に最新のカテゴリセットをダウンロードする方が適切である場合もあります。

マネージャーへのプレイスの保存

プレイスは、アイコンやカテゴリといったマネージャー固有のデータを含んでいるため、通常はそのままの状態でマネージャー間で直接保存することはできません。自身のマネージャーへの保存を容易にするため、エンジン実装者は `QPlaceManagerEngine::compatiblePlace()` 関数を実装する必要があります。この関数は、入力されたプレイスのコピーを返します。このコピーは、マネージャーに保存できるよう、必要に応じてプロパティが削除または変更されています。

互換性のあるプレイスの構築には、元のプレイスの特定のプロパティを無視することが含まれる場合があります。例えば、連絡先情報がサポートされていない場合、それらは互換性のあるプレイスから除外されます。また、特定のプロパティを変更する場合もあります。例えば、元のプレイスのアイコンをバックエンドがアクセス可能な場所にコピーまたはダウンロードしやすくするために、アイコンのパラメータを変更する場合などです。

マネージャー間の場所の相互参照

マネージャー間で場所を相互参照し、照合したい状況が生じる場合があります。このような状況は、あるマネージャーが場所への読み取り専用アクセスを提供している(元のマネージャー)一方で、別の読み書き可能なマネージャー(宛先マネージャー)が、前者から選択されたお気に入りを保存するために使用される場合に発生し得ます。 元マネージャーで検索を行う際、どの場所が「お気に入り」として宛先マネージャーに登録されているかを確認したい場合や、元の名前ではなくカスタマイズされたお気に入り名を表示したい場合があります。

代替識別子による相互参照

相互参照を実現するためには、元の場所とお気に入りに登録された場所の間にリンクが必要であり、これは通常、代替識別子属性によって処理されます。お気に入りに登録された場所には、元の場所の識別子を持つ代替識別子属性が含まれています。

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

代替識別子による相互参照を実装するには、3つの前提条件があります。1つ目は、元のマネージャーが x_provider 属性を提供し、その値としてマネージャーのQGeoServiceProvider の名前を指定することです。属性ラベルは空のままにしておく必要があり、これはユーザーにこの属性を表示しないことを示します。

注: 一般的に、すべてのマネージャーがx_provider 属性を設定することが期待されます 。

2つ目は、宛先マネージャーのQPlaceManager::compatiblePlace()が、初期場所のx_provider 属性を使用し、保存される場所の代替識別子属性を設定することです。 代替識別子属性のキーは「x_id_<provider name>」であり、テキスト値は初期場所の識別子です。x_provider 属性は、互換性のある場所には渡してはなりません。保存されると、保存された場所の x_provider は宛先マネージャーと見なされます。

3つ目は、宛先マネージャーのQPlaceManager::matchingPlaces()が、パラメータキーとしてQPlaceMatchRequest::AlternativeId を受け入れ、値として代替識別子属性のキーを受け入れることです。この場合、x_id_<provider name>が期待される値となります。これは、QPlaceMatchRequest 内の場所の識別子が、x_id_<provider name>という代替識別子属性と照合されるべきであることを示しています。

なお、宛先マネージャーが任意のマネージャーからの保存や相互参照を容易にするためには、プロバイダー名を事前に把握できない上、IDの構造も分からないため、内部的には任意のキー・値ペアの保存に対応している必要があります。

その他のリンク方法

元のマネージャーが場所 ID を提供しない場合、相互参照や照合を行うための他の手段を用意する必要があるかもしれません。1 つのアプローチとして、場所の座標を利用する方法が考えられます。元のマネージャー内の場所の座標が、宛先マネージャー内の場所の座標と同一、または近似している場合、それらが同じ場所である可能性が高くなります。 この場合、マネージャーはQPlaceManager::matchingPlaces() を実装し、パラメータキーを「proximity」、パラメータ値を「一致を検出するために2つの場所が満たすべき距離」として指定したQPlaceMatchRequest を受け入れるようにします。例えば、出発地と目的地の場所が互いに50m以内にある場合、それらは同一の場所と見なすことができます。

ただし、一般的には、前述のように代替識別子を用いて相互参照を実装することが推奨されます。

ユーザー可読と非ユーザー可読の拡張属性

属性がエンドユーザーに読み取られることを意図していない場合は、その旨を示すためにラベルフィールドを空にしておく必要があります。

© 2026 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.