forked from qt-creator/qt-creator
QmlDesigner: Add image cache
The image cache is saving images and icon of this images in a sqlite database. If there are no images they are generated in the backgound. The icons are fetched by item library. Task-number: QDS-2782 Task-number: QDS-2783 Task-number: QDS-2858 Change-Id: I5a32cccfef7f8fd8eb78902605a09f5da18ce88e Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -151,8 +151,19 @@ public:
|
|||||||
qint32 nodeId = -1;
|
qint32 nodeId = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CapturedDataCommand() = default;
|
||||||
|
|
||||||
|
CapturedDataCommand(QVector<StateData> &&stateData)
|
||||||
|
: stateData{std::move(stateData)}
|
||||||
|
{}
|
||||||
|
|
||||||
|
CapturedDataCommand(QImage &&image)
|
||||||
|
: image{std::move(image)}
|
||||||
|
{}
|
||||||
|
|
||||||
friend QDataStream &operator<<(QDataStream &out, const CapturedDataCommand &command)
|
friend QDataStream &operator<<(QDataStream &out, const CapturedDataCommand &command)
|
||||||
{
|
{
|
||||||
|
out << command.image;
|
||||||
out << command.stateData;
|
out << command.stateData;
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
@@ -160,12 +171,14 @@ public:
|
|||||||
|
|
||||||
friend QDataStream &operator>>(QDataStream &in, CapturedDataCommand &command)
|
friend QDataStream &operator>>(QDataStream &in, CapturedDataCommand &command)
|
||||||
{
|
{
|
||||||
|
in >> command.image;
|
||||||
in >> command.stateData;
|
in >> command.stateData;
|
||||||
|
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
QImage image;
|
||||||
QVector<StateData> stateData;
|
QVector<StateData> stateData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -86,6 +86,7 @@ public:
|
|||||||
virtual void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command) = 0;
|
virtual void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command) = 0;
|
||||||
virtual void changeLanguage(const ChangeLanguageCommand &command) = 0;
|
virtual void changeLanguage(const ChangeLanguageCommand &command) = 0;
|
||||||
virtual void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) = 0;
|
virtual void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) = 0;
|
||||||
|
virtual void dispatchCommand(const QVariant &) {}
|
||||||
|
|
||||||
virtual void benchmark(const QString &) {}
|
virtual void benchmark(const QString &) {}
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ HEADERS += $$PWD/qt5nodeinstanceserver.h \
|
|||||||
$$PWD/capturenodeinstanceserverdispatcher.h \
|
$$PWD/capturenodeinstanceserverdispatcher.h \
|
||||||
$$PWD/capturescenecreatedcommand.h \
|
$$PWD/capturescenecreatedcommand.h \
|
||||||
$$PWD/nodeinstanceserverdispatcher.h \
|
$$PWD/nodeinstanceserverdispatcher.h \
|
||||||
|
$$PWD/qt5captureimagenodeinstanceserver.h \
|
||||||
$$PWD/qt5capturepreviewnodeinstanceserver.h \
|
$$PWD/qt5capturepreviewnodeinstanceserver.h \
|
||||||
$$PWD/qt5testnodeinstanceserver.h \
|
$$PWD/qt5testnodeinstanceserver.h \
|
||||||
$$PWD/qt5informationnodeinstanceserver.h \
|
$$PWD/qt5informationnodeinstanceserver.h \
|
||||||
@@ -33,11 +34,13 @@ HEADERS += $$PWD/qt5nodeinstanceserver.h \
|
|||||||
$$PWD/layoutnodeinstance.h \
|
$$PWD/layoutnodeinstance.h \
|
||||||
$$PWD/qt3dpresentationnodeinstance.h \
|
$$PWD/qt3dpresentationnodeinstance.h \
|
||||||
$$PWD/quick3dnodeinstance.h \
|
$$PWD/quick3dnodeinstance.h \
|
||||||
$$PWD/quick3dtexturenodeinstance.h
|
$$PWD/quick3dtexturenodeinstance.h \
|
||||||
|
|
||||||
|
|
||||||
SOURCES += $$PWD/qt5nodeinstanceserver.cpp \
|
SOURCES += $$PWD/qt5nodeinstanceserver.cpp \
|
||||||
$$PWD/capturenodeinstanceserverdispatcher.cpp \
|
$$PWD/capturenodeinstanceserverdispatcher.cpp \
|
||||||
$$PWD/nodeinstanceserverdispatcher.cpp \
|
$$PWD/nodeinstanceserverdispatcher.cpp \
|
||||||
|
$$PWD/qt5captureimagenodeinstanceserver.cpp \
|
||||||
$$PWD/qt5capturepreviewnodeinstanceserver.cpp \
|
$$PWD/qt5capturepreviewnodeinstanceserver.cpp \
|
||||||
$$PWD/qt5testnodeinstanceserver.cpp \
|
$$PWD/qt5testnodeinstanceserver.cpp \
|
||||||
$$PWD/qt5informationnodeinstanceserver.cpp \
|
$$PWD/qt5informationnodeinstanceserver.cpp \
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "nodeinstanceserverdispatcher.h"
|
#include "nodeinstanceserverdispatcher.h"
|
||||||
|
|
||||||
|
#include "qt5captureimagenodeinstanceserver.h"
|
||||||
#include "qt5capturepreviewnodeinstanceserver.h"
|
#include "qt5capturepreviewnodeinstanceserver.h"
|
||||||
#include "qt5informationnodeinstanceserver.h"
|
#include "qt5informationnodeinstanceserver.h"
|
||||||
#include "qt5rendernodeinstanceserver.h"
|
#include "qt5rendernodeinstanceserver.h"
|
||||||
@@ -183,6 +184,8 @@ std::unique_ptr<NodeInstanceServer> createNodeInstanceServer(
|
|||||||
{
|
{
|
||||||
if (serverName == "capturemode")
|
if (serverName == "capturemode")
|
||||||
return std::make_unique<Qt5CapturePreviewNodeInstanceServer>(nodeInstanceClient);
|
return std::make_unique<Qt5CapturePreviewNodeInstanceServer>(nodeInstanceClient);
|
||||||
|
else if (serverName == "captureiconmode")
|
||||||
|
return std::make_unique<Qt5CaptureImageNodeInstanceServer>(nodeInstanceClient);
|
||||||
else if (serverName == "rendermode")
|
else if (serverName == "rendermode")
|
||||||
return std::make_unique<Qt5RenderNodeInstanceServer>(nodeInstanceClient);
|
return std::make_unique<Qt5RenderNodeInstanceServer>(nodeInstanceClient);
|
||||||
else if (serverName == "editormode")
|
else if (serverName == "editormode")
|
||||||
|
@@ -0,0 +1,84 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "qt5captureimagenodeinstanceserver.h"
|
||||||
|
#include "servernodeinstance.h"
|
||||||
|
|
||||||
|
#include <captureddatacommand.h>
|
||||||
|
#include <createscenecommand.h>
|
||||||
|
#include <nodeinstanceclientinterface.h>
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QQuickView>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QImage renderImage(ServerNodeInstance rootNodeInstance)
|
||||||
|
{
|
||||||
|
rootNodeInstance.updateDirtyNodeRecursive();
|
||||||
|
|
||||||
|
QSize previewImageSize = rootNodeInstance.boundingRect().size().toSize();
|
||||||
|
if (previewImageSize.isEmpty())
|
||||||
|
previewImageSize = {640, 480};
|
||||||
|
|
||||||
|
if (previewImageSize.width() > 800 || previewImageSize.height() > 800)
|
||||||
|
previewImageSize.scale({800, 800}, Qt::KeepAspectRatio);
|
||||||
|
|
||||||
|
QImage previewImage = rootNodeInstance.renderPreviewImage(previewImageSize);
|
||||||
|
|
||||||
|
return previewImage;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Qt5CaptureImageNodeInstanceServer::collectItemChangesAndSendChangeCommands()
|
||||||
|
{
|
||||||
|
static bool inFunction = false;
|
||||||
|
|
||||||
|
if (!rootNodeInstance().holdsGraphical()) {
|
||||||
|
nodeInstanceClient()->capturedData(CapturedDataCommand{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inFunction) {
|
||||||
|
inFunction = true;
|
||||||
|
|
||||||
|
auto rooNodeInstance = rootNodeInstance();
|
||||||
|
rooNodeInstance.rootQuickItem()->setClip(true);
|
||||||
|
|
||||||
|
DesignerSupport::polishItems(quickView());
|
||||||
|
|
||||||
|
QImage image = renderImage(rooNodeInstance);
|
||||||
|
|
||||||
|
nodeInstanceClient()->capturedData(CapturedDataCommand{std::move(image)});
|
||||||
|
|
||||||
|
slowDownRenderTimer();
|
||||||
|
inFunction = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
@@ -0,0 +1,45 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <qt5previewnodeinstanceserver.h>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class Qt5CaptureImageNodeInstanceServer : public Qt5PreviewNodeInstanceServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Qt5CaptureImageNodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient)
|
||||||
|
: Qt5PreviewNodeInstanceServer(nodeInstanceClient)
|
||||||
|
{}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void collectItemChangesAndSendChangeCommands() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -100,7 +100,7 @@ void Qt5CapturePreviewNodeInstanceServer::collectItemChangesAndSendChangeCommand
|
|||||||
stateInstance.deactivateState();
|
stateInstance.deactivateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeInstanceClient()->capturedData(CapturedDataCommand{stateDatas});
|
nodeInstanceClient()->capturedData(CapturedDataCommand{std::move(stateDatas)});
|
||||||
|
|
||||||
slowDownRenderTimer();
|
slowDownRenderTimer();
|
||||||
inFunction = false;
|
inFunction = false;
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
#include "capturenodeinstanceserverdispatcher.h"
|
#include "capturenodeinstanceserverdispatcher.h"
|
||||||
|
#include "qt5captureimagenodeinstanceserver.h"
|
||||||
#include "qt5capturepreviewnodeinstanceserver.h"
|
#include "qt5capturepreviewnodeinstanceserver.h"
|
||||||
#include "qt5informationnodeinstanceserver.h"
|
#include "qt5informationnodeinstanceserver.h"
|
||||||
#include "qt5previewnodeinstanceserver.h"
|
#include "qt5previewnodeinstanceserver.h"
|
||||||
@@ -92,6 +93,9 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
|
|||||||
} else if (QCoreApplication::arguments().at(2) == QLatin1String("capturemode")) {
|
} else if (QCoreApplication::arguments().at(2) == QLatin1String("capturemode")) {
|
||||||
setNodeInstanceServer(std::make_unique<Qt5CapturePreviewNodeInstanceServer>(this));
|
setNodeInstanceServer(std::make_unique<Qt5CapturePreviewNodeInstanceServer>(this));
|
||||||
initializeSocket();
|
initializeSocket();
|
||||||
|
} else if (QCoreApplication::arguments().at(2) == QLatin1String("captureiconmode")) {
|
||||||
|
setNodeInstanceServer(std::make_unique<Qt5CaptureImageNodeInstanceServer>(this));
|
||||||
|
initializeSocket();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -566,7 +566,7 @@ QRectF QuickItemNodeInstance::boundingRectWithStepChilds(QQuickItem *parentItem)
|
|||||||
|
|
||||||
boundingRect = boundingRect.united(QRectF(QPointF(0, 0), size()));
|
boundingRect = boundingRect.united(QRectF(QPointF(0, 0), size()));
|
||||||
|
|
||||||
foreach (QQuickItem *childItem, parentItem->childItems()) {
|
for (QQuickItem *childItem : parentItem->childItems()) {
|
||||||
if (!nodeInstanceServer()->hasInstanceForObject(childItem)) {
|
if (!nodeInstanceServer()->hasInstanceForObject(childItem)) {
|
||||||
QRectF transformedRect = childItem->mapRectToItem(parentItem, boundingRectWithStepChilds(childItem));
|
QRectF transformedRect = childItem->mapRectToItem(parentItem, boundingRectWithStepChilds(childItem));
|
||||||
if (isRectangleSane(transformedRect))
|
if (isRectangleSane(transformedRect))
|
||||||
@@ -574,6 +574,9 @@ QRectF QuickItemNodeInstance::boundingRectWithStepChilds(QQuickItem *parentItem)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (boundingRect.isEmpty())
|
||||||
|
QRectF{0, 0, 640, 480};
|
||||||
|
|
||||||
return boundingRect;
|
return boundingRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -42,9 +42,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
int internalMain(QGuiApplication *application)
|
int internalMain(QGuiApplication *application)
|
||||||
{
|
{
|
||||||
QCoreApplication::setOrganizationName("QtProject");
|
QCoreApplication::setOrganizationName("QtProject");
|
||||||
@@ -138,6 +140,7 @@ int internalMain(QGuiApplication *application)
|
|||||||
|
|
||||||
return application->exec();
|
return application->exec();
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@@ -46,8 +46,6 @@ Item {
|
|||||||
width: itemLibraryIconWidth // to be set in Qml context
|
width: itemLibraryIconWidth // to be set in Qml context
|
||||||
height: itemLibraryIconHeight // to be set in Qml context
|
height: itemLibraryIconHeight // to be set in Qml context
|
||||||
source: itemLibraryIconPath // to be set by model
|
source: itemLibraryIconPath // to be set by model
|
||||||
|
|
||||||
cache: false // Allow thumbnail to be dynamically updated
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
@@ -71,10 +69,11 @@ Item {
|
|||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolTipArea {
|
ImagePreviewTooltipArea {
|
||||||
id: mouseRegion
|
id: mouseRegion
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
tooltip: itemName
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
rootView.startDragAndDrop(mouseRegion, itemLibraryEntry)
|
rootView.startDragAndDrop(mouseRegion, itemLibraryEntry)
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,48 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
import QtQuick 2.1
|
||||||
|
import HelperWidgets 2.0
|
||||||
|
import QtQuick.Layouts 1.0
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
|
||||||
|
onExited: tooltipBackend.hideTooltip()
|
||||||
|
onCanceled: tooltipBackend.hideTooltip()
|
||||||
|
onClicked: forceActiveFocus()
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 1000
|
||||||
|
running: mouseArea.containsMouse
|
||||||
|
onTriggered: {
|
||||||
|
tooltipBackend.componentName = itemName
|
||||||
|
tooltipBackend.componentPath = componentPath
|
||||||
|
tooltipBackend.showTooltip()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -47,3 +47,4 @@ ExpressionTextField 2.0 ExpressionTextField.qml
|
|||||||
MarginSection 2.0 MarginSection.qml
|
MarginSection 2.0 MarginSection.qml
|
||||||
HorizontalScrollBar 2.0 HorizontalScrollBar.qml
|
HorizontalScrollBar 2.0 HorizontalScrollBar.qml
|
||||||
VerticalScrollBar 2.0 VerticalScrollBar.qml
|
VerticalScrollBar 2.0 VerticalScrollBar.qml
|
||||||
|
ImagePreviewTooltipArea 2.0 ImagePreviewTooltipArea.qml
|
||||||
|
@@ -44,4 +44,6 @@ add_qtc_library(Sqlite
|
|||||||
tableconstraints.h
|
tableconstraints.h
|
||||||
utf8string.cpp utf8string.h
|
utf8string.cpp utf8string.h
|
||||||
utf8stringvector.cpp utf8stringvector.h
|
utf8stringvector.cpp utf8stringvector.h
|
||||||
|
sqliteblob.h
|
||||||
|
sqlitetimestamp.h
|
||||||
)
|
)
|
||||||
|
@@ -27,6 +27,8 @@ SOURCES += \
|
|||||||
$$PWD/sqlitebasestatement.cpp
|
$$PWD/sqlitebasestatement.cpp
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/constraints.h \
|
$$PWD/constraints.h \
|
||||||
|
$$PWD/sqliteblob.h \
|
||||||
|
$$PWD/sqlitetimestamp.h \
|
||||||
$$PWD/tableconstraints.h \
|
$$PWD/tableconstraints.h \
|
||||||
$$PWD/createtablesqlstatementbuilder.h \
|
$$PWD/createtablesqlstatementbuilder.h \
|
||||||
$$PWD/lastchangedrowid.h \
|
$$PWD/lastchangedrowid.h \
|
||||||
|
@@ -191,12 +191,12 @@ void BaseStatement::bind(int index, Utils::SmallStringView text)
|
|||||||
checkForBindingError(resultCode);
|
checkForBindingError(resultCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseStatement::bind(int index, Utils::span<const byte> bytes)
|
void BaseStatement::bind(int index, BlobView blobView)
|
||||||
{
|
{
|
||||||
int resultCode = sqlite3_bind_blob64(m_compiledStatement.get(),
|
int resultCode = sqlite3_bind_blob64(m_compiledStatement.get(),
|
||||||
index,
|
index,
|
||||||
bytes.data(),
|
blobView.data(),
|
||||||
static_cast<long long>(bytes.size()),
|
blobView.size(),
|
||||||
SQLITE_STATIC);
|
SQLITE_STATIC);
|
||||||
if (resultCode != SQLITE_OK)
|
if (resultCode != SQLITE_OK)
|
||||||
checkForBindingError(resultCode);
|
checkForBindingError(resultCode);
|
||||||
@@ -498,7 +498,7 @@ StringType textForColumn(sqlite3_stmt *sqlStatment, int column)
|
|||||||
return StringType(text, size);
|
return StringType(text, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::span<const byte> blobForColumn(sqlite3_stmt *sqlStatment, int column)
|
BlobView blobForColumn(sqlite3_stmt *sqlStatment, int column)
|
||||||
{
|
{
|
||||||
const byte *blob = reinterpret_cast<const byte *>(sqlite3_column_blob(sqlStatment, column));
|
const byte *blob = reinterpret_cast<const byte *>(sqlite3_column_blob(sqlStatment, column));
|
||||||
std::size_t size = std::size_t(sqlite3_column_bytes(sqlStatment, column));
|
std::size_t size = std::size_t(sqlite3_column_bytes(sqlStatment, column));
|
||||||
@@ -506,7 +506,7 @@ Utils::span<const byte> blobForColumn(sqlite3_stmt *sqlStatment, int column)
|
|||||||
return {blob, size};
|
return {blob, size};
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::span<const byte> convertToBlobForColumn(sqlite3_stmt *sqlStatment, int column)
|
BlobView convertToBlobForColumn(sqlite3_stmt *sqlStatment, int column)
|
||||||
{
|
{
|
||||||
int dataType = sqlite3_column_type(sqlStatment, column);
|
int dataType = sqlite3_column_type(sqlStatment, column);
|
||||||
if (dataType == SQLITE_BLOB)
|
if (dataType == SQLITE_BLOB)
|
||||||
@@ -571,7 +571,7 @@ double BaseStatement::fetchDoubleValue(int column) const
|
|||||||
return sqlite3_column_double(m_compiledStatement.get(), column);
|
return sqlite3_column_double(m_compiledStatement.get(), column);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::span<const byte> BaseStatement::fetchBlobValue(int column) const
|
BlobView BaseStatement::fetchBlobValue(int column) const
|
||||||
{
|
{
|
||||||
return convertToBlobForColumn(m_compiledStatement.get(), column);
|
return convertToBlobForColumn(m_compiledStatement.get(), column);
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "sqliteglobal.h"
|
#include "sqliteglobal.h"
|
||||||
|
|
||||||
|
#include "sqliteblob.h"
|
||||||
#include "sqliteexception.h"
|
#include "sqliteexception.h"
|
||||||
#include "sqlitevalue.h"
|
#include "sqlitevalue.h"
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ public:
|
|||||||
double fetchDoubleValue(int column) const;
|
double fetchDoubleValue(int column) const;
|
||||||
Utils::SmallStringView fetchSmallStringViewValue(int column) const;
|
Utils::SmallStringView fetchSmallStringViewValue(int column) const;
|
||||||
ValueView fetchValueView(int column) const;
|
ValueView fetchValueView(int column) const;
|
||||||
Utils::span<const byte> fetchBlobValue(int column) const;
|
BlobView fetchBlobValue(int column) const;
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
Type fetchValue(int column) const;
|
Type fetchValue(int column) const;
|
||||||
int columnCount() const;
|
int columnCount() const;
|
||||||
@@ -82,7 +83,7 @@ public:
|
|||||||
void bind(int index, void *pointer);
|
void bind(int index, void *pointer);
|
||||||
void bind(int index, Utils::SmallStringView fetchValue);
|
void bind(int index, Utils::SmallStringView fetchValue);
|
||||||
void bind(int index, const Value &fetchValue);
|
void bind(int index, const Value &fetchValue);
|
||||||
void bind(int index, Utils::span<const byte> bytes);
|
void bind(int index, BlobView blobView);
|
||||||
|
|
||||||
void bind(int index, uint value) { bind(index, static_cast<long long>(value)); }
|
void bind(int index, uint value) { bind(index, static_cast<long long>(value)); }
|
||||||
|
|
||||||
@@ -358,7 +359,7 @@ private:
|
|||||||
operator long long() { return statement.fetchLongLongValue(column); }
|
operator long long() { return statement.fetchLongLongValue(column); }
|
||||||
operator double() { return statement.fetchDoubleValue(column); }
|
operator double() { return statement.fetchDoubleValue(column); }
|
||||||
operator Utils::SmallStringView() { return statement.fetchSmallStringViewValue(column); }
|
operator Utils::SmallStringView() { return statement.fetchSmallStringViewValue(column); }
|
||||||
operator Utils::span<const Sqlite::byte>() { return statement.fetchBlobValue(column); }
|
operator BlobView() { return statement.fetchBlobValue(column); }
|
||||||
operator ValueView() { return statement.fetchValueView(column); }
|
operator ValueView() { return statement.fetchValueView(column); }
|
||||||
|
|
||||||
StatementImplementation &statement;
|
StatementImplementation &statement;
|
||||||
|
100
src/libs/sqlite/sqliteblob.h
Normal file
100
src/libs/sqlite/sqliteblob.h
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "sqliteglobal.h"
|
||||||
|
|
||||||
|
#include <utils/span.h>
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
|
||||||
|
class BlobView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BlobView() = default;
|
||||||
|
|
||||||
|
BlobView(const byte *data, std::size_t size)
|
||||||
|
: m_data(data)
|
||||||
|
, m_size(size)
|
||||||
|
{}
|
||||||
|
|
||||||
|
BlobView(const QByteArray &byteArray)
|
||||||
|
: m_data(reinterpret_cast<const byte *>(byteArray.constData()))
|
||||||
|
, m_size(static_cast<std::size_t>(byteArray.size()))
|
||||||
|
{}
|
||||||
|
|
||||||
|
BlobView(const std::vector<Sqlite::byte> &bytes)
|
||||||
|
: m_data(bytes.data())
|
||||||
|
, m_size(static_cast<std::size_t>(bytes.size()))
|
||||||
|
{}
|
||||||
|
|
||||||
|
const byte *data() const { return m_data; }
|
||||||
|
const char *cdata() const { return reinterpret_cast<const char *>(m_data); }
|
||||||
|
std::size_t size() const { return m_size; }
|
||||||
|
int sisize() const { return static_cast<int>(m_size); }
|
||||||
|
long long ssize() const { return static_cast<long long>(m_size); }
|
||||||
|
bool empty() const { return !m_size; }
|
||||||
|
|
||||||
|
friend bool operator==(Sqlite::BlobView first, Sqlite::BlobView second)
|
||||||
|
{
|
||||||
|
return first.size() == second.size()
|
||||||
|
&& std::memcmp(first.data(), second.data(), first.size()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const byte *m_data{};
|
||||||
|
std::size_t m_size{};
|
||||||
|
};
|
||||||
|
|
||||||
|
class Blob
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Blob(BlobView blobView)
|
||||||
|
{
|
||||||
|
bytes.reserve(blobView.size());
|
||||||
|
std::copy_n(blobView.data(), blobView.size(), std::back_inserter(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Sqlite::byte> bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ByteArrayBlob
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ByteArrayBlob(BlobView blobView)
|
||||||
|
: byteArray{blobView.cdata(), blobView.sisize()}
|
||||||
|
{}
|
||||||
|
|
||||||
|
QByteArray byteArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Sqlite
|
@@ -46,7 +46,7 @@ void checkResultCode(int resultCode)
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
SessionChangeSet::SessionChangeSet(Utils::span<const byte> blob)
|
SessionChangeSet::SessionChangeSet(BlobView blob)
|
||||||
: data(sqlite3_malloc64(blob.size()))
|
: data(sqlite3_malloc64(blob.size()))
|
||||||
, size(int(blob.size()))
|
, size(int(blob.size()))
|
||||||
{
|
{
|
||||||
@@ -64,7 +64,7 @@ SessionChangeSet::~SessionChangeSet()
|
|||||||
sqlite3_free(data);
|
sqlite3_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::span<const byte> SessionChangeSet::asSpan() const
|
BlobView SessionChangeSet::asBlobView() const
|
||||||
{
|
{
|
||||||
return {static_cast<const byte *>(data), static_cast<std::size_t>(size)};
|
return {static_cast<const byte *>(data), static_cast<std::size_t>(size)};
|
||||||
}
|
}
|
||||||
|
@@ -25,10 +25,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "sqliteblob.h"
|
||||||
#include "sqliteglobal.h"
|
#include "sqliteglobal.h"
|
||||||
|
|
||||||
#include <utils/span.h>
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@ class Sessions;
|
|||||||
class SessionChangeSet
|
class SessionChangeSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SessionChangeSet(Utils::span<const byte> blob);
|
SessionChangeSet(BlobView blob);
|
||||||
SessionChangeSet(Sessions &session);
|
SessionChangeSet(Sessions &session);
|
||||||
~SessionChangeSet();
|
~SessionChangeSet();
|
||||||
SessionChangeSet(const SessionChangeSet &) = delete;
|
SessionChangeSet(const SessionChangeSet &) = delete;
|
||||||
@@ -54,7 +53,7 @@ public:
|
|||||||
}
|
}
|
||||||
void operator=(SessionChangeSet &);
|
void operator=(SessionChangeSet &);
|
||||||
|
|
||||||
Utils::span<const byte> asSpan() const;
|
BlobView asBlobView() const;
|
||||||
|
|
||||||
friend void swap(SessionChangeSet &first, SessionChangeSet &second) noexcept
|
friend void swap(SessionChangeSet &first, SessionChangeSet &second) noexcept
|
||||||
{
|
{
|
||||||
|
@@ -103,7 +103,7 @@ void Sessions::commit()
|
|||||||
if (session && !sqlite3session_isempty(session.get())) {
|
if (session && !sqlite3session_isempty(session.get())) {
|
||||||
SessionChangeSet changeSet{*this};
|
SessionChangeSet changeSet{*this};
|
||||||
|
|
||||||
insertSession.write(changeSet.asSpan());
|
insertSession.write(changeSet.asBlobView());
|
||||||
}
|
}
|
||||||
|
|
||||||
session.reset();
|
session.reset();
|
||||||
|
47
src/libs/sqlite/sqlitetimestamp.h
Normal file
47
src/libs/sqlite/sqlitetimestamp.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
|
||||||
|
namespace Sqlite {
|
||||||
|
|
||||||
|
class TimeStamp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TimeStamp() = default;
|
||||||
|
TimeStamp(long long value)
|
||||||
|
: value(value)
|
||||||
|
{}
|
||||||
|
|
||||||
|
friend bool operator==(TimeStamp first, TimeStamp second)
|
||||||
|
{
|
||||||
|
return first.value == second.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
long long value = -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Sqlite
|
@@ -23,6 +23,8 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include "sqliteexception.h"
|
#include "sqliteexception.h"
|
||||||
|
|
||||||
#include <utils/smallstring.h>
|
#include <utils/smallstring.h>
|
||||||
@@ -32,9 +34,6 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Sqlite {
|
namespace Sqlite {
|
||||||
|
|
||||||
enum class ValueType : unsigned char { Null, Integer, Float, String };
|
enum class ValueType : unsigned char { Null, Integer, Float, String };
|
||||||
|
@@ -53,9 +53,11 @@ class PROJECTEXPLORER_EXPORT Target : public QObject
|
|||||||
friend class SessionManager; // for setActiveBuild and setActiveDeployConfiguration
|
friend class SessionManager; // for setActiveBuild and setActiveDeployConfiguration
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
struct _constructor_tag { explicit _constructor_tag() = default; };
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct _constructor_tag
|
||||||
|
{
|
||||||
|
explicit _constructor_tag() = default;
|
||||||
|
};
|
||||||
Target(Project *parent, Kit *k, _constructor_tag);
|
Target(Project *parent, Kit *k, _constructor_tag);
|
||||||
~Target() override;
|
~Target() override;
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ endif()
|
|||||||
add_qtc_plugin(QmlDesigner
|
add_qtc_plugin(QmlDesigner
|
||||||
DEPENDS
|
DEPENDS
|
||||||
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
|
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
|
||||||
Qt5::QuickWidgets Qt5::CorePrivate
|
Qt5::QuickWidgets Qt5::CorePrivate Sqlite
|
||||||
DEFINES
|
DEFINES
|
||||||
DESIGNER_CORE_LIBRARY
|
DESIGNER_CORE_LIBRARY
|
||||||
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
|
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
|
||||||
@@ -317,6 +317,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
itemlibraryassetimportdialog.cpp itemlibraryassetimportdialog.h
|
itemlibraryassetimportdialog.cpp itemlibraryassetimportdialog.h
|
||||||
itemlibraryassetimportdialog.ui
|
itemlibraryassetimportdialog.ui
|
||||||
itemlibraryassetimporter.cpp itemlibraryassetimporter.h
|
itemlibraryassetimporter.cpp itemlibraryassetimporter.h
|
||||||
|
itemlibraryiconimageprovider.cpp itemlibraryiconimageprovider.h
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS Quick3DAssetImport QUIET)
|
find_package(Qt5 COMPONENTS Quick3DAssetImport QUIET)
|
||||||
@@ -502,6 +503,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
include/textmodifier.h
|
include/textmodifier.h
|
||||||
include/variantproperty.h
|
include/variantproperty.h
|
||||||
include/viewmanager.h
|
include/viewmanager.h
|
||||||
|
include/imagecache.h
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
@@ -586,6 +588,21 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
pluginmanager/widgetpluginmanager.cpp pluginmanager/widgetpluginmanager.h
|
pluginmanager/widgetpluginmanager.cpp pluginmanager/widgetpluginmanager.h
|
||||||
pluginmanager/widgetpluginpath.cpp pluginmanager/widgetpluginpath.h
|
pluginmanager/widgetpluginpath.cpp pluginmanager/widgetpluginpath.h
|
||||||
rewritertransaction.cpp rewritertransaction.h
|
rewritertransaction.cpp rewritertransaction.h
|
||||||
|
|
||||||
|
imagecache/imagecachecollector.h
|
||||||
|
imagecache/imagecachecollector.cpp
|
||||||
|
imagecache/imagecache.cpp
|
||||||
|
imagecache/imagecachecollectorinterface.h
|
||||||
|
imagecache/imagecacheconnectionmanager.cpp
|
||||||
|
imagecache/imagecacheconnectionmanager.h
|
||||||
|
imagecache/imagecachegenerator.cpp
|
||||||
|
imagecache/imagecachegenerator.h
|
||||||
|
imagecache/imagecachestorage.h
|
||||||
|
imagecache/imagecachegeneratorinterface.h
|
||||||
|
imagecache/imagecachestorageinterface.h
|
||||||
|
imagecache/timestampproviderinterface.h
|
||||||
|
imagecache/timestampprovider.h
|
||||||
|
imagecache/timestampprovider.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
|
@@ -7,6 +7,7 @@ qtHaveModule(quick3dassetimport) {
|
|||||||
|
|
||||||
# Input
|
# Input
|
||||||
HEADERS += itemlibraryview.h \
|
HEADERS += itemlibraryview.h \
|
||||||
|
$$PWD/itemlibraryiconimageprovider.h \
|
||||||
itemlibrarywidget.h \
|
itemlibrarywidget.h \
|
||||||
itemlibrarymodel.h \
|
itemlibrarymodel.h \
|
||||||
itemlibraryresourceview.h \
|
itemlibraryresourceview.h \
|
||||||
@@ -19,6 +20,7 @@ HEADERS += itemlibraryview.h \
|
|||||||
customfilesystemmodel.h
|
customfilesystemmodel.h
|
||||||
|
|
||||||
SOURCES += itemlibraryview.cpp \
|
SOURCES += itemlibraryview.cpp \
|
||||||
|
$$PWD/itemlibraryiconimageprovider.cpp \
|
||||||
itemlibrarywidget.cpp \
|
itemlibrarywidget.cpp \
|
||||||
itemlibrarymodel.cpp \
|
itemlibrarymodel.cpp \
|
||||||
itemlibraryresourceview.cpp \
|
itemlibraryresourceview.cpp \
|
||||||
|
@@ -502,7 +502,6 @@ bool ItemLibraryAssetImporter::generateComponentIcon(int size, const QString &ic
|
|||||||
QProcessUniquePointer process = puppetCreator.createPuppetProcess(
|
QProcessUniquePointer process = puppetCreator.createPuppetProcess(
|
||||||
"custom",
|
"custom",
|
||||||
{},
|
{},
|
||||||
this,
|
|
||||||
std::function<void()>(),
|
std::function<void()>(),
|
||||||
[&](int exitCode, QProcess::ExitStatus exitStatus) {
|
[&](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||||
processFinished(exitCode, exitStatus);
|
processFinished(exitCode, exitStatus);
|
||||||
|
@@ -0,0 +1,93 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "itemlibraryiconimageprovider.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <utils/stylehelper.h>
|
||||||
|
|
||||||
|
#include <QMetaObject>
|
||||||
|
#include <QQuickImageResponse>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ImageRespose : public QQuickImageResponse
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QQuickTextureFactory *textureFactory() const override
|
||||||
|
{
|
||||||
|
return QQuickTextureFactory::textureFactoryForImage(m_image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setImage(const QImage &image)
|
||||||
|
{
|
||||||
|
m_image = image;
|
||||||
|
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void abort()
|
||||||
|
{
|
||||||
|
m_image = QImage{
|
||||||
|
Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/item-default-icon.png")};
|
||||||
|
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QImage m_image;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
QQuickImageResponse *ItemLibraryIconImageProvider::requestImageResponse(const QString &id,
|
||||||
|
const QSize &)
|
||||||
|
{
|
||||||
|
auto response = std::make_unique<ImageRespose>();
|
||||||
|
|
||||||
|
m_cache.requestIcon(
|
||||||
|
id,
|
||||||
|
[response = QPointer<ImageRespose>(response.get())](const QImage &image) {
|
||||||
|
QMetaObject::invokeMethod(
|
||||||
|
response,
|
||||||
|
[response, image] {
|
||||||
|
if (response)
|
||||||
|
response->setImage(image);
|
||||||
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
},
|
||||||
|
[response = QPointer<ImageRespose>(response.get())] {
|
||||||
|
QMetaObject::invokeMethod(
|
||||||
|
response,
|
||||||
|
[response] {
|
||||||
|
if (response)
|
||||||
|
response->abort();
|
||||||
|
},
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,58 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <nodeinstanceview.h>
|
||||||
|
#include <rewriterview.h>
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <imagecache.h>
|
||||||
|
#include <imagecache/imagecachecollector.h>
|
||||||
|
#include <imagecache/imagecacheconnectionmanager.h>
|
||||||
|
#include <imagecache/imagecachegenerator.h>
|
||||||
|
#include <imagecache/imagecachestorage.h>
|
||||||
|
#include <imagecache/timestampprovider.h>
|
||||||
|
|
||||||
|
#include <sqlitedatabase.h>
|
||||||
|
|
||||||
|
#include <QQuickAsyncImageProvider>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ItemLibraryIconImageProvider : public QQuickAsyncImageProvider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ItemLibraryIconImageProvider(ImageCache &imageCache)
|
||||||
|
: m_cache{imageCache}
|
||||||
|
{}
|
||||||
|
|
||||||
|
QQuickImageResponse *requestImageResponse(const QString &id, const QSize &requestedSize) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ImageCache &m_cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -47,8 +47,18 @@ QString ItemLibraryItem::typeName() const
|
|||||||
|
|
||||||
QString ItemLibraryItem::itemLibraryIconPath() const
|
QString ItemLibraryItem::itemLibraryIconPath() const
|
||||||
{
|
{
|
||||||
//Prepend image provider prefix
|
if (m_itemLibraryEntry.customComponentSource().isEmpty()) {
|
||||||
return QStringLiteral("image://qmldesigner_itemlibrary/") + m_itemLibraryEntry.libraryEntryIconPath();
|
return QStringLiteral("image://qmldesigner_itemlibrary/")
|
||||||
|
+ m_itemLibraryEntry.libraryEntryIconPath();
|
||||||
|
} else {
|
||||||
|
return QStringLiteral("image://itemlibrary_preview/")
|
||||||
|
+ m_itemLibraryEntry.customComponentSource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ItemLibraryItem::componentPath() const
|
||||||
|
{
|
||||||
|
return m_itemLibraryEntry.customComponentSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ItemLibraryItem::setVisible(bool isVisible)
|
bool ItemLibraryItem::setVisible(bool isVisible)
|
||||||
|
@@ -42,6 +42,7 @@ class ItemLibraryItem: public QObject {
|
|||||||
Q_PROPERTY(QString itemName READ itemName FINAL)
|
Q_PROPERTY(QString itemName READ itemName FINAL)
|
||||||
Q_PROPERTY(QString itemLibraryIconPath READ itemLibraryIconPath FINAL)
|
Q_PROPERTY(QString itemLibraryIconPath READ itemLibraryIconPath FINAL)
|
||||||
Q_PROPERTY(bool itemVisible READ isVisible NOTIFY visibilityChanged FINAL)
|
Q_PROPERTY(bool itemVisible READ isVisible NOTIFY visibilityChanged FINAL)
|
||||||
|
Q_PROPERTY(QString componentPath READ componentPath FINAL)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ItemLibraryItem(QObject *parent);
|
ItemLibraryItem(QObject *parent);
|
||||||
@@ -50,6 +51,7 @@ public:
|
|||||||
QString itemName() const;
|
QString itemName() const;
|
||||||
QString typeName() const;
|
QString typeName() const;
|
||||||
QString itemLibraryIconPath() const;
|
QString itemLibraryIconPath() const;
|
||||||
|
QString componentPath() const;
|
||||||
|
|
||||||
bool setVisible(bool isVisible);
|
bool setVisible(bool isVisible);
|
||||||
bool isVisible() const;
|
bool isVisible() const;
|
||||||
|
@@ -29,6 +29,8 @@
|
|||||||
#include "itemlibraryitem.h"
|
#include "itemlibraryitem.h"
|
||||||
#include "itemlibrarysection.h"
|
#include "itemlibrarysection.h"
|
||||||
|
|
||||||
|
#include <components/previewtooltip/previewtooltipbackend.h>
|
||||||
|
|
||||||
#include <model.h>
|
#include <model.h>
|
||||||
#include <nodehints.h>
|
#include <nodehints.h>
|
||||||
#include <nodemetainfo.h>
|
#include <nodemetainfo.h>
|
||||||
|
@@ -25,24 +25,47 @@
|
|||||||
|
|
||||||
#include "itemlibraryview.h"
|
#include "itemlibraryview.h"
|
||||||
#include "itemlibrarywidget.h"
|
#include "itemlibrarywidget.h"
|
||||||
|
#include "metainfo.h"
|
||||||
|
#include <bindingproperty.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <imagecache.h>
|
||||||
|
#include <imagecache/imagecachecollector.h>
|
||||||
|
#include <imagecache/imagecacheconnectionmanager.h>
|
||||||
|
#include <imagecache/imagecachegenerator.h>
|
||||||
|
#include <imagecache/imagecachestorage.h>
|
||||||
|
#include <imagecache/timestampprovider.h>
|
||||||
#include <import.h>
|
#include <import.h>
|
||||||
#include <importmanagerview.h>
|
#include <importmanagerview.h>
|
||||||
#include <qmlitemnode.h>
|
|
||||||
#include <rewriterview.h>
|
|
||||||
#include <bindingproperty.h>
|
|
||||||
#include <nodelistproperty.h>
|
#include <nodelistproperty.h>
|
||||||
|
#include <projectexplorer/kit.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <rewriterview.h>
|
||||||
|
#include <sqlitedatabase.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <qmldesignerplugin.h>
|
#include <qmldesignerplugin.h>
|
||||||
#include "metainfo.h"
|
#include <qmlitemnode.h>
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ImageCacheData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sqlite::Database database{
|
||||||
|
Utils::PathString{Core::ICore::cacheResourcePath() + "/imagecache-v1.db"}};
|
||||||
|
ImageCacheStorage<Sqlite::Database> storage{database};
|
||||||
|
ImageCacheConnectionManager connectionManager;
|
||||||
|
ImageCacheCollector collector{connectionManager};
|
||||||
|
ImageCacheGenerator generator{collector, storage};
|
||||||
|
TimeStampProvider timeStampProvider;
|
||||||
|
ImageCache cache{storage, generator, timeStampProvider};
|
||||||
|
};
|
||||||
|
|
||||||
ItemLibraryView::ItemLibraryView(QObject* parent)
|
ItemLibraryView::ItemLibraryView(QObject* parent)
|
||||||
: AbstractView(parent),
|
: AbstractView(parent),
|
||||||
m_importManagerView(new ImportManagerView(this))
|
m_importManagerView(new ImportManagerView(this))
|
||||||
|
|
||||||
{
|
{
|
||||||
|
m_imageCacheData = std::make_unique<ImageCacheData>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemLibraryView::~ItemLibraryView() = default;
|
ItemLibraryView::~ItemLibraryView() = default;
|
||||||
@@ -55,7 +78,7 @@ bool ItemLibraryView::hasWidget() const
|
|||||||
WidgetInfo ItemLibraryView::widgetInfo()
|
WidgetInfo ItemLibraryView::widgetInfo()
|
||||||
{
|
{
|
||||||
if (m_widget.isNull()) {
|
if (m_widget.isNull()) {
|
||||||
m_widget = new ItemLibraryWidget;
|
m_widget = new ItemLibraryWidget{m_imageCacheData->cache};
|
||||||
m_widget->setImportsWidget(m_importManagerView->widgetInfo().widget);
|
m_widget->setImportsWidget(m_importManagerView->widgetInfo().widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +93,16 @@ WidgetInfo ItemLibraryView::widgetInfo()
|
|||||||
void ItemLibraryView::modelAttached(Model *model)
|
void ItemLibraryView::modelAttached(Model *model)
|
||||||
{
|
{
|
||||||
AbstractView::modelAttached(model);
|
AbstractView::modelAttached(model);
|
||||||
|
auto target = QmlDesignerPlugin::instance()->currentDesignDocument()->currentTarget();
|
||||||
|
m_imageCacheData->cache.clean();
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
auto clonedTarget = std::make_unique<ProjectExplorer::Target>(
|
||||||
|
target->project(), target->kit()->clone(), ProjectExplorer::Target::_constructor_tag{});
|
||||||
|
|
||||||
|
m_imageCacheData->collector.setTarget(std::move(clonedTarget));
|
||||||
|
}
|
||||||
|
|
||||||
m_widget->clearSearchFilter();
|
m_widget->clearSearchFilter();
|
||||||
m_widget->setModel(model);
|
m_widget->setModel(model);
|
||||||
updateImports();
|
updateImports();
|
||||||
@@ -83,6 +116,8 @@ void ItemLibraryView::modelAboutToBeDetached(Model *model)
|
|||||||
{
|
{
|
||||||
model->detachView(m_importManagerView);
|
model->detachView(m_importManagerView);
|
||||||
|
|
||||||
|
m_imageCacheData->collector.setTarget({});
|
||||||
|
|
||||||
AbstractView::modelAboutToBeDetached(model);
|
AbstractView::modelAboutToBeDetached(model);
|
||||||
|
|
||||||
m_widget->setModel(nullptr);
|
m_widget->setModel(nullptr);
|
||||||
@@ -124,7 +159,7 @@ void ItemLibraryView::importsChanged(const QList<Import> &addedImports, const QL
|
|||||||
void ItemLibraryView::setResourcePath(const QString &resourcePath)
|
void ItemLibraryView::setResourcePath(const QString &resourcePath)
|
||||||
{
|
{
|
||||||
if (m_widget.isNull())
|
if (m_widget.isNull())
|
||||||
m_widget = new ItemLibraryWidget;
|
m_widget = new ItemLibraryWidget{m_imageCacheData->cache};
|
||||||
|
|
||||||
m_widget->setResourcePath(resourcePath);
|
m_widget->setResourcePath(resourcePath);
|
||||||
}
|
}
|
||||||
@@ -142,4 +177,4 @@ void ItemLibraryView::updateImports()
|
|||||||
m_widget->delayedUpdateModel();
|
m_widget->delayedUpdateModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
} //QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -34,6 +34,7 @@ namespace QmlDesigner {
|
|||||||
|
|
||||||
class ItemLibraryWidget;
|
class ItemLibraryWidget;
|
||||||
class ImportManagerView;
|
class ImportManagerView;
|
||||||
|
class ImageCacheData;
|
||||||
|
|
||||||
class ItemLibraryView : public AbstractView
|
class ItemLibraryView : public AbstractView
|
||||||
{
|
{
|
||||||
@@ -58,6 +59,7 @@ protected:
|
|||||||
void updateImports();
|
void updateImports();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unique_ptr<ImageCacheData> m_imageCacheData;
|
||||||
QPointer<ItemLibraryWidget> m_widget;
|
QPointer<ItemLibraryWidget> m_widget;
|
||||||
ImportManagerView *m_importManagerView;
|
ImportManagerView *m_importManagerView;
|
||||||
bool m_hasErrors = false;
|
bool m_hasErrors = false;
|
||||||
|
@@ -27,19 +27,21 @@
|
|||||||
|
|
||||||
#include "customfilesystemmodel.h"
|
#include "customfilesystemmodel.h"
|
||||||
#include "itemlibraryassetimportdialog.h"
|
#include "itemlibraryassetimportdialog.h"
|
||||||
|
#include "itemlibraryiconimageprovider.h"
|
||||||
|
|
||||||
#include <theme.h>
|
#include <theme.h>
|
||||||
|
|
||||||
#include <itemlibrarymodel.h>
|
|
||||||
#include <itemlibraryimageprovider.h>
|
|
||||||
#include <itemlibraryinfo.h>
|
|
||||||
#include <metainfo.h>
|
|
||||||
#include <model.h>
|
|
||||||
#include <rewritingexception.h>
|
|
||||||
#include <qmldesignerplugin.h>
|
|
||||||
#include <qmldesignerconstants.h>
|
|
||||||
#include <designeractionmanager.h>
|
#include <designeractionmanager.h>
|
||||||
#include <designermcumanager.h>
|
#include <designermcumanager.h>
|
||||||
|
#include <itemlibraryimageprovider.h>
|
||||||
|
#include <itemlibraryinfo.h>
|
||||||
|
#include <itemlibrarymodel.h>
|
||||||
|
#include <metainfo.h>
|
||||||
|
#include <model.h>
|
||||||
|
#include <previewtooltip/previewtooltipbackend.h>
|
||||||
|
#include <rewritingexception.h>
|
||||||
|
#include <qmldesignerconstants.h>
|
||||||
|
#include <qmldesignerplugin.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/flowlayout.h>
|
#include <utils/flowlayout.h>
|
||||||
@@ -81,14 +83,14 @@ static QString propertyEditorResourcesPath() {
|
|||||||
return Core::ICore::resourcePath() + QStringLiteral("/qmldesigner/propertyEditorQmlSources");
|
return Core::ICore::resourcePath() + QStringLiteral("/qmldesigner/propertyEditorQmlSources");
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
ItemLibraryWidget::ItemLibraryWidget(ImageCache &imageCache)
|
||||||
QFrame(parent),
|
: m_itemIconSize(24, 24)
|
||||||
m_itemIconSize(24, 24),
|
, m_itemViewQuickWidget(new QQuickWidget(this))
|
||||||
m_itemViewQuickWidget(new QQuickWidget(this)),
|
, m_resourcesView(new ItemLibraryResourceView(this))
|
||||||
m_resourcesView(new ItemLibraryResourceView(this)),
|
, m_importTagsWidget(new QWidget(this))
|
||||||
m_importTagsWidget(new QWidget(this)),
|
, m_addResourcesWidget(new QWidget(this))
|
||||||
m_addResourcesWidget(new QWidget(this)),
|
, m_imageCache{imageCache}
|
||||||
m_filterFlag(QtBasic)
|
, m_filterFlag(QtBasic)
|
||||||
{
|
{
|
||||||
m_compressionTimer.setInterval(200);
|
m_compressionTimer.setInterval(200);
|
||||||
m_compressionTimer.setSingleShot(true);
|
m_compressionTimer.setSingleShot(true);
|
||||||
@@ -102,16 +104,20 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
|||||||
m_itemViewQuickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
|
m_itemViewQuickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
|
||||||
m_itemLibraryModel = new ItemLibraryModel(this);
|
m_itemLibraryModel = new ItemLibraryModel(this);
|
||||||
|
|
||||||
m_itemViewQuickWidget->rootContext()->setContextProperties(
|
m_itemViewQuickWidget->rootContext()->setContextProperties(QVector<QQmlContext::PropertyPair>{
|
||||||
QVector<QQmlContext::PropertyPair>{
|
{{"itemLibraryModel"}, QVariant::fromValue(m_itemLibraryModel.data())},
|
||||||
{{"itemLibraryModel"}, QVariant::fromValue(m_itemLibraryModel.data())},
|
{{"itemLibraryIconWidth"}, m_itemIconSize.width()},
|
||||||
{{"itemLibraryIconWidth"}, m_itemIconSize.width()},
|
{{"itemLibraryIconHeight"}, m_itemIconSize.height()},
|
||||||
{{"itemLibraryIconHeight"}, m_itemIconSize.height()},
|
{{"rootView"}, QVariant::fromValue(this)},
|
||||||
{{"rootView"}, QVariant::fromValue(this)},
|
{{"highlightColor"}, Utils::StyleHelper::notTooBrightHighlightColor()},
|
||||||
{{"highlightColor"}, Utils::StyleHelper::notTooBrightHighlightColor()}
|
});
|
||||||
}
|
|
||||||
);
|
m_previewTooltipBackend = std::make_unique<PreviewTooltipBackend>(m_imageCache);
|
||||||
m_itemViewQuickWidget->setClearColor(Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate));
|
m_itemViewQuickWidget->rootContext()->setContextProperty("tooltipBackend",
|
||||||
|
m_previewTooltipBackend.get());
|
||||||
|
|
||||||
|
m_itemViewQuickWidget->setClearColor(
|
||||||
|
Theme::getColor(Theme::Color::QmlDesigner_BackgroundColorDarkAlternate));
|
||||||
|
|
||||||
/* create Resources view and its model */
|
/* create Resources view and its model */
|
||||||
m_resourcesFileSystemModel = new CustomFileSystemModel(this);
|
m_resourcesFileSystemModel = new CustomFileSystemModel(this);
|
||||||
@@ -119,6 +125,7 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
|||||||
|
|
||||||
/* create image provider for loading item icons */
|
/* create image provider for loading item icons */
|
||||||
m_itemViewQuickWidget->engine()->addImageProvider(QStringLiteral("qmldesigner_itemlibrary"), new Internal::ItemLibraryImageProvider);
|
m_itemViewQuickWidget->engine()->addImageProvider(QStringLiteral("qmldesigner_itemlibrary"), new Internal::ItemLibraryImageProvider);
|
||||||
|
|
||||||
Theme::setupTheme(m_itemViewQuickWidget->engine());
|
Theme::setupTheme(m_itemViewQuickWidget->engine());
|
||||||
|
|
||||||
/* other widgets */
|
/* other widgets */
|
||||||
@@ -243,6 +250,8 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
|||||||
reloadQmlSource();
|
reloadQmlSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ItemLibraryWidget::~ItemLibraryWidget() = default;
|
||||||
|
|
||||||
void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
|
void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
|
||||||
{
|
{
|
||||||
if (m_itemLibraryInfo.data() == itemLibraryInfo)
|
if (m_itemLibraryInfo.data() == itemLibraryInfo)
|
||||||
@@ -306,9 +315,14 @@ void ItemLibraryWidget::delayedUpdateModel()
|
|||||||
|
|
||||||
void ItemLibraryWidget::setModel(Model *model)
|
void ItemLibraryWidget::setModel(Model *model)
|
||||||
{
|
{
|
||||||
|
m_itemViewQuickWidget->engine()->removeImageProvider("itemlibrary_preview");
|
||||||
m_model = model;
|
m_model = model;
|
||||||
if (!model)
|
if (!model)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m_itemViewQuickWidget->engine()->addImageProvider("itemlibrary_preview",
|
||||||
|
new ItemLibraryIconImageProvider{m_imageCache});
|
||||||
|
|
||||||
setItemLibraryInfo(model->metaInfo().itemLibraryInfo());
|
setItemLibraryInfo(model->metaInfo().itemLibraryInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +332,8 @@ void ItemLibraryWidget::setCurrentIndexOfStackedWidget(int index)
|
|||||||
m_filterLineEdit->setVisible(false);
|
m_filterLineEdit->setVisible(false);
|
||||||
m_importTagsWidget->setVisible(true);
|
m_importTagsWidget->setVisible(true);
|
||||||
m_addResourcesWidget->setVisible(false);
|
m_addResourcesWidget->setVisible(false);
|
||||||
} if (index == 1) {
|
}
|
||||||
|
if (index == 1) {
|
||||||
m_filterLineEdit->setVisible(true);
|
m_filterLineEdit->setVisible(true);
|
||||||
m_importTagsWidget->setVisible(false);
|
m_importTagsWidget->setVisible(false);
|
||||||
m_addResourcesWidget->setVisible(true);
|
m_addResourcesWidget->setVisible(true);
|
||||||
@@ -564,5 +579,4 @@ void ItemLibraryWidget::addResources()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // namespace QmlDesigner
|
||||||
}
|
|
||||||
|
@@ -37,6 +37,8 @@
|
|||||||
#include <QQmlPropertyMap>
|
#include <QQmlPropertyMap>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QStackedWidget;
|
class QStackedWidget;
|
||||||
class QShortcut;
|
class QShortcut;
|
||||||
@@ -52,6 +54,9 @@ class CustomFileSystemModel;
|
|||||||
|
|
||||||
class ItemLibraryModel;
|
class ItemLibraryModel;
|
||||||
class ItemLibraryResourceView;
|
class ItemLibraryResourceView;
|
||||||
|
class PreviewTooltipBackend;
|
||||||
|
class ImageCache;
|
||||||
|
class ImageCacheCollector;
|
||||||
|
|
||||||
class ItemLibraryWidget : public QFrame
|
class ItemLibraryWidget : public QFrame
|
||||||
{
|
{
|
||||||
@@ -63,7 +68,8 @@ class ItemLibraryWidget : public QFrame
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ItemLibraryWidget(QWidget *parent = nullptr);
|
ItemLibraryWidget(ImageCache &imageCache);
|
||||||
|
~ItemLibraryWidget();
|
||||||
|
|
||||||
void setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo);
|
void setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo);
|
||||||
QList<QToolButton *> createToolBarWidgets();
|
QList<QToolButton *> createToolBarWidgets();
|
||||||
@@ -115,9 +121,10 @@ private:
|
|||||||
QScopedPointer<ItemLibraryResourceView> m_resourcesView;
|
QScopedPointer<ItemLibraryResourceView> m_resourcesView;
|
||||||
QScopedPointer<QWidget> m_importTagsWidget;
|
QScopedPointer<QWidget> m_importTagsWidget;
|
||||||
QScopedPointer<QWidget> m_addResourcesWidget;
|
QScopedPointer<QWidget> m_addResourcesWidget;
|
||||||
|
std::unique_ptr<PreviewTooltipBackend> m_previewTooltipBackend;
|
||||||
|
|
||||||
QShortcut *m_qmlSourceUpdateShortcut;
|
QShortcut *m_qmlSourceUpdateShortcut;
|
||||||
|
ImageCache &m_imageCache;
|
||||||
QPointer<Model> m_model;
|
QPointer<Model> m_model;
|
||||||
FilterChangeFlag m_filterFlag;
|
FilterChangeFlag m_filterFlag;
|
||||||
ItemLibraryEntry m_currentitemLibraryEntry;
|
ItemLibraryEntry m_currentitemLibraryEntry;
|
||||||
|
@@ -82,12 +82,6 @@
|
|||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="imageLabel">
|
<widget class="QLabel" name="imageLabel">
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>150</width>
|
<width>150</width>
|
||||||
@@ -100,9 +94,6 @@
|
|||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Plain</enum>
|
<enum>QFrame::Plain</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
|
||||||
<string notr="true"><image></string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
|
@@ -0,0 +1,63 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "previewimagetooltip.h"
|
||||||
|
#include "ui_previewimagetooltip.h"
|
||||||
|
|
||||||
|
#include <utils/theme/theme.h>
|
||||||
|
|
||||||
|
#include <QtGui/qpixmap.h>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
PreviewImageTooltip::PreviewImageTooltip(QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, m_ui(std::make_unique<Ui::PreviewImageTooltip>())
|
||||||
|
{
|
||||||
|
// setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
setWindowFlags(Qt::ToolTip);
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
setStyleSheet(QString("QWidget { background-color: %1 }").arg(Utils::creatorTheme()->color(Utils::Theme::BackgroundColorNormal).name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
PreviewImageTooltip::~PreviewImageTooltip() = default;
|
||||||
|
|
||||||
|
void PreviewImageTooltip::setComponentPath(const QString &path)
|
||||||
|
{
|
||||||
|
m_ui->componentPathLabel->setText(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewImageTooltip::setComponentName(const QString &name)
|
||||||
|
{
|
||||||
|
m_ui->componentNameLabel->setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewImageTooltip::setImage(const QImage &image)
|
||||||
|
{
|
||||||
|
resize(image.width() + 20 + m_ui->componentNameLabel->width(),
|
||||||
|
std::max(image.height() + 20, height()));
|
||||||
|
m_ui->imageLabel->setPixmap(QPixmap::fromImage({image}));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,53 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <QtWidgets/qwidget.h>
|
||||||
|
#include <QtGui/qpixmap.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
namespace Ui {
|
||||||
|
class PreviewImageTooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PreviewImageTooltip : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PreviewImageTooltip(QWidget *parent = {});
|
||||||
|
~PreviewImageTooltip();
|
||||||
|
|
||||||
|
void setComponentPath(const QString &path);
|
||||||
|
void setComponentName(const QString &name);
|
||||||
|
void setImage(const QImage &pixmap);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::PreviewImageTooltip> m_ui;
|
||||||
|
};
|
||||||
|
}
|
@@ -0,0 +1,158 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>QmlDesigner::PreviewImageTooltip</class>
|
||||||
|
<widget class="QWidget" name="QmlDesigner::PreviewImageTooltip">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>200</width>
|
||||||
|
<height>200</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>1000</width>
|
||||||
|
<height>1000</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="autoFillBackground">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizeGripEnabled" stdset="0">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Box</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="componentPathLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::NoTextInteraction</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" rowspan="2">
|
||||||
|
<widget class="QLabel" name="imageLabel">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::Box</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="Utils::ElidingLabel" name="componentNameLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::NoTextInteraction</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>Utils::ElidingLabel</class>
|
||||||
|
<extends>QLabel</extends>
|
||||||
|
<header location="global">utils/elidinglabel.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@@ -0,0 +1,110 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 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 "previewtooltipbackend.h"
|
||||||
|
|
||||||
|
#include "previewimagetooltip.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <imagecache.h>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDesktopWidget>
|
||||||
|
#include <QMetaObject>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
PreviewTooltipBackend::PreviewTooltipBackend(ImageCache &cache)
|
||||||
|
: m_cache{cache}
|
||||||
|
{}
|
||||||
|
|
||||||
|
PreviewTooltipBackend::~PreviewTooltipBackend()
|
||||||
|
{
|
||||||
|
hideTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewTooltipBackend::showTooltip()
|
||||||
|
{
|
||||||
|
if (m_componentPath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_tooltip = std::make_unique<PreviewImageTooltip>();
|
||||||
|
|
||||||
|
m_tooltip->setComponentName(m_componentName);
|
||||||
|
m_tooltip->setComponentPath(m_componentPath);
|
||||||
|
|
||||||
|
m_cache.requestImage(
|
||||||
|
m_componentPath,
|
||||||
|
[tooltip = QPointer<PreviewImageTooltip>(m_tooltip.get())](const QImage &image) {
|
||||||
|
QMetaObject::invokeMethod(tooltip, [tooltip, image] {
|
||||||
|
if (tooltip)
|
||||||
|
tooltip->setImage(image);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[] {});
|
||||||
|
|
||||||
|
auto desktopWidget = QApplication::desktop();
|
||||||
|
auto mousePosition = desktopWidget->cursor().pos();
|
||||||
|
|
||||||
|
mousePosition += {20, 20};
|
||||||
|
m_tooltip->move(mousePosition);
|
||||||
|
m_tooltip->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PreviewTooltipBackend::hideTooltip()
|
||||||
|
{
|
||||||
|
if (m_tooltip)
|
||||||
|
m_tooltip->hide();
|
||||||
|
|
||||||
|
m_tooltip.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlDesigner::PreviewTooltipBackend::componentPath() const
|
||||||
|
{
|
||||||
|
return m_componentPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDesigner::PreviewTooltipBackend::setComponentPath(const QString &path)
|
||||||
|
{
|
||||||
|
m_componentPath = path;
|
||||||
|
|
||||||
|
if (m_componentPath != path)
|
||||||
|
emit componentPathChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString QmlDesigner::PreviewTooltipBackend::componentName() const
|
||||||
|
{
|
||||||
|
return m_componentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QmlDesigner::PreviewTooltipBackend::setComponentName(const QString &name)
|
||||||
|
{
|
||||||
|
m_componentName = name;
|
||||||
|
|
||||||
|
if (m_componentName != name)
|
||||||
|
emit componentNameChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,71 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 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 <QObject>
|
||||||
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class PreviewImageTooltip;
|
||||||
|
class ImageCache;
|
||||||
|
|
||||||
|
class PreviewTooltipBackend : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(QString componentPath READ componentPath WRITE setComponentPath NOTIFY componentPathChanged)
|
||||||
|
Q_PROPERTY(QString componentName READ componentName WRITE setComponentName NOTIFY componentNameChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
PreviewTooltipBackend(ImageCache &cache);
|
||||||
|
~PreviewTooltipBackend();
|
||||||
|
|
||||||
|
Q_INVOKABLE void showTooltip();
|
||||||
|
Q_INVOKABLE void hideTooltip();
|
||||||
|
|
||||||
|
QString componentPath() const;
|
||||||
|
void setComponentPath(const QString &path);
|
||||||
|
|
||||||
|
QString componentName() const;
|
||||||
|
void setComponentName(const QString &path);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void componentPathChanged();
|
||||||
|
void componentNameChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_componentPath;
|
||||||
|
QString m_componentName;
|
||||||
|
std::unique_ptr<PreviewImageTooltip> m_tooltip;
|
||||||
|
ImageCache &m_cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QML_DECLARE_TYPE(QmlDesigner::PreviewTooltipBackend)
|
@@ -0,0 +1,11 @@
|
|||||||
|
HEADERS += \
|
||||||
|
$$PWD/previewtooltipbackend.h \
|
||||||
|
$$PWD/previewimagetooltip.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/previewtooltipbackend.cpp \
|
||||||
|
$$PWD/previewimagetooltip.cpp
|
||||||
|
|
||||||
|
FORMS += $$PWD/previewimagetooltip.ui
|
||||||
|
|
||||||
|
|
@@ -14,6 +14,7 @@ include (../../../../share/qtcreator/qml/qmlpuppet/container/container.pri)
|
|||||||
include (../../../../share/qtcreator/qml/qmlpuppet/types/types.pri)
|
include (../../../../share/qtcreator/qml/qmlpuppet/types/types.pri)
|
||||||
|
|
||||||
SOURCES += $$PWD/model/abstractview.cpp \
|
SOURCES += $$PWD/model/abstractview.cpp \
|
||||||
|
$$PWD/imagecache/imagecachecollector.cpp \
|
||||||
$$PWD/model/rewriterview.cpp \
|
$$PWD/model/rewriterview.cpp \
|
||||||
$$PWD/model/documentmessage.cpp \
|
$$PWD/model/documentmessage.cpp \
|
||||||
$$PWD/metainfo/metainfo.cpp \
|
$$PWD/metainfo/metainfo.cpp \
|
||||||
@@ -84,9 +85,15 @@ SOURCES += $$PWD/model/abstractview.cpp \
|
|||||||
$$PWD/model/qmltimeline.cpp \
|
$$PWD/model/qmltimeline.cpp \
|
||||||
$$PWD/model/qmltimelinekeyframegroup.cpp \
|
$$PWD/model/qmltimelinekeyframegroup.cpp \
|
||||||
$$PWD/model/annotation.cpp \
|
$$PWD/model/annotation.cpp \
|
||||||
$$PWD/model/stylesheetmerger.cpp
|
$$PWD/model/stylesheetmerger.cpp \
|
||||||
|
$$PWD/imagecache/imagecache.cpp \
|
||||||
|
$$PWD/imagecache/imagecacheconnectionmanager.cpp \
|
||||||
|
$$PWD/imagecache/imagecachegenerator.cpp \
|
||||||
|
$$PWD/imagecache/timestampprovider.cpp
|
||||||
|
|
||||||
|
|
||||||
HEADERS += $$PWD/include/qmldesignercorelib_global.h \
|
HEADERS += $$PWD/include/qmldesignercorelib_global.h \
|
||||||
|
$$PWD/imagecache/imagecachecollector.h \
|
||||||
$$PWD/include/abstractview.h \
|
$$PWD/include/abstractview.h \
|
||||||
$$PWD/include/nodeinstanceview.h \
|
$$PWD/include/nodeinstanceview.h \
|
||||||
$$PWD/include/rewriterview.h \
|
$$PWD/include/rewriterview.h \
|
||||||
@@ -162,7 +169,17 @@ HEADERS += $$PWD/include/qmldesignercorelib_global.h \
|
|||||||
$$PWD/include/qmltimeline.h \
|
$$PWD/include/qmltimeline.h \
|
||||||
$$PWD/include/qmltimelinekeyframegroup.h \
|
$$PWD/include/qmltimelinekeyframegroup.h \
|
||||||
$$PWD/include/annotation.h \
|
$$PWD/include/annotation.h \
|
||||||
$$PWD/include/stylesheetmerger.h
|
$$PWD/include/stylesheetmerger.h \
|
||||||
|
$$PWD/include/imagecache.h \
|
||||||
|
$$PWD/imagecache/imagecachecollectorinterface.h \
|
||||||
|
$$PWD/imagecache/imagecacheconnectionmanager.h \
|
||||||
|
$$PWD/imagecache/imagecachegeneratorinterface.h \
|
||||||
|
$$PWD/imagecache/imagecachestorageinterface.h \
|
||||||
|
$$PWD/imagecache/imagecachegenerator.h \
|
||||||
|
$$PWD/imagecache/imagecachestorage.h \
|
||||||
|
$$PWD/imagecache/timestampprovider.h \
|
||||||
|
$$PWD/imagecache/timestampproviderinterface.h
|
||||||
|
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
$$PWD/instances/puppetdialog.ui
|
$$PWD/instances/puppetdialog.ui
|
||||||
|
166
src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp
Normal file
166
src/plugins/qmldesigner/designercore/imagecache/imagecache.cpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "imagecache.h"
|
||||||
|
|
||||||
|
#include "imagecachegenerator.h"
|
||||||
|
#include "imagecachestorage.h"
|
||||||
|
#include "timestampprovider.h"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
ImageCache::ImageCache(ImageCacheStorageInterface &storage,
|
||||||
|
ImageCacheGeneratorInterface &generator,
|
||||||
|
TimeStampProviderInterface &timeStampProvider)
|
||||||
|
: m_storage(storage)
|
||||||
|
, m_generator(generator)
|
||||||
|
, m_timeStampProvider(timeStampProvider)
|
||||||
|
{
|
||||||
|
m_backgroundThread = std::thread{[this] {
|
||||||
|
while (isRunning()) {
|
||||||
|
if (auto [hasEntry, entry] = getEntry(); hasEntry) {
|
||||||
|
request(entry.name,
|
||||||
|
entry.requestType,
|
||||||
|
std::move(entry.captureCallback),
|
||||||
|
std::move(entry.abortCallback),
|
||||||
|
m_storage,
|
||||||
|
m_generator,
|
||||||
|
m_timeStampProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForEntries();
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageCache::~ImageCache()
|
||||||
|
{
|
||||||
|
clean();
|
||||||
|
stopThread();
|
||||||
|
m_condition.notify_all();
|
||||||
|
if (m_backgroundThread.joinable())
|
||||||
|
m_backgroundThread.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::request(Utils::SmallStringView name,
|
||||||
|
ImageCache::RequestType requestType,
|
||||||
|
ImageCache::CaptureCallback captureCallback,
|
||||||
|
ImageCache::AbortCallback abortCallback,
|
||||||
|
ImageCacheStorageInterface &storage,
|
||||||
|
ImageCacheGeneratorInterface &generator,
|
||||||
|
TimeStampProviderInterface &timeStampProvider)
|
||||||
|
{
|
||||||
|
const auto timeStamp = timeStampProvider.timeStamp(name);
|
||||||
|
const auto entry = requestType == RequestType::Image ? storage.fetchImage(name, timeStamp)
|
||||||
|
: storage.fetchIcon(name, timeStamp);
|
||||||
|
|
||||||
|
if (entry.hasEntry) {
|
||||||
|
if (entry.image.isNull())
|
||||||
|
abortCallback();
|
||||||
|
else
|
||||||
|
captureCallback(entry.image);
|
||||||
|
} else {
|
||||||
|
generator.generateImage(name, timeStamp, std::move(captureCallback), std::move(abortCallback));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::requestImage(Utils::PathString name,
|
||||||
|
ImageCache::CaptureCallback captureCallback,
|
||||||
|
AbortCallback abortCallback)
|
||||||
|
{
|
||||||
|
addEntry(std::move(name), std::move(captureCallback), std::move(abortCallback), RequestType::Image);
|
||||||
|
m_condition.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::requestIcon(Utils::PathString name,
|
||||||
|
ImageCache::CaptureCallback captureCallback,
|
||||||
|
ImageCache::AbortCallback abortCallback)
|
||||||
|
{
|
||||||
|
addEntry(std::move(name), std::move(captureCallback), std::move(abortCallback), RequestType::Icon);
|
||||||
|
m_condition.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::clean()
|
||||||
|
{
|
||||||
|
clearEntries();
|
||||||
|
m_generator.clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<bool, ImageCache::Entry> ImageCache::getEntry()
|
||||||
|
{
|
||||||
|
std::unique_lock lock{m_mutex};
|
||||||
|
|
||||||
|
if (m_entries.empty())
|
||||||
|
return {false, Entry{}};
|
||||||
|
|
||||||
|
Entry entry = m_entries.back();
|
||||||
|
m_entries.pop_back();
|
||||||
|
|
||||||
|
return {true, entry};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::addEntry(Utils::PathString &&name,
|
||||||
|
ImageCache::CaptureCallback &&captureCallback,
|
||||||
|
AbortCallback &&abortCallback,
|
||||||
|
RequestType requestType)
|
||||||
|
{
|
||||||
|
std::unique_lock lock{m_mutex};
|
||||||
|
|
||||||
|
m_entries.emplace_back(std::move(name),
|
||||||
|
std::move(captureCallback),
|
||||||
|
std::move(abortCallback),
|
||||||
|
requestType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::clearEntries()
|
||||||
|
{
|
||||||
|
std::unique_lock lock{m_mutex};
|
||||||
|
for (Entry &entry : m_entries)
|
||||||
|
entry.abortCallback();
|
||||||
|
m_entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::waitForEntries()
|
||||||
|
{
|
||||||
|
std::unique_lock lock{m_mutex};
|
||||||
|
if (m_entries.empty())
|
||||||
|
m_condition.wait(lock, [&] { return m_entries.size() || m_finishing; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::stopThread()
|
||||||
|
{
|
||||||
|
std::unique_lock lock{m_mutex};
|
||||||
|
m_finishing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImageCache::isRunning()
|
||||||
|
{
|
||||||
|
std::unique_lock lock{m_mutex};
|
||||||
|
return !m_finishing;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,117 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "imagecachecollector.h"
|
||||||
|
#include "imagecacheconnectionmanager.h"
|
||||||
|
|
||||||
|
#include <metainfo.h>
|
||||||
|
#include <model.h>
|
||||||
|
#include <nodeinstanceview.h>
|
||||||
|
#include <plaintexteditmodifier.h>
|
||||||
|
#include <rewriterview.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QByteArray fileToByteArray(QString const &filename)
|
||||||
|
{
|
||||||
|
QFile file(filename);
|
||||||
|
QFileInfo fleInfo(file);
|
||||||
|
|
||||||
|
if (fleInfo.exists() && file.open(QFile::ReadOnly))
|
||||||
|
return file.readAll();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString fileToString(const QString &filename)
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(fileToByteArray(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
ImageCacheCollector::ImageCacheCollector(ImageCacheConnectionManager &connectionManager)
|
||||||
|
: m_connectionManager{connectionManager}
|
||||||
|
{}
|
||||||
|
|
||||||
|
ImageCacheCollector::~ImageCacheCollector() = default;
|
||||||
|
|
||||||
|
void ImageCacheCollector::start(Utils::SmallStringView name,
|
||||||
|
CaptureCallback captureCallback,
|
||||||
|
AbortCallback abortCallback)
|
||||||
|
{
|
||||||
|
RewriterView rewriterView{RewriterView::Amend, nullptr};
|
||||||
|
NodeInstanceView nodeInstanceView{m_connectionManager};
|
||||||
|
|
||||||
|
const QString filePath{name};
|
||||||
|
std::unique_ptr<Model> model{QmlDesigner::Model::create("QtQuick/Item", 2, 1)};
|
||||||
|
model->setFileUrl(QUrl::fromLocalFile(filePath));
|
||||||
|
|
||||||
|
auto textDocument = std::make_unique<QTextDocument>(fileToString(filePath));
|
||||||
|
|
||||||
|
auto modifier = std::make_unique<NotIndentingTextEditModifier>(textDocument.get(),
|
||||||
|
QTextCursor{textDocument.get()});
|
||||||
|
|
||||||
|
rewriterView.setTextModifier(modifier.get());
|
||||||
|
|
||||||
|
model->setRewriterView(&rewriterView);
|
||||||
|
|
||||||
|
if (rewriterView.inErrorState() || !rewriterView.rootModelNode().metaInfo().isGraphicalItem()) {
|
||||||
|
abortCallback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_connectionManager.setCallback(std::move(captureCallback));
|
||||||
|
|
||||||
|
nodeInstanceView.setTarget(m_target.get());
|
||||||
|
nodeInstanceView.setCrashCallback(abortCallback);
|
||||||
|
model->setNodeInstanceView(&nodeInstanceView);
|
||||||
|
|
||||||
|
bool capturedDataArrived = m_connectionManager.waitForCapturedData();
|
||||||
|
|
||||||
|
m_connectionManager.setCallback({});
|
||||||
|
m_connectionManager.setCrashCallback({});
|
||||||
|
|
||||||
|
model->setNodeInstanceView({});
|
||||||
|
model->setRewriterView({});
|
||||||
|
|
||||||
|
if (!capturedDataArrived)
|
||||||
|
abortCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCacheCollector::setTarget(std::unique_ptr<ProjectExplorer::Target> target)
|
||||||
|
{
|
||||||
|
m_target = std::move(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -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 "imagecachecollectorinterface.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QTextDocument;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class Model;
|
||||||
|
class NotIndentingTextEditModifier;
|
||||||
|
class ImageCacheConnectionManager;
|
||||||
|
class RewriterView;
|
||||||
|
class NodeInstanceView;
|
||||||
|
|
||||||
|
class ImageCacheCollector final : public ImageCacheCollectorInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageCacheCollector(ImageCacheConnectionManager &connectionManager);
|
||||||
|
|
||||||
|
~ImageCacheCollector();
|
||||||
|
|
||||||
|
void start(Utils::SmallStringView filePath,
|
||||||
|
CaptureCallback captureCallback,
|
||||||
|
AbortCallback abortCallback) override;
|
||||||
|
|
||||||
|
void setTarget(std::unique_ptr<ProjectExplorer::Target> target);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ImageCacheConnectionManager &m_connectionManager;
|
||||||
|
std::unique_ptr<ProjectExplorer::Target> m_target;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,48 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <utils/smallstringview.h>
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ImageCacheCollectorInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using CaptureCallback = std::function<void(QImage &&image)>;
|
||||||
|
using AbortCallback = std::function<void()>;
|
||||||
|
|
||||||
|
virtual void start(Utils::SmallStringView filePath,
|
||||||
|
CaptureCallback captureCallback,
|
||||||
|
AbortCallback abortCallback)
|
||||||
|
= 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~ImageCacheCollectorInterface() = default;
|
||||||
|
};
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,68 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "imagecacheconnectionmanager.h"
|
||||||
|
|
||||||
|
#include <captureddatacommand.h>
|
||||||
|
|
||||||
|
#include <QLocalSocket>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
ImageCacheConnectionManager::ImageCacheConnectionManager()
|
||||||
|
{
|
||||||
|
connections().emplace_back("Capture icon", "captureiconmode");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCacheConnectionManager::setCallback(ImageCacheConnectionManager::Callback callback)
|
||||||
|
{
|
||||||
|
m_captureCallback = std::move(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImageCacheConnectionManager::waitForCapturedData()
|
||||||
|
{
|
||||||
|
if (connections().empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
disconnect(connections().front().socket.get(), &QIODevice::readyRead, nullptr, nullptr);
|
||||||
|
|
||||||
|
while (!m_capturedDataArrived) {
|
||||||
|
bool dataArrived = connections().front().socket->waitForReadyRead(600000);
|
||||||
|
|
||||||
|
if (!dataArrived)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
readDataStream(connections().front());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_capturedDataArrived = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCacheConnectionManager::dispatchCommand(const QVariant &command,
|
||||||
|
ConnectionManagerInterface::Connection &)
|
||||||
|
{
|
||||||
|
static const int capturedDataCommandType = QMetaType::type("CapturedDataCommand");
|
||||||
|
|
||||||
|
if (command.userType() == capturedDataCommandType) {
|
||||||
|
m_captureCallback(command.value<CapturedDataCommand>().image);
|
||||||
|
m_capturedDataArrived = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,45 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <designercore/instances/connectionmanager.h>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class CapturedDataCommand;
|
||||||
|
|
||||||
|
class ImageCacheConnectionManager : public ConnectionManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Callback = std::function<void(QImage &&)>;
|
||||||
|
|
||||||
|
ImageCacheConnectionManager();
|
||||||
|
|
||||||
|
void setCallback(Callback captureCallback);
|
||||||
|
|
||||||
|
bool waitForCapturedData();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void dispatchCommand(const QVariant &command, Connection &connection) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Callback m_captureCallback;
|
||||||
|
bool m_capturedDataArrived = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,159 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "imagecachegenerator.h"
|
||||||
|
|
||||||
|
#include "imagecachecollectorinterface.h"
|
||||||
|
#include "imagecachestorage.h"
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
ImageCacheGenerator::~ImageCacheGenerator()
|
||||||
|
{
|
||||||
|
std::lock_guard threadLock{*m_threadMutex.get()};
|
||||||
|
|
||||||
|
if (m_backgroundThread)
|
||||||
|
m_backgroundThread->wait();
|
||||||
|
|
||||||
|
clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCacheGenerator::generateImage(Utils::SmallStringView name,
|
||||||
|
Sqlite::TimeStamp timeStamp,
|
||||||
|
ImageCacheGeneratorInterface::CaptureCallback &&captureCallback,
|
||||||
|
AbortCallback &&abortCallback)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard lock{m_dataMutex};
|
||||||
|
m_tasks.emplace_back(name, timeStamp, std::move(captureCallback), std::move(abortCallback));
|
||||||
|
}
|
||||||
|
|
||||||
|
startGenerationAsynchronously();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCacheGenerator::clean()
|
||||||
|
{
|
||||||
|
std::lock_guard dataLock{m_dataMutex};
|
||||||
|
m_tasks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReleaseProcessing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ReleaseProcessing(std::atomic_flag &processing)
|
||||||
|
: m_processing(processing)
|
||||||
|
{
|
||||||
|
m_processing.test_and_set(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ReleaseProcessing() { m_processing.clear(std::memory_order_release); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic_flag &m_processing;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ImageCacheGenerator::startGeneration(std::shared_ptr<std::mutex> threadMutex)
|
||||||
|
{
|
||||||
|
ReleaseProcessing guard(m_processing);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
Task task;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::unique_lock threadLock{*threadMutex.get(), std::defer_lock_t{}};
|
||||||
|
|
||||||
|
if (!threadLock.try_lock())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::lock_guard dataLock{m_dataMutex};
|
||||||
|
|
||||||
|
if (m_tasks.empty()) {
|
||||||
|
m_storage.walCheckpointFull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
task = std::move(m_tasks.back());
|
||||||
|
|
||||||
|
m_tasks.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_collector.start(
|
||||||
|
task.filePath,
|
||||||
|
[this, threadMutex, task](QImage &&image) {
|
||||||
|
std::unique_lock lock{*threadMutex.get(), std::defer_lock_t{}};
|
||||||
|
|
||||||
|
if (!lock.try_lock())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (threadMutex.use_count() == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (image.isNull())
|
||||||
|
task.abortCallback();
|
||||||
|
else
|
||||||
|
task.captureCallback(image);
|
||||||
|
|
||||||
|
m_storage.storeImage(std::move(task.filePath), task.timeStamp, image);
|
||||||
|
},
|
||||||
|
[this, threadMutex, task] {
|
||||||
|
std::unique_lock lock{*threadMutex.get(), std::defer_lock_t{}};
|
||||||
|
|
||||||
|
if (!lock.try_lock())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (threadMutex.use_count() == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
task.abortCallback();
|
||||||
|
m_storage.storeImage(std::move(task.filePath), task.timeStamp, {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCacheGenerator::startGenerationAsynchronously()
|
||||||
|
{
|
||||||
|
if (m_processing.test_and_set(std::memory_order_acquire))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::unique_lock lock{*m_threadMutex.get(), std::defer_lock_t{}};
|
||||||
|
|
||||||
|
if (!lock.try_lock())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_backgroundThread)
|
||||||
|
m_backgroundThread->wait();
|
||||||
|
|
||||||
|
m_backgroundThread.reset(QThread::create(
|
||||||
|
[this](std::shared_ptr<std::mutex> threadMutex) { startGeneration(threadMutex); },
|
||||||
|
m_threadMutex));
|
||||||
|
m_backgroundThread->start();
|
||||||
|
// m_backgroundThread = std::thread(
|
||||||
|
// [this](std::shared_ptr<std::mutex> threadMutex) { startGeneration(threadMutex); },
|
||||||
|
// m_threadMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,95 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "imagecachegeneratorinterface.h"
|
||||||
|
|
||||||
|
#include <utils/smallstring.h>
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QPlainTextEdit;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ImageCacheCollectorInterface;
|
||||||
|
class ImageCacheStorageInterface;
|
||||||
|
|
||||||
|
class ImageCacheGenerator final : public ImageCacheGeneratorInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageCacheGenerator(ImageCacheCollectorInterface &collector, ImageCacheStorageInterface &storage)
|
||||||
|
: m_collector{collector}
|
||||||
|
, m_storage(storage)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~ImageCacheGenerator();
|
||||||
|
|
||||||
|
void generateImage(Utils::SmallStringView filePath,
|
||||||
|
Sqlite::TimeStamp timeStamp,
|
||||||
|
CaptureCallback &&captureCallback,
|
||||||
|
AbortCallback &&abortCallback) override;
|
||||||
|
void clean() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Task
|
||||||
|
{
|
||||||
|
Task() = default;
|
||||||
|
Task(Utils::SmallStringView filePath,
|
||||||
|
Sqlite::TimeStamp timeStamp,
|
||||||
|
CaptureCallback &&captureCallback,
|
||||||
|
AbortCallback &&abortCallback)
|
||||||
|
: filePath(filePath)
|
||||||
|
, captureCallback(std::move(captureCallback))
|
||||||
|
, abortCallback(std::move(abortCallback))
|
||||||
|
, timeStamp(timeStamp)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Utils::PathString filePath;
|
||||||
|
CaptureCallback captureCallback;
|
||||||
|
AbortCallback abortCallback;
|
||||||
|
Sqlite::TimeStamp timeStamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
void startGeneration(std::shared_ptr<std::mutex> threadMutex);
|
||||||
|
void startGenerationAsynchronously();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<QThread> m_backgroundThread;
|
||||||
|
std::mutex m_dataMutex;
|
||||||
|
std::shared_ptr<std::mutex> m_threadMutex{std::make_shared<std::mutex>()};
|
||||||
|
std::vector<Task> m_tasks;
|
||||||
|
ImageCacheCollectorInterface &m_collector;
|
||||||
|
ImageCacheStorageInterface &m_storage;
|
||||||
|
std::atomic_flag m_processing = ATOMIC_FLAG_INIT;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,53 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <sqlitetimestamp.h>
|
||||||
|
#include <utils/smallstringview.h>
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ImageCacheGeneratorInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using CaptureCallback = std::function<void(const QImage &image)>;
|
||||||
|
using AbortCallback = std::function<void()>;
|
||||||
|
|
||||||
|
virtual void generateImage(Utils::SmallStringView name,
|
||||||
|
Sqlite::TimeStamp timeStamp,
|
||||||
|
CaptureCallback &&captureCallback,
|
||||||
|
AbortCallback &&abortCallback)
|
||||||
|
= 0;
|
||||||
|
|
||||||
|
virtual void clean() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~ImageCacheGeneratorInterface() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,197 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "imagecachestorageinterface.h"
|
||||||
|
|
||||||
|
#include <createtablesqlstatementbuilder.h>
|
||||||
|
|
||||||
|
#include <sqliteblob.h>
|
||||||
|
#include <sqlitereadstatement.h>
|
||||||
|
#include <sqlitetable.h>
|
||||||
|
#include <sqlitetransaction.h>
|
||||||
|
#include <sqlitewritestatement.h>
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QImageReader>
|
||||||
|
#include <QImageWriter>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
template<typename DatabaseType>
|
||||||
|
class ImageCacheStorage : public ImageCacheStorageInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ReadStatement = typename DatabaseType::ReadStatement;
|
||||||
|
using WriteStatement = typename DatabaseType::WriteStatement;
|
||||||
|
|
||||||
|
ImageCacheStorage(DatabaseType &database)
|
||||||
|
: database(database)
|
||||||
|
{
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry fetchImage(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp) const override
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Sqlite::DeferredTransaction transaction{database};
|
||||||
|
|
||||||
|
auto optionalBlob = selectImageStatement.template value<Sqlite::ByteArrayBlob>(
|
||||||
|
name, minimumTimeStamp.value);
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
if (optionalBlob) {
|
||||||
|
QBuffer buffer{&optionalBlob->byteArray};
|
||||||
|
QImageReader reader{&buffer, "PNG"};
|
||||||
|
|
||||||
|
return Entry{reader.read(), true};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
|
||||||
|
} catch (const Sqlite::StatementIsBusy &) {
|
||||||
|
return fetchImage(name, minimumTimeStamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry fetchIcon(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp) const override
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Sqlite::DeferredTransaction transaction{database};
|
||||||
|
|
||||||
|
auto optionalBlob = selectIconStatement.template value<Sqlite::ByteArrayBlob>(
|
||||||
|
name, minimumTimeStamp.value);
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
if (optionalBlob) {
|
||||||
|
QBuffer buffer{&optionalBlob->byteArray};
|
||||||
|
QImageReader reader{&buffer, "PNG"};
|
||||||
|
|
||||||
|
return Entry{reader.read(), true};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
|
||||||
|
} catch (const Sqlite::StatementIsBusy &) {
|
||||||
|
return fetchIcon(name, minimumTimeStamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void storeImage(Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QImage &image) override
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Sqlite::ImmediateTransaction transaction{database};
|
||||||
|
|
||||||
|
if (image.isNull()) {
|
||||||
|
upsertImageStatement.write(name,
|
||||||
|
newTimeStamp.value,
|
||||||
|
Sqlite::NullValue{},
|
||||||
|
Sqlite::NullValue{});
|
||||||
|
} else {
|
||||||
|
QSize iconSize = image.size().scaled(QSize{96, 96}.boundedTo(image.size()),
|
||||||
|
Qt::KeepAspectRatio);
|
||||||
|
QImage icon = image.scaled(iconSize);
|
||||||
|
upsertImageStatement.write(name,
|
||||||
|
newTimeStamp.value,
|
||||||
|
Sqlite::BlobView{createImageBuffer(image)->data()},
|
||||||
|
Sqlite::BlobView{createImageBuffer(icon)->data()});
|
||||||
|
}
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
} catch (const Sqlite::StatementIsBusy &) {
|
||||||
|
return storeImage(name, newTimeStamp, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void walCheckpointFull()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
database.walCheckpointFull();
|
||||||
|
} catch (const Sqlite::StatementIsBusy &) {
|
||||||
|
return walCheckpointFull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Initializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Initializer(DatabaseType &database)
|
||||||
|
{
|
||||||
|
if (!database.isInitialized()) {
|
||||||
|
Sqlite::ExclusiveTransaction transaction{database};
|
||||||
|
|
||||||
|
createImagesTable(database);
|
||||||
|
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
database.setIsInitialized(true);
|
||||||
|
|
||||||
|
database.walCheckpointFull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void createImagesTable(DatabaseType &database)
|
||||||
|
{
|
||||||
|
Sqlite::Table table;
|
||||||
|
table.setUseIfNotExists(true);
|
||||||
|
table.setName("images");
|
||||||
|
table.addColumn("id", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
|
||||||
|
table.addColumn("name", Sqlite::ColumnType::Text, {Sqlite::NotNull{}, Sqlite::Unique{}});
|
||||||
|
table.addColumn("mtime", Sqlite::ColumnType::Integer);
|
||||||
|
table.addColumn("image", Sqlite::ColumnType::Blob);
|
||||||
|
table.addColumn("icon", Sqlite::ColumnType::Blob);
|
||||||
|
|
||||||
|
table.initialize(database);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<QBuffer> createImageBuffer(const QImage &image)
|
||||||
|
{
|
||||||
|
auto buffer = std::make_unique<QBuffer>();
|
||||||
|
buffer->open(QIODevice::WriteOnly);
|
||||||
|
QImageWriter writer{buffer.get(), "PNG"};
|
||||||
|
writer.write(image);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
DatabaseType &database;
|
||||||
|
Initializer initializer{database};
|
||||||
|
Sqlite::ImmediateNonThrowingDestructorTransaction transaction{database};
|
||||||
|
mutable ReadStatement selectImageStatement{
|
||||||
|
"SELECT image FROM images WHERE name=?1 AND mtime >= ?2", database};
|
||||||
|
mutable ReadStatement selectIconStatement{
|
||||||
|
"SELECT icon FROM images WHERE name=?1 AND mtime >= ?2", database};
|
||||||
|
WriteStatement upsertImageStatement{
|
||||||
|
"INSERT INTO images(name, mtime, image, icon) VALUES (?1, ?2, ?3, ?4) ON "
|
||||||
|
"CONFLICT(name) DO UPDATE SET mtime=excluded.mtime, image=excluded.image, "
|
||||||
|
"icon=excluded.icon",
|
||||||
|
database};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,58 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <QImage>
|
||||||
|
|
||||||
|
#include <sqlitetimestamp.h>
|
||||||
|
#include <utils/smallstringview.h>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
namespace Internal {
|
||||||
|
class ImageCacheStorageEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QImage image;
|
||||||
|
bool hasEntry = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
|
class ImageCacheStorageInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Entry = Internal::ImageCacheStorageEntry;
|
||||||
|
|
||||||
|
virtual Entry fetchImage(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp) const = 0;
|
||||||
|
virtual Entry fetchIcon(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp) const = 0;
|
||||||
|
virtual void storeImage(Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QImage &image) = 0;
|
||||||
|
virtual void walCheckpointFull() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~ImageCacheStorageInterface() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,38 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "timestampprovider.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
Sqlite::TimeStamp TimeStampProvider::timeStamp(Utils::SmallStringView name) const
|
||||||
|
{
|
||||||
|
return QFileInfo{QString{name}}.lastModified().toSecsSinceEpoch();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -0,0 +1,39 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "timestampproviderinterface.h"
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class TimeStampProvider : public TimeStampProviderInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sqlite::TimeStamp timeStamp(Utils::SmallStringView name) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
||||||
|
|
@@ -0,0 +1,44 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <sqlitetimestamp.h>
|
||||||
|
#include <utils/smallstringview.h>
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class TimeStampProviderInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual Sqlite::TimeStamp timeStamp(Utils::SmallStringView name) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~TimeStampProviderInterface() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -49,6 +49,9 @@ public:
|
|||||||
bool renameId(const QString &oldId, const QString &newId) override;
|
bool renameId(const QString &oldId, const QString &newId) override;
|
||||||
bool moveToComponent(int nodeOffset) override;
|
bool moveToComponent(int nodeOffset) override;
|
||||||
QStringList autoComplete(QTextDocument *textDocument, int position, bool explicitComplete) override;
|
QStringList autoComplete(QTextDocument *textDocument, int position, bool explicitComplete) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextEditor::TextEditorWidget *m_textEdit;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -0,0 +1,37 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class FileSystemFacadeInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
protected:
|
||||||
|
~FileSystemFacadeInterface() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
113
src/plugins/qmldesigner/designercore/include/imagecache.h
Normal file
113
src/plugins/qmldesigner/designercore/include/imagecache.h
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <utils/smallstring.h>
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class TimeStampProviderInterface;
|
||||||
|
class ImageCacheStorageInterface;
|
||||||
|
class ImageCacheGeneratorInterface;
|
||||||
|
|
||||||
|
class ImageCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using CaptureCallback = std::function<void(const QImage &)>;
|
||||||
|
using AbortCallback = std::function<void()>;
|
||||||
|
|
||||||
|
~ImageCache();
|
||||||
|
|
||||||
|
ImageCache(ImageCacheStorageInterface &storage,
|
||||||
|
ImageCacheGeneratorInterface &generator,
|
||||||
|
TimeStampProviderInterface &timeStampProvider);
|
||||||
|
|
||||||
|
void requestImage(Utils::PathString name,
|
||||||
|
CaptureCallback captureCallback,
|
||||||
|
AbortCallback abortCallback);
|
||||||
|
void requestIcon(Utils::PathString name,
|
||||||
|
CaptureCallback captureCallback,
|
||||||
|
AbortCallback abortCallback);
|
||||||
|
|
||||||
|
void clean();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class RequestType { Image, Icon };
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
Entry() = default;
|
||||||
|
Entry(Utils::PathString name,
|
||||||
|
CaptureCallback &&captureCallback,
|
||||||
|
AbortCallback &&abortCallback,
|
||||||
|
RequestType requestType)
|
||||||
|
: name{std::move(name)}
|
||||||
|
, captureCallback{std::move(captureCallback)}
|
||||||
|
, abortCallback{std::move(abortCallback)}
|
||||||
|
, requestType{requestType}
|
||||||
|
{}
|
||||||
|
|
||||||
|
Utils::PathString name;
|
||||||
|
CaptureCallback captureCallback;
|
||||||
|
AbortCallback abortCallback;
|
||||||
|
RequestType requestType = RequestType::Image;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::tuple<bool, Entry> getEntry();
|
||||||
|
void addEntry(Utils::PathString &&name,
|
||||||
|
CaptureCallback &&captureCallback,
|
||||||
|
AbortCallback &&abortCallback,
|
||||||
|
RequestType requestType);
|
||||||
|
void clearEntries();
|
||||||
|
void waitForEntries();
|
||||||
|
void stopThread();
|
||||||
|
bool isRunning();
|
||||||
|
static void request(Utils::SmallStringView name,
|
||||||
|
ImageCache::RequestType requestType,
|
||||||
|
ImageCache::CaptureCallback captureCallback,
|
||||||
|
ImageCache::AbortCallback abortCallback,
|
||||||
|
ImageCacheStorageInterface &storage,
|
||||||
|
ImageCacheGeneratorInterface &generator,
|
||||||
|
TimeStampProviderInterface &timeStampProvider);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Entry> m_entries;
|
||||||
|
mutable std::mutex m_mutex;
|
||||||
|
std::condition_variable m_condition;
|
||||||
|
std::thread m_backgroundThread;
|
||||||
|
ImageCacheStorageInterface &m_storage;
|
||||||
|
ImageCacheGeneratorInterface &m_generator;
|
||||||
|
TimeStampProviderInterface &m_timeStampProvider;
|
||||||
|
bool m_finishing{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace QmlDesigner
|
@@ -146,6 +146,11 @@ public:
|
|||||||
QVariant previewImageDataForGenericNode(const ModelNode &modelNode, const ModelNode &renderNode);
|
QVariant previewImageDataForGenericNode(const ModelNode &modelNode, const ModelNode &renderNode);
|
||||||
QVariant previewImageDataForImageNode(const ModelNode &modelNode);
|
QVariant previewImageDataForImageNode(const ModelNode &modelNode);
|
||||||
|
|
||||||
|
void setCrashCallback(std::function<void()> crashCallback)
|
||||||
|
{
|
||||||
|
m_crashCallback = std::move(crashCallback);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void timerEvent(QTimerEvent *event) override;
|
void timerEvent(QTimerEvent *event) override;
|
||||||
|
|
||||||
@@ -231,6 +236,7 @@ private:
|
|||||||
|
|
||||||
// key: fileUrl value: (key: instance qml id, value: related tool states)
|
// key: fileUrl value: (key: instance qml id, value: related tool states)
|
||||||
QHash<QUrl, QHash<QString, QVariantMap>> m_edit3DToolStates;
|
QHash<QUrl, QHash<QString, QVariantMap>> m_edit3DToolStates;
|
||||||
|
std::function<void()> m_crashCallback{[this] { handleCrash(); }};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ProxyNodeInstanceView
|
} // namespace ProxyNodeInstanceView
|
||||||
|
@@ -47,6 +47,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
PlainTextEditModifier(QPlainTextEdit *textEdit);
|
PlainTextEditModifier(QPlainTextEdit *textEdit);
|
||||||
|
PlainTextEditModifier(QTextDocument *document, const QTextCursor &textCursor);
|
||||||
~PlainTextEditModifier() override;
|
~PlainTextEditModifier() override;
|
||||||
|
|
||||||
QTextDocument *textDocument() const override;
|
QTextDocument *textDocument() const override;
|
||||||
@@ -76,20 +77,17 @@ public:
|
|||||||
bool moveToComponent(int /* nodeOffset */) override
|
bool moveToComponent(int /* nodeOffset */) override
|
||||||
{ return false; }
|
{ return false; }
|
||||||
|
|
||||||
protected:
|
|
||||||
QPlainTextEdit *plainTextEdit() const
|
|
||||||
{ return m_textEdit; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void textEditChanged();
|
void textEditChanged();
|
||||||
void runRewriting(Utils::ChangeSet *writer);
|
void runRewriting(Utils::ChangeSet *writer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::ChangeSet *m_changeSet;
|
Utils::ChangeSet *m_changeSet = nullptr;
|
||||||
QPlainTextEdit *m_textEdit;
|
QTextDocument *m_textDocument;
|
||||||
bool m_changeSignalsEnabled;
|
QTextCursor m_textCursor;
|
||||||
bool m_pendingChangeSignal;
|
bool m_changeSignalsEnabled{true};
|
||||||
bool m_ongoingTextChange;
|
bool m_pendingChangeSignal{false};
|
||||||
|
bool m_ongoingTextChange{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMLDESIGNERCORE_EXPORT NotIndentingTextEditModifier: public PlainTextEditModifier
|
class QMLDESIGNERCORE_EXPORT NotIndentingTextEditModifier: public PlainTextEditModifier
|
||||||
@@ -99,6 +97,10 @@ public:
|
|||||||
: PlainTextEditModifier(textEdit)
|
: PlainTextEditModifier(textEdit)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
NotIndentingTextEditModifier(QTextDocument *document, const QTextCursor &textCursor)
|
||||||
|
: PlainTextEditModifier{document, textCursor}
|
||||||
|
{}
|
||||||
|
|
||||||
void indent(int /*offset*/, int /*length*/) override
|
void indent(int /*offset*/, int /*length*/) override
|
||||||
{}
|
{}
|
||||||
void indentLines(int /*offset*/, int /*length*/) override
|
void indentLines(int /*offset*/, int /*length*/) override
|
||||||
|
@@ -33,11 +33,12 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
void BaseConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
void BaseConnectionManager::setUp(NodeInstanceServerInterface *nodeInstanceServer,
|
||||||
const QString &,
|
const QString &,
|
||||||
ProjectExplorer::Target *)
|
ProjectExplorer::Target *,
|
||||||
|
AbstractView *view)
|
||||||
{
|
{
|
||||||
m_nodeInstanceServerProxy = nodeInstanceServerProxy;
|
m_nodeInstanceServer = nodeInstanceServer;
|
||||||
m_isActive = true;
|
m_isActive = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,14 @@ void BaseConnectionManager::shutDown()
|
|||||||
|
|
||||||
writeCommand(QVariant::fromValue(EndPuppetCommand()));
|
writeCommand(QVariant::fromValue(EndPuppetCommand()));
|
||||||
|
|
||||||
m_nodeInstanceServerProxy = nullptr;
|
m_nodeInstanceServer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseConnectionManager::setCrashCallback(std::function<void()> callback)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock{m_callbackMutex};
|
||||||
|
|
||||||
|
m_crashCallback = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseConnectionManager::isActive() const
|
bool BaseConnectionManager::isActive() const
|
||||||
@@ -85,7 +93,7 @@ void BaseConnectionManager::dispatchCommand(const QVariant &command, Connection
|
|||||||
if (!isActive())
|
if (!isActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_nodeInstanceServerProxy->dispatchCommand(command);
|
m_nodeInstanceServer->dispatchCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseConnectionManager::readDataStream(Connection &connection)
|
void BaseConnectionManager::readDataStream(Connection &connection)
|
||||||
@@ -123,5 +131,12 @@ void BaseConnectionManager::readDataStream(Connection &connection)
|
|||||||
for (const QVariant &command : commandList)
|
for (const QVariant &command : commandList)
|
||||||
dispatchCommand(command, connection);
|
dispatchCommand(command, connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseConnectionManager::callCrashCallback()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock{m_callbackMutex};
|
||||||
|
|
||||||
|
m_crashCallback();
|
||||||
|
}
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|
||||||
|
@@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QLocalSocket;
|
class QLocalSocket;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -40,7 +42,6 @@ class Target;
|
|||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class AbstractView;
|
class AbstractView;
|
||||||
class NodeInstanceServerProxy;
|
|
||||||
|
|
||||||
class QMLDESIGNERCORE_EXPORT BaseConnectionManager : public QObject, public ConnectionManagerInterface
|
class QMLDESIGNERCORE_EXPORT BaseConnectionManager : public QObject, public ConnectionManagerInterface
|
||||||
{
|
{
|
||||||
@@ -49,11 +50,14 @@ class QMLDESIGNERCORE_EXPORT BaseConnectionManager : public QObject, public Conn
|
|||||||
public:
|
public:
|
||||||
BaseConnectionManager() = default;
|
BaseConnectionManager() = default;
|
||||||
|
|
||||||
void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
void setUp(NodeInstanceServerInterface *nodeInstanceServer,
|
||||||
const QString &qrcMappingString,
|
const QString &qrcMappingString,
|
||||||
ProjectExplorer::Target *target) override;
|
ProjectExplorer::Target *target,
|
||||||
|
AbstractView *view) override;
|
||||||
void shutDown() override;
|
void shutDown() override;
|
||||||
|
|
||||||
|
void setCrashCallback(std::function<void()> callback) override;
|
||||||
|
|
||||||
bool isActive() const;
|
bool isActive() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -61,15 +65,19 @@ protected:
|
|||||||
virtual void showCannotConnectToPuppetWarningAndSwitchToEditMode();
|
virtual void showCannotConnectToPuppetWarningAndSwitchToEditMode();
|
||||||
using ConnectionManagerInterface::processFinished;
|
using ConnectionManagerInterface::processFinished;
|
||||||
void processFinished();
|
void processFinished();
|
||||||
void writeCommandToIODevice(const QVariant &command,
|
static void writeCommandToIODevice(const QVariant &command,
|
||||||
QIODevice *ioDevice,
|
QIODevice *ioDevice,
|
||||||
unsigned int commandCounter);
|
unsigned int commandCounter);
|
||||||
void readDataStream(Connection &connection);
|
void readDataStream(Connection &connection);
|
||||||
|
|
||||||
NodeInstanceServerProxy *nodeInstanceServerProxy() const { return m_nodeInstanceServerProxy; }
|
NodeInstanceServerInterface *nodeInstanceServer() const { return m_nodeInstanceServer; }
|
||||||
|
|
||||||
|
void callCrashCallback();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeInstanceServerProxy *m_nodeInstanceServerProxy{};
|
std::mutex m_callbackMutex;
|
||||||
|
std::function<void()> m_crashCallback;
|
||||||
|
NodeInstanceServerInterface *m_nodeInstanceServer{};
|
||||||
bool m_isActive = false;
|
bool m_isActive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -34,11 +34,12 @@
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
void CapturingConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
void CapturingConnectionManager::setUp(NodeInstanceServerInterface *nodeInstanceServer,
|
||||||
const QString &qrcMappingString,
|
const QString &qrcMappingString,
|
||||||
ProjectExplorer::Target *target)
|
ProjectExplorer::Target *target,
|
||||||
|
AbstractView *view)
|
||||||
{
|
{
|
||||||
InteractiveConnectionManager::setUp(nodeInstanceServerProxy, qrcMappingString, target);
|
InteractiveConnectionManager::setUp(nodeInstanceServer, qrcMappingString, target, view);
|
||||||
|
|
||||||
int indexOfCapturePuppetStream = QCoreApplication::arguments().indexOf(
|
int indexOfCapturePuppetStream = QCoreApplication::arguments().indexOf(
|
||||||
"-capture-puppet-stream");
|
"-capture-puppet-stream");
|
||||||
@@ -72,7 +73,7 @@ void CapturingConnectionManager::writeCommand(const QVariant &command)
|
|||||||
|
|
||||||
if (m_captureFileForTest.isWritable()) {
|
if (m_captureFileForTest.isWritable()) {
|
||||||
qDebug() << "command name: " << QMetaType::typeName(command.userType());
|
qDebug() << "command name: " << QMetaType::typeName(command.userType());
|
||||||
writeCommandToIODevice(command, &m_captureFileForTest, m_writeCommandCounter);
|
writeCommandToIODevice(command, &m_captureFileForTest, writeCommandCounter());
|
||||||
qDebug() << "\tcatpure file offset: " << m_captureFileForTest.pos();
|
qDebug() << "\tcatpure file offset: " << m_captureFileForTest.pos();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,9 +32,10 @@ namespace QmlDesigner {
|
|||||||
class QMLDESIGNERCORE_EXPORT CapturingConnectionManager : public InteractiveConnectionManager
|
class QMLDESIGNERCORE_EXPORT CapturingConnectionManager : public InteractiveConnectionManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
void setUp(NodeInstanceServerInterface *nodeInstanceServer,
|
||||||
const QString &qrcMappingString,
|
const QString &qrcMappingString,
|
||||||
ProjectExplorer::Target *target) override;
|
ProjectExplorer::Target *target,
|
||||||
|
AbstractView *view) override;
|
||||||
|
|
||||||
void processFinished(int exitCode, QProcess::ExitStatus exitStatus) override;
|
void processFinished(int exitCode, QProcess::ExitStatus exitStatus) override;
|
||||||
|
|
||||||
|
@@ -46,19 +46,19 @@ ConnectionManager::ConnectionManager() = default;
|
|||||||
|
|
||||||
ConnectionManager::~ConnectionManager() = default;
|
ConnectionManager::~ConnectionManager() = default;
|
||||||
|
|
||||||
void ConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
void ConnectionManager::setUp(NodeInstanceServerInterface *nodeInstanceServerProxy,
|
||||||
const QString &qrcMappingString,
|
const QString &qrcMappingString,
|
||||||
ProjectExplorer::Target *target)
|
ProjectExplorer::Target *target,
|
||||||
|
AbstractView *view)
|
||||||
{
|
{
|
||||||
BaseConnectionManager::setUp(nodeInstanceServerProxy, qrcMappingString, target);
|
BaseConnectionManager::setUp(nodeInstanceServerProxy, qrcMappingString, target, view);
|
||||||
|
|
||||||
m_localServer = std::make_unique<QLocalServer>();
|
m_localServer = std::make_unique<QLocalServer>();
|
||||||
QString socketToken(QUuid::createUuid().toString());
|
QString socketToken(QUuid::createUuid().toString());
|
||||||
m_localServer->listen(socketToken);
|
m_localServer->listen(socketToken);
|
||||||
m_localServer->setMaxPendingConnections(3);
|
m_localServer->setMaxPendingConnections(3);
|
||||||
|
|
||||||
NodeInstanceView *nodeInstanceView = nodeInstanceServerProxy->nodeInstanceView();
|
PuppetCreator puppetCreator(target, view->model());
|
||||||
PuppetCreator puppetCreator(target, nodeInstanceView->model());
|
|
||||||
puppetCreator.setQrcMappingString(qrcMappingString);
|
puppetCreator.setQrcMappingString(qrcMappingString);
|
||||||
|
|
||||||
puppetCreator.createQml2PuppetExecutableIfMissing();
|
puppetCreator.createQml2PuppetExecutableIfMissing();
|
||||||
@@ -67,7 +67,6 @@ void ConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
|||||||
connection.qmlPuppetProcess = puppetCreator.createPuppetProcess(
|
connection.qmlPuppetProcess = puppetCreator.createPuppetProcess(
|
||||||
connection.mode,
|
connection.mode,
|
||||||
socketToken,
|
socketToken,
|
||||||
nodeInstanceView,
|
|
||||||
[&] { printProcessOutput(connection.qmlPuppetProcess.get(), connection.name); },
|
[&] { printProcessOutput(connection.qmlPuppetProcess.get(), connection.name); },
|
||||||
[&](int exitCode, QProcess::ExitStatus exitStatus) {
|
[&](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||||
processFinished(exitCode, exitStatus);
|
processFinished(exitCode, exitStatus);
|
||||||
@@ -90,7 +89,7 @@ void ConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
|||||||
|
|
||||||
if (connectedToPuppet) {
|
if (connectedToPuppet) {
|
||||||
connection.socket.reset(m_localServer->nextPendingConnection());
|
connection.socket.reset(m_localServer->nextPendingConnection());
|
||||||
QObject::connect(connection.socket.get(), &QIODevice::readyRead, [&] {
|
QObject::connect(connection.socket.get(), &QIODevice::readyRead, this, [&] {
|
||||||
readDataStream(connection);
|
readDataStream(connection);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -101,11 +100,6 @@ void ConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_localServer->close();
|
m_localServer->close();
|
||||||
|
|
||||||
connect(this,
|
|
||||||
&ConnectionManager::processCrashed,
|
|
||||||
nodeInstanceServerProxy,
|
|
||||||
&NodeInstanceServerProxy::processCrashed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionManager::shutDown()
|
void ConnectionManager::shutDown()
|
||||||
@@ -143,7 +137,7 @@ void ConnectionManager::processFinished(int exitCode, QProcess::ExitStatus exitS
|
|||||||
closeSocketsAndKillProcesses();
|
closeSocketsAndKillProcesses();
|
||||||
|
|
||||||
if (exitStatus == QProcess::CrashExit)
|
if (exitStatus == QProcess::CrashExit)
|
||||||
emit processCrashed();
|
callCrashCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionManager::closeSocketsAndKillProcesses()
|
void ConnectionManager::closeSocketsAndKillProcesses()
|
||||||
|
@@ -48,19 +48,20 @@ public:
|
|||||||
~ConnectionManager() override;
|
~ConnectionManager() override;
|
||||||
enum PuppetStreamType { FirstPuppetStream, SecondPuppetStream, ThirdPuppetStream };
|
enum PuppetStreamType { FirstPuppetStream, SecondPuppetStream, ThirdPuppetStream };
|
||||||
|
|
||||||
void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
void setUp(NodeInstanceServerInterface *nodeInstanceServerProxy,
|
||||||
const QString &qrcMappingString,
|
const QString &qrcMappingString,
|
||||||
ProjectExplorer::Target *target) override;
|
ProjectExplorer::Target *target,
|
||||||
|
AbstractView *view) override;
|
||||||
void shutDown() override;
|
void shutDown() override;
|
||||||
|
|
||||||
void writeCommand(const QVariant &command) override;
|
void writeCommand(const QVariant &command) override;
|
||||||
|
|
||||||
signals:
|
|
||||||
void processCrashed();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using BaseConnectionManager::processFinished;
|
using BaseConnectionManager::processFinished;
|
||||||
void processFinished(int exitCode, QProcess::ExitStatus exitStatus) override;
|
void processFinished(int exitCode, QProcess::ExitStatus exitStatus) override;
|
||||||
|
std::vector<Connection> &connections() { return m_connections; }
|
||||||
|
|
||||||
|
quint32 &writeCommandCounter() { return m_writeCommandCounter; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void printProcessOutput(QProcess *process, const QString &connectionName);
|
void printProcessOutput(QProcess *process, const QString &connectionName);
|
||||||
@@ -69,7 +70,6 @@ private:
|
|||||||
private:
|
private:
|
||||||
std::unique_ptr<QLocalServer> m_localServer;
|
std::unique_ptr<QLocalServer> m_localServer;
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<Connection> m_connections;
|
std::vector<Connection> m_connections;
|
||||||
quint32 m_writeCommandCounter = 0;
|
quint32 m_writeCommandCounter = 0;
|
||||||
};
|
};
|
||||||
|
@@ -38,7 +38,8 @@ class Target;
|
|||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class NodeInstanceServerProxy;
|
class NodeInstanceServerInterface;
|
||||||
|
class AbstractView;
|
||||||
|
|
||||||
class QMLDESIGNERCORE_EXPORT ConnectionManagerInterface
|
class QMLDESIGNERCORE_EXPORT ConnectionManagerInterface
|
||||||
{
|
{
|
||||||
@@ -65,12 +66,15 @@ public:
|
|||||||
|
|
||||||
virtual ~ConnectionManagerInterface();
|
virtual ~ConnectionManagerInterface();
|
||||||
|
|
||||||
virtual void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
virtual void setUp(NodeInstanceServerInterface *nodeInstanceServer,
|
||||||
const QString &qrcMappingString,
|
const QString &qrcMappingString,
|
||||||
ProjectExplorer::Target *target)
|
ProjectExplorer::Target *target,
|
||||||
|
AbstractView *view)
|
||||||
= 0;
|
= 0;
|
||||||
virtual void shutDown() = 0;
|
virtual void shutDown() = 0;
|
||||||
|
|
||||||
|
virtual void setCrashCallback(std::function<void()> callback) = 0;
|
||||||
|
|
||||||
virtual void writeCommand(const QVariant &command) = 0;
|
virtual void writeCommand(const QVariant &command) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -38,20 +38,21 @@ namespace QmlDesigner {
|
|||||||
|
|
||||||
InteractiveConnectionManager::InteractiveConnectionManager()
|
InteractiveConnectionManager::InteractiveConnectionManager()
|
||||||
{
|
{
|
||||||
m_connections.emplace_back("Editor", "editormode");
|
connections().emplace_back("Editor", "editormode");
|
||||||
m_connections.emplace_back("Render", "rendermode");
|
connections().emplace_back("Render", "rendermode");
|
||||||
m_connections.emplace_back("Preview", "previewmode");
|
connections().emplace_back("Preview", "previewmode");
|
||||||
}
|
}
|
||||||
|
|
||||||
void InteractiveConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
void InteractiveConnectionManager::setUp(NodeInstanceServerInterface *nodeInstanceServer,
|
||||||
const QString &qrcMappingString,
|
const QString &qrcMappingString,
|
||||||
ProjectExplorer::Target *target)
|
ProjectExplorer::Target *target,
|
||||||
|
AbstractView *view)
|
||||||
{
|
{
|
||||||
ConnectionManager::setUp(nodeInstanceServerProxy, qrcMappingString, target);
|
ConnectionManager::setUp(nodeInstanceServer, qrcMappingString, target, view);
|
||||||
|
|
||||||
DesignerSettings settings = QmlDesignerPlugin::instance()->settings();
|
DesignerSettings settings = QmlDesignerPlugin::instance()->settings();
|
||||||
int timeOutTime = settings.value(DesignerSettingsKey::PUPPET_KILL_TIMEOUT).toInt();
|
int timeOutTime = settings.value(DesignerSettingsKey::PUPPET_KILL_TIMEOUT).toInt();
|
||||||
for (Connection &connection : m_connections)
|
for (Connection &connection : connections())
|
||||||
connection.timer->setInterval(timeOutTime);
|
connection.timer->setInterval(timeOutTime);
|
||||||
|
|
||||||
if (QmlDesignerPlugin::instance()
|
if (QmlDesignerPlugin::instance()
|
||||||
@@ -59,7 +60,7 @@ void InteractiveConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceSe
|
|||||||
.value(DesignerSettingsKey::DEBUG_PUPPET)
|
.value(DesignerSettingsKey::DEBUG_PUPPET)
|
||||||
.toString()
|
.toString()
|
||||||
.isEmpty()) {
|
.isEmpty()) {
|
||||||
for (Connection &connection : m_connections) {
|
for (Connection &connection : connections()) {
|
||||||
QObject::connect(connection.timer.get(), &QTimer::timeout, [&]() {
|
QObject::connect(connection.timer.get(), &QTimer::timeout, [&]() {
|
||||||
puppetTimeout(connection);
|
puppetTimeout(connection);
|
||||||
});
|
});
|
||||||
@@ -67,6 +68,12 @@ void InteractiveConnectionManager::setUp(NodeInstanceServerProxy *nodeInstanceSe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InteractiveConnectionManager::shutDown()
|
||||||
|
{
|
||||||
|
m_view = {};
|
||||||
|
ConnectionManager::shutDown();
|
||||||
|
}
|
||||||
|
|
||||||
void InteractiveConnectionManager::showCannotConnectToPuppetWarningAndSwitchToEditMode()
|
void InteractiveConnectionManager::showCannotConnectToPuppetWarningAndSwitchToEditMode()
|
||||||
{
|
{
|
||||||
Core::AsynchronousMessageBox::warning(
|
Core::AsynchronousMessageBox::warning(
|
||||||
@@ -75,8 +82,8 @@ void InteractiveConnectionManager::showCannotConnectToPuppetWarningAndSwitchToEd
|
|||||||
"Switching to another kit might help."));
|
"Switching to another kit might help."));
|
||||||
|
|
||||||
QmlDesignerPlugin::instance()->switchToTextModeDeferred();
|
QmlDesignerPlugin::instance()->switchToTextModeDeferred();
|
||||||
nodeInstanceServerProxy()->nodeInstanceView()->emitDocumentMessage(
|
if (m_view)
|
||||||
tr("Cannot Connect to QML Emulation Layer (QML Puppet)"));
|
m_view->emitDocumentMessage(tr("Cannot Connect to QML Emulation Layer (QML Puppet)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InteractiveConnectionManager::dispatchCommand(const QVariant &command, Connection &connection)
|
void InteractiveConnectionManager::dispatchCommand(const QVariant &command, Connection &connection)
|
||||||
|
@@ -34,9 +34,12 @@ class InteractiveConnectionManager : public ConnectionManager
|
|||||||
public:
|
public:
|
||||||
InteractiveConnectionManager();
|
InteractiveConnectionManager();
|
||||||
|
|
||||||
void setUp(NodeInstanceServerProxy *nodeInstanceServerProxy,
|
void setUp(NodeInstanceServerInterface *nodeInstanceServer,
|
||||||
const QString &qrcMappingString,
|
const QString &qrcMappingString,
|
||||||
ProjectExplorer::Target *target) override;
|
ProjectExplorer::Target *target,
|
||||||
|
AbstractView *view) override;
|
||||||
|
|
||||||
|
void shutDown() override;
|
||||||
|
|
||||||
void showCannotConnectToPuppetWarningAndSwitchToEditMode() override;
|
void showCannotConnectToPuppetWarningAndSwitchToEditMode() override;
|
||||||
|
|
||||||
@@ -46,6 +49,9 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void puppetTimeout(Connection &connection);
|
void puppetTimeout(Connection &connection);
|
||||||
void puppetAlive(Connection &connection);
|
void puppetAlive(Connection &connection);
|
||||||
|
|
||||||
|
private:
|
||||||
|
AbstractView *m_view{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -100,7 +100,7 @@ NodeInstanceServerProxy::NodeInstanceServerProxy(NodeInstanceView *nodeInstanceV
|
|||||||
if (instanceViewBenchmark().isInfoEnabled())
|
if (instanceViewBenchmark().isInfoEnabled())
|
||||||
m_benchmarkTimer.start();
|
m_benchmarkTimer.start();
|
||||||
|
|
||||||
m_connectionManager.setUp(this, qrcMappingString(), target);
|
m_connectionManager.setUp(this, qrcMappingString(), target, nodeInstanceView);
|
||||||
|
|
||||||
qCInfo(instanceViewBenchmark) << "puppets setup:" << m_benchmarkTimer.elapsed();
|
qCInfo(instanceViewBenchmark) << "puppets setup:" << m_benchmarkTimer.elapsed();
|
||||||
}
|
}
|
||||||
|
@@ -84,6 +84,7 @@ public:
|
|||||||
void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command) override;
|
void requestModelNodePreviewImage(const RequestModelNodePreviewImageCommand &command) override;
|
||||||
void changeLanguage(const ChangeLanguageCommand &command) override;
|
void changeLanguage(const ChangeLanguageCommand &command) override;
|
||||||
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override;
|
void changePreviewImageSize(const ChangePreviewImageSizeCommand &command) override;
|
||||||
|
void dispatchCommand(const QVariant &command) override;
|
||||||
|
|
||||||
NodeInstanceView *nodeInstanceView() const { return m_nodeInstanceView; }
|
NodeInstanceView *nodeInstanceView() const { return m_nodeInstanceView; }
|
||||||
|
|
||||||
@@ -91,12 +92,8 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void writeCommand(const QVariant &command);
|
void writeCommand(const QVariant &command);
|
||||||
void dispatchCommand(const QVariant &command);
|
|
||||||
NodeInstanceClientInterface *nodeInstanceClient() const;
|
NodeInstanceClientInterface *nodeInstanceClient() const;
|
||||||
|
|
||||||
signals:
|
|
||||||
void processCrashed();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeInstanceView *m_nodeInstanceView{};
|
NodeInstanceView *m_nodeInstanceView{};
|
||||||
QElapsedTimer m_benchmarkTimer;
|
QElapsedTimer m_benchmarkTimer;
|
||||||
|
@@ -196,10 +196,7 @@ void NodeInstanceView::modelAttached(Model *model)
|
|||||||
AbstractView::modelAttached(model);
|
AbstractView::modelAttached(model);
|
||||||
m_nodeInstanceServer = createNodeInstanceServerProxy();
|
m_nodeInstanceServer = createNodeInstanceServerProxy();
|
||||||
m_lastCrashTime.start();
|
m_lastCrashTime.start();
|
||||||
connect(m_nodeInstanceServer.get(),
|
m_connectionManager.setCrashCallback(m_crashCallback);
|
||||||
&NodeInstanceServerProxy::processCrashed,
|
|
||||||
this,
|
|
||||||
&NodeInstanceView::handleCrash);
|
|
||||||
|
|
||||||
if (!isSkippedRootNode(rootModelNode())) {
|
if (!isSkippedRootNode(rootModelNode())) {
|
||||||
m_nodeInstanceServer->createScene(createCreateSceneCommand());
|
m_nodeInstanceServer->createScene(createCreateSceneCommand());
|
||||||
@@ -215,6 +212,8 @@ void NodeInstanceView::modelAttached(Model *model)
|
|||||||
|
|
||||||
void NodeInstanceView::modelAboutToBeDetached(Model * model)
|
void NodeInstanceView::modelAboutToBeDetached(Model * model)
|
||||||
{
|
{
|
||||||
|
m_connectionManager.setCrashCallback({});
|
||||||
|
|
||||||
removeAllInstanceNodeRelationships();
|
removeAllInstanceNodeRelationships();
|
||||||
if (m_nodeInstanceServer) {
|
if (m_nodeInstanceServer) {
|
||||||
m_nodeInstanceServer->clearScene(createClearSceneCommand());
|
m_nodeInstanceServer->clearScene(createClearSceneCommand());
|
||||||
@@ -281,11 +280,6 @@ void NodeInstanceView::restartProcess()
|
|||||||
m_nodeInstanceServer.reset();
|
m_nodeInstanceServer.reset();
|
||||||
m_nodeInstanceServer = createNodeInstanceServerProxy();
|
m_nodeInstanceServer = createNodeInstanceServerProxy();
|
||||||
|
|
||||||
connect(m_nodeInstanceServer.get(),
|
|
||||||
&NodeInstanceServerProxy::processCrashed,
|
|
||||||
this,
|
|
||||||
&NodeInstanceView::handleCrash);
|
|
||||||
|
|
||||||
if (!isSkippedRootNode(rootModelNode())) {
|
if (!isSkippedRootNode(rootModelNode())) {
|
||||||
m_nodeInstanceServer->createScene(createCreateSceneCommand());
|
m_nodeInstanceServer->createScene(createCreateSceneCommand());
|
||||||
m_nodeInstanceServer->changeSelection(
|
m_nodeInstanceServer->changeSelection(
|
||||||
|
@@ -181,7 +181,6 @@ PuppetCreator::PuppetCreator(ProjectExplorer::Target *target, const Model *model
|
|||||||
QProcessUniquePointer PuppetCreator::createPuppetProcess(
|
QProcessUniquePointer PuppetCreator::createPuppetProcess(
|
||||||
const QString &puppetMode,
|
const QString &puppetMode,
|
||||||
const QString &socketToken,
|
const QString &socketToken,
|
||||||
QObject *handlerObject,
|
|
||||||
std::function<void()> processOutputCallback,
|
std::function<void()> processOutputCallback,
|
||||||
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
||||||
const QStringList &customOptions) const
|
const QStringList &customOptions) const
|
||||||
@@ -190,7 +189,6 @@ QProcessUniquePointer PuppetCreator::createPuppetProcess(
|
|||||||
qmlPuppetDirectory(m_availablePuppetType),
|
qmlPuppetDirectory(m_availablePuppetType),
|
||||||
puppetMode,
|
puppetMode,
|
||||||
socketToken,
|
socketToken,
|
||||||
handlerObject,
|
|
||||||
processOutputCallback,
|
processOutputCallback,
|
||||||
processFinishCallback,
|
processFinishCallback,
|
||||||
customOptions);
|
customOptions);
|
||||||
@@ -201,7 +199,6 @@ QProcessUniquePointer PuppetCreator::puppetProcess(
|
|||||||
const QString &workingDirectory,
|
const QString &workingDirectory,
|
||||||
const QString &puppetMode,
|
const QString &puppetMode,
|
||||||
const QString &socketToken,
|
const QString &socketToken,
|
||||||
QObject *handlerObject,
|
|
||||||
std::function<void()> processOutputCallback,
|
std::function<void()> processOutputCallback,
|
||||||
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
||||||
const QStringList &customOptions) const
|
const QStringList &customOptions) const
|
||||||
@@ -216,7 +213,6 @@ QProcessUniquePointer PuppetCreator::puppetProcess(
|
|||||||
&QProcess::kill);
|
&QProcess::kill);
|
||||||
QObject::connect(puppetProcess.get(),
|
QObject::connect(puppetProcess.get(),
|
||||||
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||||
handlerObject,
|
|
||||||
processFinishCallback);
|
processFinishCallback);
|
||||||
|
|
||||||
#ifndef QMLDESIGNER_TEST
|
#ifndef QMLDESIGNER_TEST
|
||||||
@@ -227,7 +223,7 @@ QProcessUniquePointer PuppetCreator::puppetProcess(
|
|||||||
#endif
|
#endif
|
||||||
if (forwardOutput == puppetMode || forwardOutput == "all") {
|
if (forwardOutput == puppetMode || forwardOutput == "all") {
|
||||||
puppetProcess->setProcessChannelMode(QProcess::MergedChannels);
|
puppetProcess->setProcessChannelMode(QProcess::MergedChannels);
|
||||||
QObject::connect(puppetProcess.get(), &QProcess::readyRead, handlerObject, processOutputCallback);
|
QObject::connect(puppetProcess.get(), &QProcess::readyRead, processOutputCallback);
|
||||||
}
|
}
|
||||||
puppetProcess->setWorkingDirectory(workingDirectory);
|
puppetProcess->setWorkingDirectory(workingDirectory);
|
||||||
|
|
||||||
|
@@ -58,7 +58,6 @@ public:
|
|||||||
QProcessUniquePointer createPuppetProcess(
|
QProcessUniquePointer createPuppetProcess(
|
||||||
const QString &puppetMode,
|
const QString &puppetMode,
|
||||||
const QString &socketToken,
|
const QString &socketToken,
|
||||||
QObject *handlerObject,
|
|
||||||
std::function<void()> processOutputCallback,
|
std::function<void()> processOutputCallback,
|
||||||
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
||||||
const QStringList &customOptions = {}) const;
|
const QStringList &customOptions = {}) const;
|
||||||
@@ -89,7 +88,6 @@ protected:
|
|||||||
const QString &workingDirectory,
|
const QString &workingDirectory,
|
||||||
const QString &puppetMode,
|
const QString &puppetMode,
|
||||||
const QString &socketToken,
|
const QString &socketToken,
|
||||||
QObject *handlerObject,
|
|
||||||
std::function<void()> processOutputCallback,
|
std::function<void()> processOutputCallback,
|
||||||
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
std::function<void(int, QProcess::ExitStatus)> processFinishCallback,
|
||||||
const QStringList &customOptions) const;
|
const QStringList &customOptions) const;
|
||||||
|
@@ -38,8 +38,9 @@
|
|||||||
|
|
||||||
using namespace QmlDesigner;
|
using namespace QmlDesigner;
|
||||||
|
|
||||||
BaseTextEditModifier::BaseTextEditModifier(TextEditor::TextEditorWidget *textEdit):
|
BaseTextEditModifier::BaseTextEditModifier(TextEditor::TextEditorWidget *textEdit)
|
||||||
PlainTextEditModifier(textEdit)
|
: PlainTextEditModifier(textEdit)
|
||||||
|
, m_textEdit{textEdit}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,21 +48,20 @@ void BaseTextEditModifier::indentLines(int startLine, int endLine)
|
|||||||
{
|
{
|
||||||
if (startLine < 0)
|
if (startLine < 0)
|
||||||
return;
|
return;
|
||||||
auto baseTextEditorWidget = qobject_cast<TextEditor::TextEditorWidget*>(plainTextEdit());
|
|
||||||
if (!baseTextEditorWidget)
|
if (!m_textEdit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QTextDocument *textDocument = plainTextEdit()->document();
|
TextEditor::TextDocument *baseTextEditorDocument = m_textEdit->textDocument();
|
||||||
TextEditor::TextDocument *baseTextEditorDocument = baseTextEditorWidget->textDocument();
|
|
||||||
TextEditor::TabSettings tabSettings = baseTextEditorDocument->tabSettings();
|
TextEditor::TabSettings tabSettings = baseTextEditorDocument->tabSettings();
|
||||||
QTextCursor tc(textDocument);
|
QTextCursor tc(textDocument());
|
||||||
|
|
||||||
tc.beginEditBlock();
|
tc.beginEditBlock();
|
||||||
for (int i = startLine; i <= endLine; i++) {
|
for (int i = startLine; i <= endLine; i++) {
|
||||||
QTextBlock start = textDocument->findBlockByNumber(i);
|
QTextBlock start = textDocument()->findBlockByNumber(i);
|
||||||
|
|
||||||
if (start.isValid()) {
|
if (start.isValid()) {
|
||||||
QmlJSEditor::Internal::Indenter indenter(textDocument);
|
QmlJSEditor::Internal::Indenter indenter(textDocument());
|
||||||
indenter.indentBlock(start, QChar::Null, tabSettings);
|
indenter.indentBlock(start, QChar::Null, tabSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,22 +82,23 @@ void BaseTextEditModifier::indent(int offset, int length)
|
|||||||
|
|
||||||
int BaseTextEditModifier::indentDepth() const
|
int BaseTextEditModifier::indentDepth() const
|
||||||
{
|
{
|
||||||
if (auto bte = qobject_cast<TextEditor::TextEditorWidget*>(plainTextEdit()))
|
if (m_textEdit)
|
||||||
return bte->textDocument()->tabSettings().m_indentSize;
|
return m_textEdit->textDocument()->tabSettings().m_indentSize;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseTextEditModifier::renameId(const QString &oldId, const QString &newId)
|
bool BaseTextEditModifier::renameId(const QString &oldId, const QString &newId)
|
||||||
{
|
{
|
||||||
if (auto bte = qobject_cast<TextEditor::TextEditorWidget*>(plainTextEdit())) {
|
if (m_textEdit) {
|
||||||
if (auto document = qobject_cast<QmlJSEditor::QmlJSEditorDocument *>(bte->textDocument())) {
|
if (auto document = qobject_cast<QmlJSEditor::QmlJSEditorDocument *>(
|
||||||
|
m_textEdit->textDocument())) {
|
||||||
Utils::ChangeSet changeSet;
|
Utils::ChangeSet changeSet;
|
||||||
foreach (const QmlJS::SourceLocation &loc,
|
foreach (const QmlJS::SourceLocation &loc,
|
||||||
document->semanticInfo().idLocations.value(oldId)) {
|
document->semanticInfo().idLocations.value(oldId)) {
|
||||||
changeSet.replace(loc.begin(), loc.end(), newId);
|
changeSet.replace(loc.begin(), loc.end(), newId);
|
||||||
}
|
}
|
||||||
QTextCursor tc = bte->textCursor();
|
QTextCursor tc = textCursor();
|
||||||
changeSet.apply(&tc);
|
changeSet.apply(&tc);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -120,10 +121,9 @@ static QmlJS::AST::UiObjectDefinition *getObjectDefinition(const QList<QmlJS::AS
|
|||||||
|
|
||||||
bool BaseTextEditModifier::moveToComponent(int nodeOffset)
|
bool BaseTextEditModifier::moveToComponent(int nodeOffset)
|
||||||
{
|
{
|
||||||
if (auto bte = qobject_cast<TextEditor::TextEditorWidget*>(plainTextEdit())) {
|
if (m_textEdit) {
|
||||||
if (auto document
|
if (auto document = qobject_cast<QmlJSEditor::QmlJSEditorDocument *>(
|
||||||
= qobject_cast<QmlJSEditor::QmlJSEditorDocument *>(bte->textDocument())) {
|
m_textEdit->textDocument())) {
|
||||||
|
|
||||||
auto qualifiedId = QmlJS::AST::cast<QmlJS::AST::UiQualifiedId *>(document->semanticInfo().astNodeAt(nodeOffset));
|
auto qualifiedId = QmlJS::AST::cast<QmlJS::AST::UiQualifiedId *>(document->semanticInfo().astNodeAt(nodeOffset));
|
||||||
QList<QmlJS::AST::Node *> path = document->semanticInfo().rangePath(nodeOffset);
|
QList<QmlJS::AST::Node *> path = document->semanticInfo().rangePath(nodeOffset);
|
||||||
QmlJS::AST::UiObjectDefinition *object = getObjectDefinition(path, qualifiedId);
|
QmlJS::AST::UiObjectDefinition *object = getObjectDefinition(path, qualifiedId);
|
||||||
@@ -140,9 +140,9 @@ bool BaseTextEditModifier::moveToComponent(int nodeOffset)
|
|||||||
|
|
||||||
QStringList BaseTextEditModifier::autoComplete(QTextDocument *textDocument, int position, bool explicitComplete)
|
QStringList BaseTextEditModifier::autoComplete(QTextDocument *textDocument, int position, bool explicitComplete)
|
||||||
{
|
{
|
||||||
if (auto bte = qobject_cast<TextEditor::TextEditorWidget*>(plainTextEdit()))
|
if (m_textEdit)
|
||||||
if (auto document
|
if (auto document = qobject_cast<QmlJSEditor::QmlJSEditorDocument *>(
|
||||||
= qobject_cast<QmlJSEditor::QmlJSEditorDocument *>(bte->textDocument()))
|
m_textEdit->textDocument()))
|
||||||
return QmlJSEditor::qmlJSAutoComplete(textDocument,
|
return QmlJSEditor::qmlJSAutoComplete(textDocument,
|
||||||
position,
|
position,
|
||||||
document->filePath(),
|
document->filePath(),
|
||||||
|
@@ -35,19 +35,17 @@
|
|||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
using namespace QmlDesigner;
|
using namespace QmlDesigner;
|
||||||
|
|
||||||
PlainTextEditModifier::PlainTextEditModifier(QPlainTextEdit *textEdit):
|
PlainTextEditModifier::PlainTextEditModifier(QPlainTextEdit *textEdit)
|
||||||
m_changeSet(nullptr),
|
: PlainTextEditModifier(textEdit->document(), textEdit->textCursor())
|
||||||
m_textEdit(textEdit),
|
|
||||||
m_changeSignalsEnabled(true),
|
|
||||||
m_pendingChangeSignal(false),
|
|
||||||
m_ongoingTextChange(false)
|
|
||||||
{
|
{
|
||||||
Q_ASSERT(textEdit);
|
connect(textEdit, &QPlainTextEdit::textChanged, this, &PlainTextEditModifier::textEditChanged);
|
||||||
|
|
||||||
connect(m_textEdit, &QPlainTextEdit::textChanged,
|
|
||||||
this, &PlainTextEditModifier::textEditChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlainTextEditModifier::PlainTextEditModifier(QTextDocument *document, const QTextCursor &textCursor)
|
||||||
|
: m_textDocument{document}
|
||||||
|
, m_textCursor{textCursor}
|
||||||
|
{}
|
||||||
|
|
||||||
PlainTextEditModifier::~PlainTextEditModifier() = default;
|
PlainTextEditModifier::~PlainTextEditModifier() = default;
|
||||||
|
|
||||||
void PlainTextEditModifier::replace(int offset, int length, const QString &replacement)
|
void PlainTextEditModifier::replace(int offset, int length, const QString &replacement)
|
||||||
@@ -158,17 +156,17 @@ void PlainTextEditModifier::runRewriting(ChangeSet *changeSet)
|
|||||||
|
|
||||||
QTextDocument *PlainTextEditModifier::textDocument() const
|
QTextDocument *PlainTextEditModifier::textDocument() const
|
||||||
{
|
{
|
||||||
return m_textEdit->document();
|
return m_textDocument;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PlainTextEditModifier::text() const
|
QString PlainTextEditModifier::text() const
|
||||||
{
|
{
|
||||||
return m_textEdit->toPlainText();
|
return m_textDocument->toPlainText();
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextCursor PlainTextEditModifier::textCursor() const
|
QTextCursor PlainTextEditModifier::textCursor() const
|
||||||
{
|
{
|
||||||
return m_textEdit->textCursor();
|
return m_textCursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlainTextEditModifier::deactivateChangeSignals()
|
void PlainTextEditModifier::deactivateChangeSignals()
|
||||||
|
@@ -3,7 +3,8 @@ QTC_LIB_DEPENDS += \
|
|||||||
utils \
|
utils \
|
||||||
qmljs \
|
qmljs \
|
||||||
qmleditorwidgets \
|
qmleditorwidgets \
|
||||||
advanceddockingsystem
|
advanceddockingsystem \
|
||||||
|
sqlite
|
||||||
QTC_PLUGIN_DEPENDS += \
|
QTC_PLUGIN_DEPENDS += \
|
||||||
coreplugin \
|
coreplugin \
|
||||||
texteditor \
|
texteditor \
|
||||||
|
@@ -35,6 +35,7 @@ include(components/annotationeditor/annotationeditor.pri)
|
|||||||
include(components/richtexteditor/richtexteditor.pri)
|
include(components/richtexteditor/richtexteditor.pri)
|
||||||
include(components/transitioneditor/transitioneditor.pri)
|
include(components/transitioneditor/transitioneditor.pri)
|
||||||
include(components/listmodeleditor/listmodeleditor.pri)
|
include(components/listmodeleditor/listmodeleditor.pri)
|
||||||
|
include(components/previewtooltip/previewtooltipbackend.pri)
|
||||||
|
|
||||||
BUILD_PUPPET_IN_CREATOR_BINPATH = $$(BUILD_PUPPET_IN_CREATOR_BINPATH)
|
BUILD_PUPPET_IN_CREATOR_BINPATH = $$(BUILD_PUPPET_IN_CREATOR_BINPATH)
|
||||||
!isEmpty(BUILD_PUPPET_IN_CREATOR_BINPATH) {
|
!isEmpty(BUILD_PUPPET_IN_CREATOR_BINPATH) {
|
||||||
|
@@ -27,6 +27,7 @@ Project {
|
|||||||
Depends { name: "LanguageUtils" }
|
Depends { name: "LanguageUtils" }
|
||||||
Depends { name: "QtSupport" }
|
Depends { name: "QtSupport" }
|
||||||
Depends { name: "app_version_header" }
|
Depends { name: "app_version_header" }
|
||||||
|
Depends { name: "Sqlite" }
|
||||||
|
|
||||||
cpp.defines: base.concat([
|
cpp.defines: base.concat([
|
||||||
"DESIGNER_CORE_LIBRARY",
|
"DESIGNER_CORE_LIBRARY",
|
||||||
@@ -411,6 +412,21 @@ Project {
|
|||||||
"pluginmanager/widgetpluginmanager.h",
|
"pluginmanager/widgetpluginmanager.h",
|
||||||
"pluginmanager/widgetpluginpath.cpp",
|
"pluginmanager/widgetpluginpath.cpp",
|
||||||
"pluginmanager/widgetpluginpath.h",
|
"pluginmanager/widgetpluginpath.h",
|
||||||
|
"include/imagecache.h",
|
||||||
|
"imagecache/imagecachecollector.cpp",
|
||||||
|
"imagecache/imagecachecollector.h",
|
||||||
|
"imagecache/imagecache.cpp",
|
||||||
|
"imagecache/imagecachecollectorinterface.h",
|
||||||
|
"imagecache/imagecacheconnectionmanager.cpp",
|
||||||
|
"imagecache/imagecacheconnectionmanager.h",
|
||||||
|
"imagecache/imagecachegeneratorinterface.h",
|
||||||
|
"imagecache/imagecachegenerator.cpp",
|
||||||
|
"imagecache/imagecachegenerator.h",
|
||||||
|
"imagecache/imagecachestorageinterface.h",
|
||||||
|
"imagecache/imagecachestorage.h",
|
||||||
|
"imagecache/timestampproviderinterface.h",
|
||||||
|
"imagecache/timestampprovider.h",
|
||||||
|
"imagecache/timestampprovider.cpp",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,6 +618,8 @@ Project {
|
|||||||
"itemlibrary/itemlibrarywidget.h",
|
"itemlibrary/itemlibrarywidget.h",
|
||||||
"itemlibrary/customfilesystemmodel.cpp",
|
"itemlibrary/customfilesystemmodel.cpp",
|
||||||
"itemlibrary/customfilesystemmodel.h",
|
"itemlibrary/customfilesystemmodel.h",
|
||||||
|
"itemlibrary/itemlibraryiconimageprovider.cpp",
|
||||||
|
"itemlibrary/itemlibraryiconimageprovider.h",
|
||||||
"navigator/iconcheckboxitemdelegate.cpp",
|
"navigator/iconcheckboxitemdelegate.cpp",
|
||||||
"navigator/iconcheckboxitemdelegate.h",
|
"navigator/iconcheckboxitemdelegate.h",
|
||||||
"navigator/nameitemdelegate.cpp",
|
"navigator/nameitemdelegate.cpp",
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
INCLUDEPATH += $$PWD
|
INCLUDEPATH += $$PWD
|
||||||
INCLUDEPATH += $$PWD/designercore/include
|
INCLUDEPATH += $$PWD/designercore/include
|
||||||
|
INCLUDEPATH += $$PWD/designercore/imagecache
|
||||||
INCLUDEPATH += $$PWD/designercore
|
INCLUDEPATH += $$PWD/designercore
|
||||||
INCLUDEPATH += $$PWD/../../../share/qtcreator/qml/qmlpuppet/interfaces
|
INCLUDEPATH += $$PWD/../../../share/qtcreator/qml/qmlpuppet/interfaces
|
||||||
INCLUDEPATH += $$PWD/../../../share/qtcreator/qml/qmlpuppet/types
|
INCLUDEPATH += $$PWD/../../../share/qtcreator/qml/qmlpuppet/types
|
||||||
@@ -30,9 +31,18 @@ SOURCES += \
|
|||||||
$$PWD/designercore/model/variantproperty.cpp\
|
$$PWD/designercore/model/variantproperty.cpp\
|
||||||
$$PWD/designercore/model/annotation.cpp \
|
$$PWD/designercore/model/annotation.cpp \
|
||||||
$$PWD/designercore/rewritertransaction.cpp \
|
$$PWD/designercore/rewritertransaction.cpp \
|
||||||
$$PWD/components/listmodeleditor/listmodeleditormodel.cpp
|
$$PWD/components/listmodeleditor/listmodeleditormodel.cpp \
|
||||||
|
$$PWD/designercore/imagecache/imagecache.cpp \
|
||||||
|
$$PWD/designercore/imagecache/imagecachegenerator.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
|
$$PWD/designercore/imagecache/imagecachecollectorinterface.h \
|
||||||
|
$$PWD/designercore/imagecache/imagecachestorage.h \
|
||||||
|
$$PWD/designercore/imagecache/imagecachegenerator.h \
|
||||||
|
$$PWD/designercore/imagecache/imagecachestorageinterface.h \
|
||||||
|
$$PWD/designercore/imagecache/imagecachegeneratorinterface.h \
|
||||||
|
$$PWD/designercore/imagecache/timestampproviderinterface.h \
|
||||||
|
$$PWD/designercore/include/imagecache.h \
|
||||||
$$PWD/designercore/include/modelnode.h \
|
$$PWD/designercore/include/modelnode.h \
|
||||||
$$PWD/designercore/include/model.h \
|
$$PWD/designercore/include/model.h \
|
||||||
$$PWD/../../../share/qtcreator/qml/qmlpuppet/interfaces/commondefines.h \
|
$$PWD/../../../share/qtcreator/qml/qmlpuppet/interfaces/commondefines.h \
|
||||||
|
@@ -174,6 +174,7 @@ extend_qtc_executable(qml2puppet
|
|||||||
qt5capturepreviewnodeinstanceserver.cpp qt5capturepreviewnodeinstanceserver.h
|
qt5capturepreviewnodeinstanceserver.cpp qt5capturepreviewnodeinstanceserver.h
|
||||||
nodeinstanceserverdispatcher.cpp nodeinstanceserverdispatcher.h
|
nodeinstanceserverdispatcher.cpp nodeinstanceserverdispatcher.h
|
||||||
capturenodeinstanceserverdispatcher.cpp capturenodeinstanceserverdispatcher.h
|
capturenodeinstanceserverdispatcher.cpp capturenodeinstanceserverdispatcher.h
|
||||||
|
qt5captureimagenodeinstanceserver.cpp qt5captureimagenodeinstanceserver.h
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_executable(qml2puppet
|
extend_qtc_executable(qml2puppet
|
||||||
|
@@ -224,6 +224,8 @@ QtcTool {
|
|||||||
"instances/servernodeinstance.h",
|
"instances/servernodeinstance.h",
|
||||||
"instances/qt5capturepreviewnodeinstanceserver.cpp",
|
"instances/qt5capturepreviewnodeinstanceserver.cpp",
|
||||||
"instances/qt5capturepreviewnodeinstanceserver.h",
|
"instances/qt5capturepreviewnodeinstanceserver.h",
|
||||||
|
"instances/qt5captureimagenodeinstanceserver.cpp",
|
||||||
|
"instances/qt5captureimagenodeinstanceserver.h",
|
||||||
"instances/nodeinstanceserverdispatcher.cpp",
|
"instances/nodeinstanceserverdispatcher.cpp",
|
||||||
"instances/nodeinstanceserverdispatcher.h",
|
"instances/nodeinstanceserverdispatcher.h",
|
||||||
"instances/capturenodeinstanceserverdispatcher.cpp",
|
"instances/capturenodeinstanceserverdispatcher.cpp",
|
||||||
|
@@ -28,6 +28,10 @@
|
|||||||
#include "qmldesignercorelib_global.h"
|
#include "qmldesignercorelib_global.h"
|
||||||
#include "abstractview.h"
|
#include "abstractview.h"
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class Target;
|
||||||
|
}
|
||||||
|
|
||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class NodeInstanceView : public AbstractView
|
class NodeInstanceView : public AbstractView
|
||||||
@@ -88,6 +92,8 @@ public:
|
|||||||
void requestModelNodePreviewImage(const ModelNode &node) {}
|
void requestModelNodePreviewImage(const ModelNode &node) {}
|
||||||
|
|
||||||
void sendToken(const QString &token, int number, const QVector<ModelNode> &nodeVector) {}
|
void sendToken(const QString &token, int number, const QVector<ModelNode> &nodeVector) {}
|
||||||
|
void setTarget(ProjectExplorer::Target *newTarget) {}
|
||||||
|
void setCrashCallback(std::function<void()>) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -174,6 +174,19 @@ add_qtc_test(unittest GTEST
|
|||||||
sqlstatementbuilder-test.cpp
|
sqlstatementbuilder-test.cpp
|
||||||
createtablesqlstatementbuilder-test.cpp
|
createtablesqlstatementbuilder-test.cpp
|
||||||
sqlitevalue-test.cpp
|
sqlitevalue-test.cpp
|
||||||
|
imagecache-test.cpp
|
||||||
|
imagecachegenerator-test.cpp
|
||||||
|
imagecachestorage-test.cpp
|
||||||
|
sqlitedatabasemock.h
|
||||||
|
sqlitereadstatementmock.cpp sqlitereadstatementmock.h
|
||||||
|
sqlitestatementmock.h
|
||||||
|
sqlitetransactionbackendmock.h
|
||||||
|
sqlitewritestatementmock.cpp sqlitewritestatementmock.h
|
||||||
|
notification.h
|
||||||
|
mocktimestampprovider.h
|
||||||
|
imagecachecollectormock.h
|
||||||
|
mockimagecachegenerator.h
|
||||||
|
mockimagecachestorage.h
|
||||||
)
|
)
|
||||||
|
|
||||||
function(extend_qtc_test_with_target_sources target)
|
function(extend_qtc_test_with_target_sources target)
|
||||||
@@ -335,6 +348,7 @@ extend_qtc_test(unittest
|
|||||||
"${QmlDesignerDir}"
|
"${QmlDesignerDir}"
|
||||||
"${QmlDesignerDir}/designercore"
|
"${QmlDesignerDir}/designercore"
|
||||||
"${QmlDesignerDir}/designercore/include"
|
"${QmlDesignerDir}/designercore/include"
|
||||||
|
"${QmlDesignerDir}/designercore/imagecache"
|
||||||
"${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/interfaces"
|
"${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/interfaces"
|
||||||
"${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/types"
|
"${QmlDesignerDir}/../../../share/qtcreator/qml/qmlpuppet/types"
|
||||||
DEFINES
|
DEFINES
|
||||||
@@ -382,6 +396,13 @@ extend_qtc_test(unittest
|
|||||||
model/signalhandlerproperty.cpp include/signalhandlerproperty.h
|
model/signalhandlerproperty.cpp include/signalhandlerproperty.h
|
||||||
model/variantproperty.cpp include/variantproperty.h
|
model/variantproperty.cpp include/variantproperty.h
|
||||||
rewritertransaction.cpp rewritertransaction.h
|
rewritertransaction.cpp rewritertransaction.h
|
||||||
|
imagecache/imagecache.cpp include/imagecache.h
|
||||||
|
imagecache/imagecachecollectorinterface.h
|
||||||
|
imagecache/imagecachegenerator.cpp imagecache/imagecachegenerator.h
|
||||||
|
imagecache/imagecachegeneratorinterface.h
|
||||||
|
imagecache/imagecachestorage.h
|
||||||
|
imagecache/imagecachestorageinterface.h
|
||||||
|
imagecache/timestampproviderinterface.h
|
||||||
|
|
||||||
include/qmldesignercorelib_global.h
|
include/qmldesignercorelib_global.h
|
||||||
|
|
||||||
|
@@ -14,10 +14,8 @@ defineTest(setGoogleTestDirectories) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isEmpty(GOOGLETEST_DIR) {
|
isEmpty(GOOGLETEST_DIR) {
|
||||||
exists($$PWD/../../../../googletest) {
|
exists($$PWD/3rdparty/googletest) {
|
||||||
setGoogleTestDirectories($$PWD/../../../../googletest)
|
setGoogleTestDirectories($$PWD/3rdparty/googletest)
|
||||||
} else: exists($$PWD/../../../../../googletest) {
|
|
||||||
setGoogleTestDirectories($$PWD/../../../../../googletest)
|
|
||||||
} else: linux {
|
} else: linux {
|
||||||
GTEST_INCLUDE_DIR = /usr/include/gtest
|
GTEST_INCLUDE_DIR = /usr/include/gtest
|
||||||
GMOCK_INCLUDE_DIR = /usr/include/gmock
|
GMOCK_INCLUDE_DIR = /usr/include/gmock
|
||||||
|
@@ -35,12 +35,16 @@ using testing::An;
|
|||||||
using testing::AnyNumber;
|
using testing::AnyNumber;
|
||||||
using testing::AnyOf;
|
using testing::AnyOf;
|
||||||
using testing::Assign;
|
using testing::Assign;
|
||||||
|
using testing::AtLeast;
|
||||||
|
using testing::AtMost;
|
||||||
|
using testing::Between;
|
||||||
using testing::ByMove;
|
using testing::ByMove;
|
||||||
using testing::ByRef;
|
using testing::ByRef;
|
||||||
using testing::ContainerEq;
|
using testing::ContainerEq;
|
||||||
using testing::Contains;
|
using testing::Contains;
|
||||||
using testing::ElementsAre;
|
using testing::ElementsAre;
|
||||||
using testing::Eq;
|
using testing::Eq;
|
||||||
|
using testing::Exactly;
|
||||||
using testing::Field;
|
using testing::Field;
|
||||||
using testing::Ge;
|
using testing::Ge;
|
||||||
using testing::Gt;
|
using testing::Gt;
|
||||||
|
@@ -70,6 +70,7 @@
|
|||||||
#include <usedmacro.h>
|
#include <usedmacro.h>
|
||||||
#include <utils/link.h>
|
#include <utils/link.h>
|
||||||
#include <variantproperty.h>
|
#include <variantproperty.h>
|
||||||
|
#include <qmldesigner/designercore/imagecache/imagecachestorageinterface.h>
|
||||||
|
|
||||||
#include <sqlite3ext.h>
|
#include <sqlite3ext.h>
|
||||||
|
|
||||||
@@ -1468,6 +1469,15 @@ std::ostream &operator<<(std::ostream &out, const VariantProperty &property)
|
|||||||
return out << "(" << property.parentModelNode() << ", " << property.name() << ", "
|
return out << "(" << property.parentModelNode() << ", " << property.name() << ", "
|
||||||
<< property.value() << ")";
|
<< property.value() << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
std::ostream &operator<<(std::ostream &out, const ImageCacheStorageEntry &entry)
|
||||||
|
{
|
||||||
|
return out << "(" << entry.image << ", " << entry.hasEntry << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|
||||||
void setFilePathCache(ClangBackEnd::FilePathCaching *cache)
|
void setFilePathCache(ClangBackEnd::FilePathCaching *cache)
|
||||||
|
@@ -356,6 +356,13 @@ class VariantProperty;
|
|||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const ModelNode &node);
|
std::ostream &operator<<(std::ostream &out, const ModelNode &node);
|
||||||
std::ostream &operator<<(std::ostream &out, const VariantProperty &property);
|
std::ostream &operator<<(std::ostream &out, const VariantProperty &property);
|
||||||
|
|
||||||
|
namespace Internal {
|
||||||
|
class ImageCacheStorageEntry;
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &out, const ImageCacheStorageEntry &entry);
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
|
||||||
void setFilePathCache(ClangBackEnd::FilePathCaching *filePathCache);
|
void setFilePathCache(ClangBackEnd::FilePathCaching *filePathCache);
|
||||||
|
@@ -85,6 +85,11 @@ std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &out, const QImage &image)
|
||||||
|
{
|
||||||
|
return out << "(" << image.width() << ", " << image.height() << ", " << image.format() << ")";
|
||||||
|
}
|
||||||
|
|
||||||
void PrintTo(const QString &text, std::ostream *os)
|
void PrintTo(const QString &text, std::ostream *os)
|
||||||
{
|
{
|
||||||
*os << text;
|
*os << text;
|
||||||
|
@@ -34,11 +34,13 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QVariant;
|
class QVariant;
|
||||||
class QString;
|
class QString;
|
||||||
class QTextCharFormat;
|
class QTextCharFormat;
|
||||||
|
class QImage;
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const QVariant &QVariant);
|
std::ostream &operator<<(std::ostream &out, const QVariant &QVariant);
|
||||||
std::ostream &operator<<(std::ostream &out, const QString &text);
|
std::ostream &operator<<(std::ostream &out, const QString &text);
|
||||||
std::ostream &operator<<(std::ostream &out, const QByteArray &byteArray);
|
std::ostream &operator<<(std::ostream &out, const QByteArray &byteArray);
|
||||||
std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format);
|
std::ostream &operator<<(std::ostream &out, const QTextCharFormat &format);
|
||||||
|
std::ostream &operator<<(std::ostream &out, const QImage &image);
|
||||||
|
|
||||||
void PrintTo(const QString &text, std::ostream *os);
|
void PrintTo(const QString &text, std::ostream *os);
|
||||||
void PrintTo(const QVariant &variant, std::ostream *os);
|
void PrintTo(const QVariant &variant, std::ostream *os);
|
||||||
|
326
tests/unit/unittest/imagecache-test.cpp
Normal file
326
tests/unit/unittest/imagecache-test.cpp
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 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 "googletest.h"
|
||||||
|
|
||||||
|
#include "mockimagecachegenerator.h"
|
||||||
|
#include "mockimagecachestorage.h"
|
||||||
|
#include "mocktimestampprovider.h"
|
||||||
|
#include "notification.h"
|
||||||
|
|
||||||
|
#include <imagecache.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class ImageCache : public testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Notification notification;
|
||||||
|
Notification waitInThread;
|
||||||
|
NiceMock<MockImageCacheStorage> mockStorage;
|
||||||
|
NiceMock<MockImageCacheGenerator> mockGenerator;
|
||||||
|
NiceMock<MockTimeStampProvider> mockTimeStampProvider;
|
||||||
|
QmlDesigner::ImageCache cache{mockStorage, mockGenerator, mockTimeStampProvider};
|
||||||
|
NiceMock<MockFunction<void()>> mockAbortCallback;
|
||||||
|
NiceMock<MockFunction<void(const QImage &image)>> mockCaptureCallback;
|
||||||
|
QImage image1{10, 10, QImage::Format_ARGB32};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestImageFetchesImageFromStorage)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _))
|
||||||
|
.WillRepeatedly([&](Utils::SmallStringView, auto) {
|
||||||
|
notification.notify();
|
||||||
|
return QmlDesigner::ImageCacheStorageInterface::Entry{{}, false};
|
||||||
|
});
|
||||||
|
|
||||||
|
cache.requestImage("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestImageFetchesImageFromStorageWithTimeStamp)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
|
.WillRepeatedly(Return(Sqlite::TimeStamp{123}));
|
||||||
|
EXPECT_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123})))
|
||||||
|
.WillRepeatedly([&](Utils::SmallStringView, auto) {
|
||||||
|
notification.notify();
|
||||||
|
return QmlDesigner::ImageCacheStorageInterface::Entry{QImage{}, false};
|
||||||
|
});
|
||||||
|
|
||||||
|
cache.requestImage("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestImageCallsCaptureCallbackWithImageFromStorage)
|
||||||
|
{
|
||||||
|
ON_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _))
|
||||||
|
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{image1, true}));
|
||||||
|
|
||||||
|
EXPECT_CALL(mockCaptureCallback, Call(Eq(image1))).WillRepeatedly([&](const QImage &) {
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
cache.requestImage("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestImageCallsAbortCallbackWithoutImage)
|
||||||
|
{
|
||||||
|
ON_CALL(mockStorage, fetchImage(Eq("/path/to/Component.qml"), _))
|
||||||
|
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{QImage{}, true}));
|
||||||
|
|
||||||
|
EXPECT_CALL(mockAbortCallback, Call()).WillRepeatedly([&] { notification.notify(); });
|
||||||
|
|
||||||
|
cache.requestImage("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestImageRequestImageFromGenerator)
|
||||||
|
{
|
||||||
|
ON_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
|
.WillByDefault(Return(Sqlite::TimeStamp{123}));
|
||||||
|
|
||||||
|
EXPECT_CALL(mockGenerator,
|
||||||
|
generateImage(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123}), _, _))
|
||||||
|
.WillRepeatedly([&](auto &&, auto, auto &&callback, auto) { notification.notify(); });
|
||||||
|
|
||||||
|
cache.requestImage("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestImageCallsCaptureCallbackWithImageFromGenerator)
|
||||||
|
{
|
||||||
|
ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
|
||||||
|
.WillByDefault([&](auto &&, auto, auto &&callback, auto) {
|
||||||
|
callback(QImage{image1});
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(mockCaptureCallback, Call(Eq(image1)));
|
||||||
|
|
||||||
|
cache.requestImage("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestImageCallsAbortCallbackFromGenerator)
|
||||||
|
{
|
||||||
|
ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
|
||||||
|
.WillByDefault([&](auto &&, auto, auto &&, auto &&abortCallback) {
|
||||||
|
abortCallback();
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(mockAbortCallback, Call());
|
||||||
|
|
||||||
|
cache.requestImage("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestIconFetchesIconFromStorage)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml"), _))
|
||||||
|
.WillRepeatedly([&](Utils::SmallStringView, auto) {
|
||||||
|
notification.notify();
|
||||||
|
return QmlDesigner::ImageCacheStorageInterface::Entry{{}, false};
|
||||||
|
});
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestIconFetchesIconFromStorageWithTimeStamp)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
|
.WillRepeatedly(Return(Sqlite::TimeStamp{123}));
|
||||||
|
EXPECT_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123})))
|
||||||
|
.WillRepeatedly([&](Utils::SmallStringView, auto) {
|
||||||
|
notification.notify();
|
||||||
|
return QmlDesigner::ImageCacheStorageInterface::Entry{QImage{}, false};
|
||||||
|
});
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestIconCallsCaptureCallbackWithImageFromStorage)
|
||||||
|
{
|
||||||
|
ON_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml"), _))
|
||||||
|
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{image1, true}));
|
||||||
|
|
||||||
|
EXPECT_CALL(mockCaptureCallback, Call(Eq(image1))).WillRepeatedly([&](const QImage &) {
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestIconCallsAbortCallbackWithoutIcon)
|
||||||
|
{
|
||||||
|
ON_CALL(mockStorage, fetchIcon(Eq("/path/to/Component.qml"), _))
|
||||||
|
.WillByDefault(Return(QmlDesigner::ImageCacheStorageInterface::Entry{QImage{}, true}));
|
||||||
|
|
||||||
|
EXPECT_CALL(mockAbortCallback, Call()).WillRepeatedly([&] { notification.notify(); });
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestIconRequestImageFromGenerator)
|
||||||
|
{
|
||||||
|
ON_CALL(mockTimeStampProvider, timeStamp(Eq("/path/to/Component.qml")))
|
||||||
|
.WillByDefault(Return(Sqlite::TimeStamp{123}));
|
||||||
|
|
||||||
|
EXPECT_CALL(mockGenerator,
|
||||||
|
generateImage(Eq("/path/to/Component.qml"), Eq(Sqlite::TimeStamp{123}), _, _))
|
||||||
|
.WillRepeatedly([&](auto &&, auto, auto &&callback, auto) { notification.notify(); });
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestIconCallsCaptureCallbackWithImageFromGenerator)
|
||||||
|
{
|
||||||
|
ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
|
||||||
|
.WillByDefault([&](auto &&, auto, auto &&callback, auto) {
|
||||||
|
callback(QImage{image1});
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(mockCaptureCallback, Call(Eq(image1)));
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, RequestIconCallsAbortCallbackFromGenerator)
|
||||||
|
{
|
||||||
|
ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
|
||||||
|
.WillByDefault([&](auto &&, auto, auto &&, auto &&abortCallback) {
|
||||||
|
abortCallback();
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(mockAbortCallback, Call());
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, CleanRemovesEntries)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(mockGenerator, generateImage(Eq("/path/to/Component1.qml"), _, _, _))
|
||||||
|
.WillRepeatedly([&](auto &&, auto, auto &&mockCaptureCallback, auto &&) {
|
||||||
|
mockCaptureCallback(QImage{});
|
||||||
|
waitInThread.wait();
|
||||||
|
});
|
||||||
|
EXPECT_CALL(mockGenerator, generateImage(_, _, _, _))
|
||||||
|
.WillRepeatedly([&](auto &&, auto, auto &&mockCaptureCallback, auto &&) {
|
||||||
|
mockCaptureCallback(QImage{});
|
||||||
|
});
|
||||||
|
cache.requestIcon("/path/to/Component1.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
|
||||||
|
EXPECT_CALL(mockCaptureCallback, Call(_)).Times(AtMost(1));
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component3.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
cache.clean();
|
||||||
|
waitInThread.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, CleanCallsAbort)
|
||||||
|
{
|
||||||
|
ON_CALL(mockGenerator, generateImage(Eq("/path/to/Component1.qml"), _, _, _))
|
||||||
|
.WillByDefault(
|
||||||
|
[&](auto &&, auto, auto &&mockCaptureCallback, auto &&) { waitInThread.wait(); });
|
||||||
|
cache.requestIcon("/path/to/Component1.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
cache.requestIcon("/path/to/Component2.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
|
||||||
|
EXPECT_CALL(mockAbortCallback, Call()).Times(AtLeast(2));
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component3.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
cache.clean();
|
||||||
|
waitInThread.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, CleanCallsGeneratorClean)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(mockGenerator, clean()).Times(AtLeast(1));
|
||||||
|
|
||||||
|
cache.clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCache, AfterCleanNewJobsWorks)
|
||||||
|
{
|
||||||
|
cache.clean();
|
||||||
|
|
||||||
|
EXPECT_CALL(mockGenerator, generateImage(Eq("/path/to/Component.qml"), _, _, _))
|
||||||
|
.WillRepeatedly([&](auto &&, auto, auto &&, auto &&) { notification.notify(); });
|
||||||
|
|
||||||
|
cache.requestIcon("/path/to/Component.qml",
|
||||||
|
mockCaptureCallback.AsStdFunction(),
|
||||||
|
mockAbortCallback.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
41
tests/unit/unittest/imagecachecollectormock.h
Normal file
41
tests/unit/unittest/imagecachecollectormock.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "googletest.h"
|
||||||
|
|
||||||
|
#include <imagecachecollectorinterface.h>
|
||||||
|
|
||||||
|
class ImageCacheCollectorMock : public QmlDesigner::ImageCacheCollectorInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
start,
|
||||||
|
(Utils::SmallStringView filePath,
|
||||||
|
ImageCacheCollectorInterface::CaptureCallback captureCallback,
|
||||||
|
ImageCacheCollectorInterface::AbortCallback abortCallback),
|
||||||
|
(override));
|
||||||
|
};
|
240
tests/unit/unittest/imagecachegenerator-test.cpp
Normal file
240
tests/unit/unittest/imagecachegenerator-test.cpp
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 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 "googletest.h"
|
||||||
|
|
||||||
|
#include "imagecachecollectormock.h"
|
||||||
|
#include "mockimagecachestorage.h"
|
||||||
|
#include "notification.h"
|
||||||
|
|
||||||
|
#include <imagecachegenerator.h>
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class ImageCacheGenerator : public testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
template<typename Callable, typename... Arguments>
|
||||||
|
static void executeAsync(Callable &&call, Arguments... arguments)
|
||||||
|
{
|
||||||
|
std::thread thread(
|
||||||
|
[](Callable &&call, Arguments... arguments) {
|
||||||
|
call(std::forward<Arguments>(arguments)...);
|
||||||
|
},
|
||||||
|
std::forward<Callable>(call),
|
||||||
|
std::forward<Arguments>(arguments)...);
|
||||||
|
thread.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Notification waitInThread;
|
||||||
|
Notification notification;
|
||||||
|
QImage image1{10, 10, QImage::Format_ARGB32};
|
||||||
|
NiceMock<MockFunction<void(const QImage &)>> imageCallbackMock;
|
||||||
|
NiceMock<MockFunction<void()>> abortCallbackMock;
|
||||||
|
NiceMock<ImageCacheCollectorMock> collectorMock;
|
||||||
|
NiceMock<MockImageCacheStorage> storageMock;
|
||||||
|
QmlDesigner::ImageCacheGenerator generator{collectorMock, storageMock};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, CallsCollectorWithCaptureCallback)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(collectorMock, start(Eq("name"), _, _))
|
||||||
|
.WillRepeatedly([&](auto, auto captureCallback, auto) { captureCallback(QImage{image1}); });
|
||||||
|
EXPECT_CALL(imageCallbackMock, Call(_)).WillRepeatedly([&](const QImage &) {
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, CallsCollectorOnlyIfNotProcessing)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(collectorMock, start(Eq("name"), _, _)).WillRepeatedly([&](auto, auto, auto) {
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
notification.wait(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, ProcessTaskAfterFirstFinished)
|
||||||
|
{
|
||||||
|
ON_CALL(imageCallbackMock, Call(_)).WillByDefault([&](const QImage &) { notification.notify(); });
|
||||||
|
|
||||||
|
EXPECT_CALL(collectorMock, start(Eq("name"), _, _)).WillOnce([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback(QImage{image1});
|
||||||
|
});
|
||||||
|
EXPECT_CALL(collectorMock, start(Eq("name2"), _, _)).WillOnce([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback(QImage{image1});
|
||||||
|
});
|
||||||
|
|
||||||
|
generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
generator.generateImage("name2", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
notification.wait(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, DontCrashAtDestructingGenerator)
|
||||||
|
{
|
||||||
|
ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback(QImage{image1});
|
||||||
|
});
|
||||||
|
|
||||||
|
generator.generateImage("name", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
generator.generateImage("name2", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
generator.generateImage("name3", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
generator.generateImage("name4", {}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, StoreImage)
|
||||||
|
{
|
||||||
|
ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback(QImage{image1});
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(image1)))
|
||||||
|
.WillRepeatedly([&](auto, auto, auto) { notification.notify(); });
|
||||||
|
|
||||||
|
generator.generateImage("name", {11}, imageCallbackMock.AsStdFunction(), {});
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, StoreNullImage)
|
||||||
|
{
|
||||||
|
ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback(QImage{});
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(QImage{})))
|
||||||
|
.WillRepeatedly([&](auto, auto, auto) { notification.notify(); });
|
||||||
|
|
||||||
|
generator.generateImage("name",
|
||||||
|
{11},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, AbortCallback)
|
||||||
|
{
|
||||||
|
ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback(QImage{image1});
|
||||||
|
});
|
||||||
|
ON_CALL(collectorMock, start(Eq("name2"), _, _)).WillByDefault([&](auto, auto, auto abortCallback) {
|
||||||
|
abortCallback();
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(imageCallbackMock, Call(_)).WillOnce([&](const QImage &) { notification.notify(); });
|
||||||
|
EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); });
|
||||||
|
|
||||||
|
generator.generateImage("name",
|
||||||
|
{},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
generator.generateImage("name2",
|
||||||
|
{},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
notification.wait(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, StoreNullImageForAbortCallback)
|
||||||
|
{
|
||||||
|
ON_CALL(collectorMock, start(_, _, _)).WillByDefault([&](auto, auto, auto abortCallback) {
|
||||||
|
abortCallback();
|
||||||
|
notification.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); });
|
||||||
|
EXPECT_CALL(storageMock, storeImage(Eq("name"), Eq(Sqlite::TimeStamp{11}), Eq(QImage{})));
|
||||||
|
|
||||||
|
generator.generateImage("name",
|
||||||
|
{11},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, AbortForEmptyImage)
|
||||||
|
{
|
||||||
|
NiceMock<MockFunction<void()>> abortCallbackMock;
|
||||||
|
ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback(QImage{});
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(abortCallbackMock, Call()).WillOnce([&]() { notification.notify(); });
|
||||||
|
|
||||||
|
generator.generateImage("name",
|
||||||
|
{},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, CallWalCheckpointFullIfQueueIsEmpty)
|
||||||
|
{
|
||||||
|
ON_CALL(collectorMock, start(Eq("name"), _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback({});
|
||||||
|
});
|
||||||
|
|
||||||
|
EXPECT_CALL(storageMock, walCheckpointFull()).WillRepeatedly([&]() { notification.notify(); });
|
||||||
|
|
||||||
|
generator.generateImage("name",
|
||||||
|
{11},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
generator.generateImage("name2",
|
||||||
|
{11},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
notification.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheGenerator, Clean)
|
||||||
|
{
|
||||||
|
ON_CALL(collectorMock, start(_, _, _)).WillByDefault([&](auto, auto captureCallback, auto) {
|
||||||
|
captureCallback({});
|
||||||
|
waitInThread.wait();
|
||||||
|
});
|
||||||
|
generator.generateImage("name",
|
||||||
|
{11},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
generator.generateImage("name2",
|
||||||
|
{11},
|
||||||
|
imageCallbackMock.AsStdFunction(),
|
||||||
|
abortCallbackMock.AsStdFunction());
|
||||||
|
|
||||||
|
EXPECT_CALL(imageCallbackMock, Call(_)).Times(0);
|
||||||
|
|
||||||
|
generator.clean();
|
||||||
|
waitInThread.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
334
tests/unit/unittest/imagecachestorage-test.cpp
Normal file
334
tests/unit/unittest/imagecachestorage-test.cpp
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2016 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 "googletest.h"
|
||||||
|
|
||||||
|
#include "sqlitedatabasemock.h"
|
||||||
|
|
||||||
|
#include <imagecachestorage.h>
|
||||||
|
#include <sqlitedatabase.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
MATCHER_P2(IsEntry,
|
||||||
|
image,
|
||||||
|
hasEntry,
|
||||||
|
std::string(negation ? "is't" : "is")
|
||||||
|
+ PrintToString(QmlDesigner::ImageCacheStorageInterface::Entry{image, hasEntry}))
|
||||||
|
{
|
||||||
|
const QmlDesigner::ImageCacheStorageInterface::Entry &entry = arg;
|
||||||
|
return entry.image == image && entry.hasEntry == hasEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImageCacheStorageTest : public testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
QImage createImage()
|
||||||
|
{
|
||||||
|
QImage image{150, 150, QImage::Format_ARGB32};
|
||||||
|
image.fill(QColor{128, 64, 0, 11});
|
||||||
|
image.setPixelColor(75, 75, QColor{1, 255, 33, 196});
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
using ReadStatement = QmlDesigner::ImageCacheStorage<SqliteDatabaseMock>::ReadStatement;
|
||||||
|
using WriteStatement = QmlDesigner::ImageCacheStorage<SqliteDatabaseMock>::WriteStatement;
|
||||||
|
|
||||||
|
NiceMock<SqliteDatabaseMock> databaseMock;
|
||||||
|
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
|
||||||
|
ReadStatement &selectImageStatement = storage.selectImageStatement;
|
||||||
|
ReadStatement &selectIconStatement = storage.selectIconStatement;
|
||||||
|
WriteStatement &upsertImageStatement = storage.upsertImageStatement;
|
||||||
|
QImage image1{createImage()};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, Initialize)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, exclusiveBegin());
|
||||||
|
EXPECT_CALL(databaseMock,
|
||||||
|
execute(Eq("CREATE TABLE IF NOT EXISTS images(id INTEGER PRIMARY KEY, name TEXT "
|
||||||
|
"NOT NULL UNIQUE, mtime INTEGER, image BLOB, icon BLOB)")));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
EXPECT_CALL(databaseMock, immediateBegin());
|
||||||
|
EXPECT_CALL(databaseMock, prepare(Eq(selectImageStatement.sqlStatement)));
|
||||||
|
EXPECT_CALL(databaseMock, prepare(Eq(selectIconStatement.sqlStatement)));
|
||||||
|
EXPECT_CALL(databaseMock, prepare(Eq(upsertImageStatement.sqlStatement)));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
|
||||||
|
QmlDesigner::ImageCacheStorage<SqliteDatabaseMock> storage{databaseMock};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, FetchImageCalls)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, deferredBegin());
|
||||||
|
EXPECT_CALL(selectImageStatement,
|
||||||
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123)));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
|
||||||
|
storage.fetchImage("/path/to/component", {123});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, FetchImageCallsIsBusy)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, deferredBegin());
|
||||||
|
EXPECT_CALL(selectImageStatement,
|
||||||
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123)))
|
||||||
|
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
|
EXPECT_CALL(databaseMock, rollback());
|
||||||
|
EXPECT_CALL(databaseMock, deferredBegin());
|
||||||
|
EXPECT_CALL(selectImageStatement,
|
||||||
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123)));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
|
||||||
|
storage.fetchImage("/path/to/component", {123});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, FetchIconCalls)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, deferredBegin());
|
||||||
|
EXPECT_CALL(selectIconStatement,
|
||||||
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123)));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
|
||||||
|
storage.fetchIcon("/path/to/component", {123});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, FetchIconCallsIsBusy)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, deferredBegin());
|
||||||
|
EXPECT_CALL(selectIconStatement,
|
||||||
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123)))
|
||||||
|
.WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
|
EXPECT_CALL(databaseMock, rollback());
|
||||||
|
EXPECT_CALL(databaseMock, deferredBegin());
|
||||||
|
EXPECT_CALL(selectIconStatement,
|
||||||
|
valueReturnBlob(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123)));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
|
||||||
|
storage.fetchIcon("/path/to/component", {123});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, StoreImageCalls)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, immediateBegin());
|
||||||
|
EXPECT_CALL(upsertImageStatement,
|
||||||
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123),
|
||||||
|
A<Sqlite::BlobView>(),
|
||||||
|
A<Sqlite::BlobView>()));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, StoreEmptyImageCalls)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, immediateBegin());
|
||||||
|
EXPECT_CALL(upsertImageStatement,
|
||||||
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123),
|
||||||
|
A<Sqlite::NullValue>(),
|
||||||
|
A<Sqlite::NullValue>()));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
|
||||||
|
storage.storeImage("/path/to/component", {123}, QImage{});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, StoreImageCallsIsBusy)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, immediateBegin()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
|
EXPECT_CALL(databaseMock, immediateBegin());
|
||||||
|
EXPECT_CALL(upsertImageStatement,
|
||||||
|
write(TypedEq<Utils::SmallStringView>("/path/to/component"),
|
||||||
|
TypedEq<long long>(123),
|
||||||
|
A<Sqlite::NullValue>(),
|
||||||
|
A<Sqlite::NullValue>()));
|
||||||
|
EXPECT_CALL(databaseMock, commit());
|
||||||
|
|
||||||
|
storage.storeImage("/path/to/component", {123}, QImage{});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, CallWalCheckointFull)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(databaseMock, walCheckpointFull());
|
||||||
|
|
||||||
|
storage.walCheckpointFull();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageTest, CallWalCheckointFullIsBusy)
|
||||||
|
{
|
||||||
|
InSequence s;
|
||||||
|
|
||||||
|
EXPECT_CALL(databaseMock, walCheckpointFull()).WillOnce(Throw(Sqlite::StatementIsBusy("busy")));
|
||||||
|
EXPECT_CALL(databaseMock, walCheckpointFull());
|
||||||
|
|
||||||
|
storage.walCheckpointFull();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ImageCacheStorageSlowTest : public testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
QImage createImage()
|
||||||
|
{
|
||||||
|
QImage image{150, 150, QImage::Format_ARGB32};
|
||||||
|
image.fill(QColor{128, 64, 0, 11});
|
||||||
|
image.setPixelColor(1, 1, QColor{1, 255, 33, 196});
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||||
|
QmlDesigner::ImageCacheStorage<Sqlite::Database> storage{database};
|
||||||
|
QImage image1{createImage()};
|
||||||
|
QImage image2{10, 10, QImage::Format_ARGB32};
|
||||||
|
QImage icon1{image1.scaled(96, 96)};
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, StoreImage)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
|
||||||
|
ASSERT_THAT(storage.fetchImage("/path/to/component", {123}), IsEntry(image1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, StoreEmptyImageAfterEntry)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
|
||||||
|
storage.storeImage("/path/to/component", {123}, QImage{});
|
||||||
|
|
||||||
|
ASSERT_THAT(storage.fetchImage("/path/to/component", {123}), IsEntry(QImage{}, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, StoreEmptyEntry)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, QImage{});
|
||||||
|
|
||||||
|
ASSERT_THAT(storage.fetchImage("/path/to/component", {123}), IsEntry(QImage{}, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, FetchNonExistingImageIsEmpty)
|
||||||
|
{
|
||||||
|
auto image = storage.fetchImage("/path/to/component", {123});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(QImage{}, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, FetchSameTimeImage)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
|
||||||
|
auto image = storage.fetchImage("/path/to/component", {123});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(image1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, DoNotFetchOlderImage)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
|
||||||
|
auto image = storage.fetchImage("/path/to/component", {124});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(QImage{}, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, FetchNewerImage)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
|
||||||
|
auto image = storage.fetchImage("/path/to/component", {122});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(image1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, FetchNonExistingIconIsEmpty)
|
||||||
|
{
|
||||||
|
auto image = storage.fetchIcon("/path/to/component", {123});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(QImage{}, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, FetchSameTimeIcon)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
|
||||||
|
auto image = storage.fetchIcon("/path/to/component", {123});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(icon1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, DoNotFetchOlderIcon)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
|
||||||
|
auto image = storage.fetchIcon("/path/to/component", {124});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(QImage{}, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, FetchNewerIcon)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image1);
|
||||||
|
|
||||||
|
auto image = storage.fetchIcon("/path/to/component", {122});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(icon1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ImageCacheStorageSlowTest, DontScaleSmallerIcon)
|
||||||
|
{
|
||||||
|
storage.storeImage("/path/to/component", {123}, image2);
|
||||||
|
|
||||||
|
auto image = storage.fetchImage("/path/to/component", {122});
|
||||||
|
|
||||||
|
ASSERT_THAT(image, IsEntry(image2, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
43
tests/unit/unittest/mockimagecachegenerator.h
Normal file
43
tests/unit/unittest/mockimagecachegenerator.h
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "googletest.h"
|
||||||
|
|
||||||
|
#include <imagecachegeneratorinterface.h>
|
||||||
|
|
||||||
|
class MockImageCacheGenerator : public QmlDesigner::ImageCacheGeneratorInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
generateImage,
|
||||||
|
(Utils::SmallStringView name,
|
||||||
|
Sqlite::TimeStamp timeStamp,
|
||||||
|
CaptureCallback &&captureCallback,
|
||||||
|
AbortCallback &&abortCallback),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(void, clean, (), (override));
|
||||||
|
};
|
50
tests/unit/unittest/mockimagecachestorage.h
Normal file
50
tests/unit/unittest/mockimagecachestorage.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "googletest.h"
|
||||||
|
|
||||||
|
#include <imagecachestorageinterface.h>
|
||||||
|
|
||||||
|
class MockImageCacheStorage : public QmlDesigner::ImageCacheStorageInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(QmlDesigner::ImageCacheStorageInterface::Entry,
|
||||||
|
fetchImage,
|
||||||
|
(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp),
|
||||||
|
(const, override));
|
||||||
|
|
||||||
|
MOCK_METHOD(QmlDesigner::ImageCacheStorageInterface::Entry,
|
||||||
|
fetchIcon,
|
||||||
|
(Utils::SmallStringView name, Sqlite::TimeStamp minimumTimeStamp),
|
||||||
|
(const, override));
|
||||||
|
|
||||||
|
MOCK_METHOD(void,
|
||||||
|
storeImage,
|
||||||
|
(Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QImage &image),
|
||||||
|
(override));
|
||||||
|
MOCK_METHOD(void, walCheckpointFull, (), (override));
|
||||||
|
};
|
36
tests/unit/unittest/mocktimestampprovider.h
Normal file
36
tests/unit/unittest/mocktimestampprovider.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "googletest.h"
|
||||||
|
|
||||||
|
#include <timestampproviderinterface.h>
|
||||||
|
|
||||||
|
class MockTimeStampProvider : public QmlDesigner::TimeStampProviderInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOCK_METHOD(Sqlite::TimeStamp, timeStamp, (Utils::SmallStringView name), (const, override));
|
||||||
|
};
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user