Show native directory selection dlg in web UI
This commit is contained in:
parent
bf2c446d20
commit
3a81ae4f61
|
@ -10,8 +10,10 @@
|
||||||
|
|
||||||
#include <QAuthenticator>
|
#include <QAuthenticator>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
#include <QStringBuilder>
|
||||||
#if defined(SYNCTHINGWIDGETS_USE_WEBENGINE)
|
#if defined(SYNCTHINGWIDGETS_USE_WEBENGINE)
|
||||||
#include <QWebEngineCertificateError>
|
#include <QWebEngineCertificateError>
|
||||||
#include <QWebEngineSettings>
|
#include <QWebEngineSettings>
|
||||||
|
@ -37,7 +39,7 @@ WebPage::WebPage(WebViewDialog *dlg, SYNCTHINGWIDGETS_WEB_VIEW *view)
|
||||||
settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true);
|
settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true);
|
||||||
connect(
|
connect(
|
||||||
this, &WebPage::authenticationRequired, this, static_cast<void (WebPage::*)(const QUrl &, QAuthenticator *)>(&WebPage::supplyCredentials));
|
this, &WebPage::authenticationRequired, this, static_cast<void (WebPage::*)(const QUrl &, QAuthenticator *)>(&WebPage::supplyCredentials));
|
||||||
#else
|
#else // SYNCTHINGWIDGETS_USE_WEBKIT
|
||||||
settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
|
settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
|
||||||
setNetworkAccessManager(&Data::networkAccessManager());
|
setNetworkAccessManager(&Data::networkAccessManager());
|
||||||
connect(&Data::networkAccessManager(), &QNetworkAccessManager::authenticationRequired, this,
|
connect(&Data::networkAccessManager(), &QNetworkAccessManager::authenticationRequired, this,
|
||||||
|
@ -45,6 +47,7 @@ WebPage::WebPage(WebViewDialog *dlg, SYNCTHINGWIDGETS_WEB_VIEW *view)
|
||||||
connect(&Data::networkAccessManager(), &QNetworkAccessManager::sslErrors, this,
|
connect(&Data::networkAccessManager(), &QNetworkAccessManager::sslErrors, this,
|
||||||
static_cast<void (WebPage::*)(QNetworkReply *, const QList<QSslError> &errors)>(&WebPage::handleSslErrors));
|
static_cast<void (WebPage::*)(QNetworkReply *, const QList<QSslError> &errors)>(&WebPage::handleSslErrors));
|
||||||
#endif
|
#endif
|
||||||
|
connect(this, &SYNCTHINGWIDGETS_WEB_PAGE::loadFinished, this, &WebPage::injectJavaScripts);
|
||||||
|
|
||||||
if (!m_view) {
|
if (!m_view) {
|
||||||
// initialization for new window
|
// initialization for new window
|
||||||
|
@ -78,6 +81,9 @@ bool WebPage::isSamePage(const QUrl &url1, const QUrl &url2)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Delegates creation of new windows to a new instance of WebPage which will show it in an external browser.
|
||||||
|
*/
|
||||||
SYNCTHINGWIDGETS_WEB_PAGE *WebPage::createWindow(SYNCTHINGWIDGETS_WEB_PAGE::WebWindowType type)
|
SYNCTHINGWIDGETS_WEB_PAGE *WebPage::createWindow(SYNCTHINGWIDGETS_WEB_PAGE::WebWindowType type)
|
||||||
{
|
{
|
||||||
Q_UNUSED(type)
|
Q_UNUSED(type)
|
||||||
|
@ -85,19 +91,24 @@ SYNCTHINGWIDGETS_WEB_PAGE *WebPage::createWindow(SYNCTHINGWIDGETS_WEB_PAGE::WebW
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SYNCTHINGWIDGETS_USE_WEBENGINE
|
#ifdef SYNCTHINGWIDGETS_USE_WEBENGINE
|
||||||
|
/*!
|
||||||
|
* \brief Accepts self-signed certificate.
|
||||||
|
* \todo Only ignore the error if the used certificate matches the certificate known to be used by the Syncthing GUI.
|
||||||
|
*/
|
||||||
bool WebPage::certificateError(const QWebEngineCertificateError &certificateError)
|
bool WebPage::certificateError(const QWebEngineCertificateError &certificateError)
|
||||||
{
|
{
|
||||||
switch (certificateError.error()) {
|
switch (certificateError.error()) {
|
||||||
case QWebEngineCertificateError::CertificateCommonNameInvalid:
|
case QWebEngineCertificateError::CertificateCommonNameInvalid:
|
||||||
case QWebEngineCertificateError::CertificateAuthorityInvalid:
|
case QWebEngineCertificateError::CertificateAuthorityInvalid:
|
||||||
// FIXME: only ignore the error if the used certificate matches the certificate
|
|
||||||
// known to be used by the Syncthing GUI
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Accepts navigation requests only on the same page.
|
||||||
|
*/
|
||||||
bool WebPage::acceptNavigationRequest(const QUrl &url, SYNCTHINGWIDGETS_WEB_PAGE::NavigationType type, bool isMainFrame)
|
bool WebPage::acceptNavigationRequest(const QUrl &url, SYNCTHINGWIDGETS_WEB_PAGE::NavigationType type, bool isMainFrame)
|
||||||
{
|
{
|
||||||
Q_UNUSED(isMainFrame)
|
Q_UNUSED(isMainFrame)
|
||||||
|
@ -105,15 +116,45 @@ bool WebPage::acceptNavigationRequest(const QUrl &url, SYNCTHINGWIDGETS_WEB_PAGE
|
||||||
return handleNavigationRequest(this->url(), url);
|
return handleNavigationRequest(this->url(), url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Invokes processing JavaScript messages printed via "console.log()".
|
||||||
|
*/
|
||||||
|
void WebPage::javaScriptConsoleMessage(
|
||||||
|
QWebEnginePage::JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID)
|
||||||
|
{
|
||||||
|
Q_UNUSED(level)
|
||||||
|
Q_UNUSED(lineNumber)
|
||||||
|
Q_UNUSED(sourceID)
|
||||||
|
if (level == QWebEnginePage::InfoMessageLevel) {
|
||||||
|
processJavaScriptConsoleMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#else // SYNCTHINGWIDGETS_USE_WEBKIT
|
#else // SYNCTHINGWIDGETS_USE_WEBKIT
|
||||||
|
/*!
|
||||||
|
* \brief Accepts navigation requests only on the same page.
|
||||||
|
*/
|
||||||
bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, SYNCTHINGWIDGETS_WEB_PAGE::NavigationType type)
|
bool WebPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, SYNCTHINGWIDGETS_WEB_PAGE::NavigationType type)
|
||||||
{
|
{
|
||||||
Q_UNUSED(frame)
|
Q_UNUSED(frame)
|
||||||
Q_UNUSED(type)
|
Q_UNUSED(type)
|
||||||
return handleNavigationRequest(mainFrame() ? mainFrame()->url() : QUrl(), request.url());
|
return handleNavigationRequest(mainFrame() ? mainFrame()->url() : QUrl(), request.url());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Invokes processing JavaScript messages printed via "console.log()".
|
||||||
|
*/
|
||||||
|
void WebPage::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID)
|
||||||
|
{
|
||||||
|
Q_UNUSED(lineNumber)
|
||||||
|
Q_UNUSED(sourceID)
|
||||||
|
processJavaScriptConsoleMessage(message);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shows the specified \a url in the default browser and deletes the page and associated view.
|
||||||
|
*/
|
||||||
void WebPage::delegateNewWindowToExternalBrowser(const QUrl &url)
|
void WebPage::delegateNewWindowToExternalBrowser(const QUrl &url)
|
||||||
{
|
{
|
||||||
QDesktopServices::openUrl(url);
|
QDesktopServices::openUrl(url);
|
||||||
|
@ -122,18 +163,27 @@ void WebPage::delegateNewWindowToExternalBrowser(const QUrl &url)
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Supplies credentials from the dialog's settings.
|
||||||
|
*/
|
||||||
void WebPage::supplyCredentials(const QUrl &requestUrl, QAuthenticator *authenticator)
|
void WebPage::supplyCredentials(const QUrl &requestUrl, QAuthenticator *authenticator)
|
||||||
{
|
{
|
||||||
Q_UNUSED(requestUrl)
|
Q_UNUSED(requestUrl)
|
||||||
supplyCredentials(authenticator);
|
supplyCredentials(authenticator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Supplies credentials from the dialog's settings.
|
||||||
|
*/
|
||||||
void WebPage::supplyCredentials(QNetworkReply *reply, QAuthenticator *authenticator)
|
void WebPage::supplyCredentials(QNetworkReply *reply, QAuthenticator *authenticator)
|
||||||
{
|
{
|
||||||
Q_UNUSED(reply)
|
Q_UNUSED(reply)
|
||||||
supplyCredentials(authenticator);
|
supplyCredentials(authenticator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Supplies credentials from the dialog's settings.
|
||||||
|
*/
|
||||||
void WebPage::supplyCredentials(QAuthenticator *authenticator)
|
void WebPage::supplyCredentials(QAuthenticator *authenticator)
|
||||||
{
|
{
|
||||||
if (m_dlg && m_dlg->settings().authEnabled) {
|
if (m_dlg && m_dlg->settings().authEnabled) {
|
||||||
|
@ -142,6 +192,9 @@ void WebPage::supplyCredentials(QAuthenticator *authenticator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Allows initial request and navigation on the same page but opens everything else in an external browser.
|
||||||
|
*/
|
||||||
bool WebPage::handleNavigationRequest(const QUrl ¤tUrl, const QUrl &targetUrl)
|
bool WebPage::handleNavigationRequest(const QUrl ¤tUrl, const QUrl &targetUrl)
|
||||||
{
|
{
|
||||||
if (currentUrl.isEmpty()) {
|
if (currentUrl.isEmpty()) {
|
||||||
|
@ -158,6 +211,9 @@ bool WebPage::handleNavigationRequest(const QUrl ¤tUrl, const QUrl &target
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SYNCTHINGWIDGETS_USE_WEBKIT
|
#ifdef SYNCTHINGWIDGETS_USE_WEBKIT
|
||||||
|
/*!
|
||||||
|
* \brief Ignores SSL errors that are known exceptions to support self-signed certificates.
|
||||||
|
*/
|
||||||
void WebPage::handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
void WebPage::handleSslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
|
||||||
{
|
{
|
||||||
Q_UNUSED(errors)
|
Q_UNUSED(errors)
|
||||||
|
@ -166,6 +222,54 @@ void WebPage::handleSslErrors(QNetworkReply *reply, const QList<QSslError> &erro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Injects the specified JavaScript.
|
||||||
|
*/
|
||||||
|
void WebPage::injectJavaScript(const QString &scriptSource)
|
||||||
|
{
|
||||||
|
#ifdef SYNCTHINGWIDGETS_USE_WEBENGINE
|
||||||
|
runJavaScript(scriptSource);
|
||||||
|
#else // SYNCTHINGWIDGETS_USE_WEBKIT
|
||||||
|
mainFrame()->evaluateJavaScript(scriptSource);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Injects the JavaScript code required for additional features.
|
||||||
|
* \remarks Called when the page has been loaded.
|
||||||
|
*/
|
||||||
|
void WebPage::injectJavaScripts(bool ok)
|
||||||
|
{
|
||||||
|
Q_UNUSED(ok)
|
||||||
|
// show folder path selection when double-clicking input
|
||||||
|
injectJavaScript(QStringLiteral("jQuery('#folderPath').dblclick(function(event) {"
|
||||||
|
" if (event.target && !event.target.getAttribute('readonly')) {"
|
||||||
|
" console.log('nativeInterface.showFolderPathSelection: ' + event.target.value);"
|
||||||
|
" }"
|
||||||
|
"});"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Invokes native methods requested via JavaScript log.
|
||||||
|
*/
|
||||||
|
void WebPage::processJavaScriptConsoleMessage(const QString &message)
|
||||||
|
{
|
||||||
|
if (message.startsWith(QLatin1String("nativeInterface.showFolderPathSelection: "))) {
|
||||||
|
showFolderPathSelection(message.mid(41));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Shows the folder path selection and sets the selected path in the page.
|
||||||
|
*/
|
||||||
|
void WebPage::showFolderPathSelection(const QString &defaultDir)
|
||||||
|
{
|
||||||
|
const QString dir(QFileDialog::getExistingDirectory(m_view, tr("Select path for Syncthing directory ..."), defaultDir));
|
||||||
|
if (!dir.isEmpty()) {
|
||||||
|
injectJavaScript(QStringLiteral("document.getElementById('folderPath').value = '") % dir % QStringLiteral("';"));
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace QtGui
|
} // namespace QtGui
|
||||||
|
|
||||||
#endif // SYNCTHINGWIDGETS_NO_WEBVIEW
|
#endif // SYNCTHINGWIDGETS_NO_WEBVIEW
|
||||||
|
|
|
@ -28,8 +28,11 @@ protected:
|
||||||
#ifdef SYNCTHINGWIDGETS_USE_WEBENGINE
|
#ifdef SYNCTHINGWIDGETS_USE_WEBENGINE
|
||||||
bool certificateError(const QWebEngineCertificateError &certificateError);
|
bool certificateError(const QWebEngineCertificateError &certificateError);
|
||||||
bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame);
|
bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame);
|
||||||
|
void javaScriptConsoleMessage(
|
||||||
|
QWebEnginePage::JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID);
|
||||||
#else
|
#else
|
||||||
bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type);
|
bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type);
|
||||||
|
void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -40,6 +43,10 @@ private slots:
|
||||||
#ifdef SYNCTHINGWIDGETS_USE_WEBKIT
|
#ifdef SYNCTHINGWIDGETS_USE_WEBKIT
|
||||||
void handleSslErrors(QNetworkReply *, const QList<QSslError> &errors);
|
void handleSslErrors(QNetworkReply *, const QList<QSslError> &errors);
|
||||||
#endif
|
#endif
|
||||||
|
void injectJavaScripts(bool ok);
|
||||||
|
void processJavaScriptConsoleMessage(const QString &message);
|
||||||
|
void injectJavaScript(const QString &scriptSource);
|
||||||
|
void showFolderPathSelection(const QString &defaultDir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool handleNavigationRequest(const QUrl ¤tUrl, const QUrl &url);
|
static bool handleNavigationRequest(const QUrl ¤tUrl, const QUrl &url);
|
||||||
|
|
Loading…
Reference in New Issue