forked from qt-creator/qt-creator
QmlDesigner: Implement content library view
Fixes: QDS-8058 Fixes: QDS-8059 Change-Id: I1adfdc7ac15141e010467813ec6e673060269241 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
// Copyright (C) 2022 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "contentlibrarywidget.h"
|
||||
|
||||
#include "contentlibrarymaterial.h"
|
||||
#include "contentlibrarymaterialsmodel.h"
|
||||
#include "contentlibrarytexture.h"
|
||||
#include "contentlibrarytexturesmodel.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <qmldesignerconstants.h>
|
||||
#include <qmldesignerplugin.h>
|
||||
|
||||
#include <theme.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QMimeData>
|
||||
#include <QMouseEvent>
|
||||
#include <QQmlContext>
|
||||
#include <QQuickWidget>
|
||||
#include <QQmlEngine>
|
||||
#include <QQuickItem>
|
||||
#include <QShortcut>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
static QString propertyEditorResourcesPath()
|
||||
{
|
||||
#ifdef SHARE_QML_PATH
|
||||
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
|
||||
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
|
||||
#endif
|
||||
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
|
||||
}
|
||||
|
||||
bool ContentLibraryWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::FocusOut) {
|
||||
if (obj == m_quickWidget.data())
|
||||
QMetaObject::invokeMethod(m_quickWidget->rootObject(), "closeContextMenu");
|
||||
} else if (event->type() == QMouseEvent::MouseMove) {
|
||||
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||
QTC_ASSERT(document, return false);
|
||||
Model *model = document->currentModel();
|
||||
QTC_ASSERT(model, return false);
|
||||
|
||||
if (m_materialToDrag) {
|
||||
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
||||
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) {
|
||||
QByteArray data;
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << m_materialToDrag->type();
|
||||
mimeData->setData(Constants::MIME_TYPE_BUNDLE_MATERIAL, data);
|
||||
mimeData->removeFormat("text/plain");
|
||||
|
||||
if (!m_draggedMaterial) {
|
||||
m_draggedMaterial = m_materialToDrag;
|
||||
emit draggedMaterialChanged();
|
||||
}
|
||||
|
||||
emit bundleMaterialDragStarted(m_materialToDrag);
|
||||
model->startDrag(mimeData, m_materialToDrag->icon().toLocalFile());
|
||||
m_materialToDrag = nullptr;
|
||||
}
|
||||
} else if (m_textureToDrag) {
|
||||
QMouseEvent *me = static_cast<QMouseEvent *>(event);
|
||||
if ((me->globalPos() - m_dragStartPoint).manhattanLength() > 20) {
|
||||
QByteArray data;
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << m_textureToDrag->path();
|
||||
mimeData->setData(Constants::MIME_TYPE_BUNDLE_TEXTURE, data);
|
||||
mimeData->removeFormat("text/plain");
|
||||
|
||||
model->startDrag(mimeData, m_textureToDrag->icon().toLocalFile());
|
||||
m_textureToDrag = nullptr;
|
||||
}
|
||||
}
|
||||
} else if (event->type() == QMouseEvent::MouseButtonRelease) {
|
||||
m_materialToDrag = nullptr;
|
||||
m_textureToDrag = nullptr;
|
||||
|
||||
if (m_draggedMaterial) {
|
||||
m_draggedMaterial = nullptr;
|
||||
emit draggedMaterialChanged();
|
||||
}
|
||||
}
|
||||
|
||||
return QObject::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
ContentLibraryWidget::ContentLibraryWidget()
|
||||
: m_quickWidget(new QQuickWidget(this))
|
||||
, m_materialsModel(new ContentLibraryMaterialsModel(this))
|
||||
, m_texturesModel(new ContentLibraryTexturesModel(this))
|
||||
, m_environmentsModel(new ContentLibraryTexturesModel(this))
|
||||
{
|
||||
setWindowTitle(tr("Content Library", "Title of content library widget"));
|
||||
setMinimumWidth(120);
|
||||
|
||||
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||
m_quickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
|
||||
m_quickWidget->setClearColor(Theme::getColor(Theme::Color::DSpanelBackground));
|
||||
|
||||
QString textureBundlePath = findTextureBundlePath();
|
||||
m_texturesModel->loadTextureBundle(textureBundlePath + "/Textures");
|
||||
m_environmentsModel->loadTextureBundle(textureBundlePath + "/Environments");
|
||||
|
||||
m_quickWidget->rootContext()->setContextProperties({
|
||||
{"rootView", QVariant::fromValue(this)},
|
||||
{"materialsModel", QVariant::fromValue(m_materialsModel.data())},
|
||||
{"texturesModel", QVariant::fromValue(m_texturesModel.data())},
|
||||
{"environmentsModel", QVariant::fromValue(m_environmentsModel.data())},
|
||||
});
|
||||
|
||||
Theme::setupTheme(m_quickWidget->engine());
|
||||
m_quickWidget->installEventFilter(this);
|
||||
|
||||
auto layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins({});
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_quickWidget.data());
|
||||
|
||||
updateSearch();
|
||||
|
||||
setStyleSheet(Theme::replaceCssColors(
|
||||
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
|
||||
|
||||
m_qmlSourceUpdateShortcut = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_F11), this);
|
||||
connect(m_qmlSourceUpdateShortcut, &QShortcut::activated, this, &ContentLibraryWidget::reloadQmlSource);
|
||||
|
||||
// QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_MATERIALBROWSER_TIME); // TODO
|
||||
|
||||
reloadQmlSource();
|
||||
}
|
||||
|
||||
QList<QToolButton *> ContentLibraryWidget::createToolBarWidgets()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::handleSearchFilterChanged(const QString &filterText)
|
||||
{
|
||||
if (filterText != m_filterText) {
|
||||
m_filterText = filterText;
|
||||
updateSearch();
|
||||
}
|
||||
}
|
||||
|
||||
QString ContentLibraryWidget::qmlSourcesPath()
|
||||
{
|
||||
#ifdef SHARE_QML_PATH
|
||||
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
|
||||
return QLatin1String(SHARE_QML_PATH) + "/contentLibraryQmlSource";
|
||||
#endif
|
||||
return Core::ICore::resourcePath("qmldesigner/contentLibraryQmlSource").toString();
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::clearSearchFilter()
|
||||
{
|
||||
QMetaObject::invokeMethod(m_quickWidget->rootObject(), "clearSearchFilter");
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::reloadQmlSource()
|
||||
{
|
||||
const QString materialBrowserQmlPath = qmlSourcesPath() + "/ContentLibrary.qml";
|
||||
|
||||
QTC_ASSERT(QFileInfo::exists(materialBrowserQmlPath), return);
|
||||
|
||||
m_quickWidget->engine()->clearComponentCache();
|
||||
m_quickWidget->setSource(QUrl::fromLocalFile(materialBrowserQmlPath));
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::updateSearch()
|
||||
{
|
||||
m_materialsModel->setSearchText(m_filterText);
|
||||
m_texturesModel->setSearchText(m_filterText);
|
||||
m_environmentsModel->setSearchText(m_filterText);
|
||||
m_quickWidget->update();
|
||||
}
|
||||
|
||||
QString ContentLibraryWidget::findTextureBundlePath()
|
||||
{
|
||||
QDir texBundleDir(qEnvironmentVariable("TEXTURE_BUNDLE_PATH"));
|
||||
|
||||
// search for matBundleDir from exec dir and up
|
||||
if (texBundleDir.dirName() == ".") {
|
||||
texBundleDir.setPath(QCoreApplication::applicationDirPath());
|
||||
while (!texBundleDir.cd("texture_bundle") && texBundleDir.cdUp())
|
||||
; // do nothing
|
||||
|
||||
if (texBundleDir.dirName() != "texture_bundle") // bundlePathDir not found
|
||||
return {};
|
||||
}
|
||||
|
||||
return texBundleDir.path();
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::startDragMaterial(QmlDesigner::ContentLibraryMaterial *mat,
|
||||
const QPointF &mousePos)
|
||||
{
|
||||
m_materialToDrag = mat;
|
||||
m_dragStartPoint = mousePos.toPoint();
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::startDragTexture(QmlDesigner::ContentLibraryTexture *tex,
|
||||
const QPointF &mousePos)
|
||||
{
|
||||
m_textureToDrag = tex;
|
||||
m_dragStartPoint = mousePos.toPoint();
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::addImage(ContentLibraryTexture *tex)
|
||||
{
|
||||
emit addTextureRequested(tex->path(), AddTextureMode::Image);
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::addTexture(ContentLibraryTexture *tex)
|
||||
{
|
||||
emit addTextureRequested(tex->path(), AddTextureMode::Texture);
|
||||
}
|
||||
|
||||
void ContentLibraryWidget::addEnv(ContentLibraryTexture *tex)
|
||||
{
|
||||
emit addTextureRequested(tex->path(), AddTextureMode::Environment);
|
||||
}
|
||||
|
||||
QPointer<ContentLibraryMaterialsModel> ContentLibraryWidget::materialsModel() const
|
||||
{
|
||||
return m_materialsModel;
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
Reference in New Issue
Block a user