Как разрешить трафик карты QML проходить через прокси и отключить этот прокси для остальной части программы?

У меня есть приложение, которое использует локальную сеть для связи с некоторыми устройствами и http-прокси для получения чего-либо внешнего. Я хотел бы использовать в нем плагин карты. Теперь карте потребуется HTTP-прокси для загрузки тайлов. Если я установлю глобальные настройки прокси-сервера Qt, используя переменную http_proxy, или сделаю это вручную, используя QNetworkProxy::setApplicationProxy, то карта загружается нормально, но остальная часть программы ломается. Если я отключу прокси, то смогу общаться со своими устройствами, но не вижу карту. Я пробовал использовать QQmlNetworkAccessManagerFactory, как описано в примере здесь, и он отлично работает для объекта типа Image, как определено в view.qml, но это не сработает, если я заменю Image на Item, который содержит мою карту.

Item{
    width: 500
    height: 500
    Map {
        Plugin {
            id: mapPlugin
            name: "osm"
        }
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(59.91, 10.75)
        zoomLevel: 14
        visible: true
    }
}

Метод MyNetworkAccessManagerFactory::create никогда не вызывается, и я получаю следующую ошибку: QGeoTileRequestManager: Failed to fetch tile (17366,9541,15) 5 times, giving up. Last error message was: 'Error transferring http://c.tile.openstreetmap.org/15/17366/9541.png - server replied: Service Unavailable'. Что может быть причиной этого? И как я могу установить QNetworkProxy для плагина карты?


person Anton Levanter    schedule 11.03.2019    source источник
comment
Какой плагин вы используете: osm, maxbox и т.д.?   -  person eyllanesc    schedule 11.03.2019
comment
@eyllanesc Я использую osm только для проверки и воспользуюсь здесь позже. Но это то же самое для всех них. На самом деле мне удалось заставить QQmlNetworkAccessManagerFactory example работать с изображением , но он не подхватывает настройки прокси, если я заменяю его плагином карты.   -  person Anton Levanter    schedule 12.03.2019


Ответы (1)


Вы должны изменить исходный код плагина:

src/plugins/geoservices/osm/qgeocodingmanagerengineosm.cpp
src/plugins/geoservices/osm/qgeoroutingmanagerengineosm.cpp
src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
src/plugins/geoservices/osm/qplacemanagerengineosm.cpp

В каждом из этих файлов есть QNetworkAccessManager, поэтому вы должны добавить следующий код:

#include <QtNetwork/QNetworkProxy>

// ...
// constructor

    QString proxy = parameters.value(QStringLiteral("proxy")).toString();
    if (!proxy.isEmpty()) {
#ifndef QT_NO_NETWORKPROXY
        if (proxy.toLower() != QStringLiteral("system")) {
            QUrl proxyUrl(proxy);
            if (proxyUrl.isValid()) {
                qDebug() << "Setting proxy to " << proxyUrl.toString();
                m_networkManager->setProxy(
                            QNetworkProxy(QNetworkProxy::HttpProxy,
                                          proxyUrl.host(),
                                          proxyUrl.port(8080),
                                          proxyUrl.userName(),
                                          proxyUrl.password()));
            }
        } else if (QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy) {
            QNetworkProxyFactory::setUseSystemConfiguration(true);
            qDebug() << "Setting system proxy.";
        }
#else
        qDebug() << "No proxy support";
#endif
    } else {
        qDebug() << "No proxy parameter specified.";
    }

Я создал .patch, чтобы упростить обновление, чтобы загрузить его с здесь.

Потом помещаете концы в папку src/plugins/geoservices/osm, применяете патч, компилируете и устанавливаете со следующим:

git clone -b 5.12.1 [email protected]:qt/qtlocation.git
cd qtlocation/src/plugins/geoservices/osm
wget https://raw.githubusercontent.com/eyllanesc/stackoverflow/master/questions/55105933/proxy-osm.patch
git apply proxy-osm.patch
qmake
make
sudo make install

Затем после этого вы можете использовать прокси, используя параметр плагина:

Map {
    Plugin {
        id: mapPlugin
        name: "osm"
        PluginParameter { name: "proxy"; value: "http://179.179.253.147:8080" } // <---
    }
    anchors.fill: parent
    plugin: mapPlugin
    center: QtPositioning.coordinate(59.91, 10.75)
    zoomLevel: 14
    visible: true
}
person eyllanesc    schedule 13.03.2019