From 6079a317b9e41a3daa50d10ab262f7d0c3122e2a Mon Sep 17 00:00:00 2001 From: Tim Jenssen Date: Thu, 28 May 2020 12:35:25 +0200 Subject: [PATCH] QmlDesigner: add qmldebugtranslationclient Change-Id: I4b863a454831f469823e03355d87861eed9be046 Reviewed-by: Thomas Hartmann --- .../qmlpreview/qmldebugtranslationclient.cpp | 98 ++++++++++++ .../qmlpreview/qmldebugtranslationclient.h | 66 ++++++++ src/plugins/qmlpreview/qmlpreview.pro | 2 + src/plugins/qmlpreview/qmlpreview.qbs | 2 + .../qmlpreviewconnectionmanager.cpp | 146 +++++++++++------- .../qmlpreview/qmlpreviewconnectionmanager.h | 8 +- 6 files changed, 265 insertions(+), 57 deletions(-) create mode 100644 src/plugins/qmlpreview/qmldebugtranslationclient.cpp create mode 100644 src/plugins/qmlpreview/qmldebugtranslationclient.h diff --git a/src/plugins/qmlpreview/qmldebugtranslationclient.cpp b/src/plugins/qmlpreview/qmldebugtranslationclient.cpp new file mode 100644 index 00000000000..6d1310b1179 --- /dev/null +++ b/src/plugins/qmlpreview/qmldebugtranslationclient.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "qmldebugtranslationclient.h" +#include + +#include + +namespace QmlPreview { + +QmlDebugTranslationClient::QmlDebugTranslationClient(QmlDebug::QmlDebugConnection *connection) : + QmlDebug::QmlDebugClient(QLatin1String("DebugTranslation"), connection) +{ +} + +void QmlDebugTranslationClient::changeLanguage(const QUrl &url, const QString &locale) +{ + QmlDebug::QPacket packet(dataStreamVersion()); + packet << static_cast(ChangeLanguage) << url << locale; + sendMessage(packet.data()); +} + +void QmlDebugTranslationClient::changeWarningColor(const QColor &warningColor) +{ + QmlDebug::QPacket packet(dataStreamVersion()); + packet << static_cast(ChangeWarningColor) << warningColor; + sendMessage(packet.data()); +} + +void QmlDebugTranslationClient::changeElidedTextWarningString(const QString &warningString) +{ + QmlDebug::QPacket packet(dataStreamVersion()); + packet << static_cast(ChangeElidedTextWarningString) << warningString; + sendMessage(packet.data()); +} + +void QmlDebugTranslationClient::setDebugTranslationServiceLogFile(const QString &logFilePath) +{ + QmlDebug::QPacket packet(dataStreamVersion()); + packet << static_cast(SetDebugTranslationServiceLogFile) << logFilePath; + sendMessage(packet.data()); +} + +void QmlDebugTranslationClient::enableElidedTextWarning() +{ + QmlDebug::QPacket packet(dataStreamVersion()); + packet << static_cast(EnableElidedTextWarning); + sendMessage(packet.data()); +} + +void QmlDebugTranslationClient::disableElidedTextWarning() +{ + QmlDebug::QPacket packet(dataStreamVersion()); + packet << static_cast(DisableElidedTextWarning); + sendMessage(packet.data()); +} + +void QmlDebugTranslationClient::messageReceived(const QByteArray &data) +{ + QmlDebug::QPacket packet(dataStreamVersion(), data); + qint8 command; + packet >> command; + switch (command) { + default: + qDebug() << "invalid command" << command; + break; + } +} + +void QmlDebugTranslationClient::stateChanged(QmlDebug::QmlDebugClient::State state) +{ + if (state == Unavailable) + emit debugServiceUnavailable(); +} + +} // namespace QmlPreview diff --git a/src/plugins/qmlpreview/qmldebugtranslationclient.h b/src/plugins/qmlpreview/qmldebugtranslationclient.h new file mode 100644 index 00000000000..c27726a7eb2 --- /dev/null +++ b/src/plugins/qmlpreview/qmldebugtranslationclient.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "qmlpreview_global.h" +#include + +namespace QmlPreview { + +class QMLPREVIEW_EXPORT QmlDebugTranslationClient : public QmlDebug::QmlDebugClient +{ + Q_OBJECT +public: + //needs to be in sync with QQmlDebugTranslationClient in qtdeclarative/src/plugins/qmltooling/qmldbg_preview/qqmldebugtranslationservice.h + enum Command { + ChangeLanguage, + ChangeWarningColor, + ChangeElidedTextWarningString, + SetDebugTranslationServiceLogFile, + EnableElidedTextWarning, + DisableElidedTextWarning, + TestAllLanguages + }; + + explicit QmlDebugTranslationClient(QmlDebug::QmlDebugConnection *connection); + + void changeLanguage(const QUrl &url, const QString &locale); + void changeWarningColor(const QColor &warningColor); + void changeElidedTextWarningString(const QString &warningString); //is QByteArray better here? + void setDebugTranslationServiceLogFile(const QString &logFilePath); + void enableElidedTextWarning(); + void disableElidedTextWarning(); + + void messageReceived(const QByteArray &message) override; + void stateChanged(State state) override; + +signals: +// void pathRequested(const QString &path); +// void errorReported(const QString &error); + void debugServiceUnavailable(); +}; + +} // namespace QmlPreview diff --git a/src/plugins/qmlpreview/qmlpreview.pro b/src/plugins/qmlpreview/qmlpreview.pro index 534542ec008..cfc571521f5 100644 --- a/src/plugins/qmlpreview/qmlpreview.pro +++ b/src/plugins/qmlpreview/qmlpreview.pro @@ -9,6 +9,7 @@ include(tests/tests.pri) HEADERS += \ qmlpreview_global.h \ + qmldebugtranslationclient.h \ qmlpreviewclient.h \ qmlpreviewplugin.h \ qmlpreviewruncontrol.h \ @@ -17,6 +18,7 @@ HEADERS += \ SOURCES += \ qmlpreviewplugin.cpp \ + qmldebugtranslationclient.cpp \ qmlpreviewclient.cpp \ qmlpreviewruncontrol.cpp \ qmlpreviewconnectionmanager.cpp \ diff --git a/src/plugins/qmlpreview/qmlpreview.qbs b/src/plugins/qmlpreview/qmlpreview.qbs index 342d400469c..08e64725789 100644 --- a/src/plugins/qmlpreview/qmlpreview.qbs +++ b/src/plugins/qmlpreview/qmlpreview.qbs @@ -24,6 +24,8 @@ QtcPlugin { files: [ "qmlpreviewclient.cpp", "qmlpreviewclient.h", + "qmldebugtranslationclient.cpp", + "qmldebugtranslationclient.h", "qmlpreviewconnectionmanager.cpp", "qmlpreviewconnectionmanager.h", "qmlpreviewfileontargetfinder.cpp", diff --git a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp index 8a4f3bc2051..bac56163775 100644 --- a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp +++ b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.cpp @@ -70,10 +70,64 @@ void QmlPreviewConnectionManager::setFpsHandler(QmlPreviewFpsHandler fpsHandler) void QmlPreviewConnectionManager::createClients() { - m_clientPlugin = new QmlPreviewClient(connection()); + createPreviewClient(); + createDebugTranslationClient(); +} + +QUrl QmlPreviewConnectionManager::findValidI18nDirectoryAsUrl(const QString &locale) +{ + const QString shortLocale = locale.left(locale.indexOf("_")); + QString path = m_lastLoadedUrl.path(); + + while (!path.isEmpty()) { + path = path.left(qMax(0, path.lastIndexOf("/"))); + QUrl url = m_lastLoadedUrl; + + auto tryPath = [&](const QString &postfix) { + url.setPath(path + "/i18n/qml_" + postfix); + bool success = false; + m_projectFileFinder.findFile(url, &success); + return success; + }; + + if (tryPath(locale + ".qm")) + break; + if (tryPath(locale)) + break; + if (tryPath(shortLocale + ".qm")) + break; + if (tryPath(shortLocale)) + break; + } + + QUrl url = m_lastLoadedUrl; + url.setPath(path); + return url; +} + +void QmlPreviewConnectionManager::createDebugTranslationClient() +{ + m_qmlDebugTranslationClient = new QmlDebugTranslationClient(connection()); + QObject::connect(this, &QmlPreviewConnectionManager::language, + m_qmlDebugTranslationClient.data(), [this](const QString &locale) { + + // service expects a context URL. + // Search the parent directories of the last loaded URL for i18n files. + m_qmlDebugTranslationClient->changeLanguage(findValidI18nDirectoryAsUrl(locale), locale); + }); + QObject::connect(m_qmlDebugTranslationClient.data(), &QmlDebugTranslationClient::debugServiceUnavailable, + this, []() { + QMessageBox::warning(Core::ICore::mainWindow(), "Error connect to QML DebugTranslation service", + "QML DebugTranslation feature is not available for this version of Qt."); + }, Qt::QueuedConnection); // Queue it, so that it interfere with the connection timer +} + +void QmlPreviewConnectionManager::createPreviewClient() +{ + m_qmlPreviewClient = new QmlPreviewClient(connection()); QObject::connect( - this, &QmlPreviewConnectionManager::loadFile, m_clientPlugin.data(), + this, &QmlPreviewConnectionManager::loadFile, m_qmlPreviewClient.data(), [this](const QString &filename, const QString &changedFile, const QByteArray &contents) { if (!m_fileClassifier(changedFile)) { @@ -84,57 +138,29 @@ void QmlPreviewConnectionManager::createClients() bool success = false; const QString remoteChangedFile = m_targetFileFinder.findPath(changedFile, &success); if (success) - m_clientPlugin->announceFile(remoteChangedFile, contents); + m_qmlPreviewClient->announceFile(remoteChangedFile, contents); else - m_clientPlugin->clearCache(); + m_qmlPreviewClient->clearCache(); m_lastLoadedUrl = m_targetFileFinder.findUrl(filename); - m_clientPlugin->loadUrl(m_lastLoadedUrl); + m_qmlPreviewClient->loadUrl(m_lastLoadedUrl); }); QObject::connect(this, &QmlPreviewConnectionManager::rerun, - m_clientPlugin.data(), &QmlPreviewClient::rerun); + m_qmlPreviewClient.data(), &QmlPreviewClient::rerun); QObject::connect(this, &QmlPreviewConnectionManager::zoom, - m_clientPlugin.data(), &QmlPreviewClient::zoom); + m_qmlPreviewClient.data(), &QmlPreviewClient::zoom); QObject::connect(this, &QmlPreviewConnectionManager::language, - m_clientPlugin.data(), [this](const QString &locale) { + m_qmlPreviewClient.data(), [this](const QString &locale) { - // The preview service expects a context URL. + // service expects a context URL. // Search the parent directories of the last loaded URL for i18n files. - - const QString shortLocale = locale.left(locale.indexOf("_")); - QString path = m_lastLoadedUrl.path(); - - while (!path.isEmpty()) { - path = path.left(qMax(0, path.lastIndexOf("/"))); - QUrl url = m_lastLoadedUrl; - - auto tryPath = [&](const QString &postfix) { - url.setPath(path + "/i18n/qml_" + postfix); - bool success = false; - m_projectFileFinder.findFile(url, &success); - return success; - }; - - if (tryPath(locale + ".qm")) - break; - if (tryPath(locale)) - break; - if (tryPath(shortLocale + ".qm")) - break; - if (tryPath(shortLocale)) - break; - } - - QUrl url = m_lastLoadedUrl; - url.setPath(path); - - m_clientPlugin->language(url, locale); + m_qmlPreviewClient->language(findValidI18nDirectoryAsUrl(locale), locale); }); - QObject::connect(m_clientPlugin.data(), &QmlPreviewClient::pathRequested, + QObject::connect(m_qmlPreviewClient.data(), &QmlPreviewClient::pathRequested, this, [this](const QString &path) { const bool found = m_projectFileFinder.findFileOrDirectory( path, [&](const QString &filename, int confidence) { @@ -146,31 +172,31 @@ void QmlPreviewConnectionManager::createClients() m_fileSystemWatcher.addFile(filename, Utils::FileSystemWatcher::WatchModifiedDate); } - m_clientPlugin->announceFile(path, contents); + m_qmlPreviewClient->announceFile(path, contents); } else { - m_clientPlugin->announceError(path); + m_qmlPreviewClient->announceError(path); } } else { - m_clientPlugin->announceError(path); + m_qmlPreviewClient->announceError(path); } }, [&](const QStringList &entries, int confidence) { if (confidence == path.length()) - m_clientPlugin->announceDirectory(path, entries); + m_qmlPreviewClient->announceDirectory(path, entries); else - m_clientPlugin->announceError(path); + m_qmlPreviewClient->announceError(path); }); if (!found) - m_clientPlugin->announceError(path); + m_qmlPreviewClient->announceError(path); }); - QObject::connect(m_clientPlugin.data(), &QmlPreviewClient::errorReported, + QObject::connect(m_qmlPreviewClient.data(), &QmlPreviewClient::errorReported, this, [](const QString &error) { Core::MessageManager::write("Error loading QML Live Preview:"); Core::MessageManager::write(error); }); - QObject::connect(m_clientPlugin.data(), &QmlPreviewClient::fpsReported, + QObject::connect(m_qmlPreviewClient.data(), &QmlPreviewClient::fpsReported, this, [this](const QmlPreviewClient::FpsInfo &frames) { if (m_fpsHandler) { quint16 stats[] = { @@ -181,14 +207,14 @@ void QmlPreviewConnectionManager::createClients() } }); - QObject::connect(m_clientPlugin.data(), &QmlPreviewClient::debugServiceUnavailable, + QObject::connect(m_qmlPreviewClient.data(), &QmlPreviewClient::debugServiceUnavailable, this, []() { QMessageBox::warning(Core::ICore::mainWindow(), "Error loading QML Live Preview", "QML Live Preview is not available for this version of Qt."); }, Qt::QueuedConnection); // Queue it, so that it interfere with the connection timer QObject::connect(&m_fileSystemWatcher, &Utils::FileSystemWatcher::fileChanged, - m_clientPlugin.data(), [this](const QString &changedFile) { + m_qmlPreviewClient.data(), [this](const QString &changedFile) { if (!m_fileLoader || !m_lastLoadedUrl.isValid()) return; @@ -205,20 +231,28 @@ void QmlPreviewConnectionManager::createClients() const QString remoteChangedFile = m_targetFileFinder.findPath(changedFile, &success); if (success) - m_clientPlugin->announceFile(remoteChangedFile, contents); + m_qmlPreviewClient->announceFile(remoteChangedFile, contents); else - m_clientPlugin->clearCache(); + m_qmlPreviewClient->clearCache(); - m_clientPlugin->loadUrl(m_lastLoadedUrl); + m_qmlPreviewClient->loadUrl(m_lastLoadedUrl); }); } +void QmlPreviewConnectionManager::clearClient(QObject *client) +{ + if (client) { + disconnect(client, nullptr, this, nullptr); + disconnect(this, nullptr, client, nullptr); + client->deleteLater(); + } +}; + + void QmlPreviewConnectionManager::destroyClients() { - disconnect(m_clientPlugin.data(), nullptr, this, nullptr); - disconnect(this, nullptr, m_clientPlugin.data(), nullptr); - m_clientPlugin->deleteLater(); - m_clientPlugin.clear(); + clearClient(m_qmlPreviewClient); + clearClient(m_qmlDebugTranslationClient); m_fileSystemWatcher.removeFiles(m_fileSystemWatcher.files()); QTC_ASSERT(m_fileSystemWatcher.directories().isEmpty(), m_fileSystemWatcher.removeDirectories(m_fileSystemWatcher.directories())); diff --git a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.h b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.h index 77489cba141..7d87ca79f3f 100644 --- a/src/plugins/qmlpreview/qmlpreviewconnectionmanager.h +++ b/src/plugins/qmlpreview/qmlpreviewconnectionmanager.h @@ -27,6 +27,7 @@ #include "qmlpreviewplugin.h" #include "qmlpreviewclient.h" +#include "qmldebugtranslationclient.h" #include "qmlpreviewfileontargetfinder.h" #include @@ -64,9 +65,14 @@ protected: void destroyClients() override; private: + void createPreviewClient(); + void createDebugTranslationClient(); + QUrl findValidI18nDirectoryAsUrl(const QString &locale); + void clearClient(QObject *client); Utils::FileInProjectFinder m_projectFileFinder; QmlPreviewFileOnTargetFinder m_targetFileFinder; - QPointer m_clientPlugin; + QPointer m_qmlPreviewClient; + QPointer m_qmlDebugTranslationClient; Utils::FileSystemWatcher m_fileSystemWatcher; QUrl m_lastLoadedUrl; QmlPreviewFileLoader m_fileLoader = nullptr;