forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.11'
Change-Id: I6389fd3583ca0638fa6b94c03d2442a584b604bc
This commit is contained in:
16
dist/changes-4.10.1.md
vendored
16
dist/changes-4.10.1.md
vendored
@@ -19,9 +19,13 @@ you can check out from the public Git repository. For example:
|
|||||||
|
|
||||||
* Fixed that text moved around when resizing and zooming (QTCREATORBUG-4756)
|
* Fixed that text moved around when resizing and zooming (QTCREATORBUG-4756)
|
||||||
|
|
||||||
|
## All Projects
|
||||||
|
|
||||||
|
* Fixed `Qt Creator Plugin` wizard (QTCREATORBUG-22945)
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
* Fixed more layout restoration issues (QTCREATORBUG-22286, QTCREATORBUG-22938)
|
* Fixed more layout restoration issues (QTCREATORBUG-22286, QTCREATORBUG-22415, QTCREATORBUG-22938)
|
||||||
|
|
||||||
### LLDB
|
### LLDB
|
||||||
|
|
||||||
@@ -36,7 +40,13 @@ you can check out from the public Git repository. For example:
|
|||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
|
|
||||||
|
* Fixed debugging with Xcode 11 (QTCREATORBUG-22955)
|
||||||
* Fixed window stacking order after closing file dialog (QTCREATORBUG-22906)
|
* Fixed window stacking order after closing file dialog (QTCREATORBUG-22906)
|
||||||
|
* Fixed window size after exiting fullscreen
|
||||||
|
|
||||||
|
### QNX
|
||||||
|
|
||||||
|
* Fixed that QNX compiler could not be selected for C
|
||||||
|
|
||||||
## Credits for these changes go to:
|
## Credits for these changes go to:
|
||||||
|
|
||||||
@@ -44,7 +54,9 @@ Aleksei German
|
|||||||
Alexander Akulich
|
Alexander Akulich
|
||||||
Andre Hartmann
|
Andre Hartmann
|
||||||
André Pönitz
|
André Pönitz
|
||||||
|
Christian Kandeler
|
||||||
Christian Stenger
|
Christian Stenger
|
||||||
|
Cristian Adam
|
||||||
David Schulz
|
David Schulz
|
||||||
Eike Ziller
|
Eike Ziller
|
||||||
Knud Dollereder
|
Knud Dollereder
|
||||||
@@ -53,5 +65,5 @@ Lisandro Damián Nicanor Pérez Meyer
|
|||||||
Nikolai Kosjar
|
Nikolai Kosjar
|
||||||
Orgad Shaneh
|
Orgad Shaneh
|
||||||
Richard Weickelt
|
Richard Weickelt
|
||||||
|
Sergey Belyashov
|
||||||
Thomas Hartmann
|
Thomas Hartmann
|
||||||
|
|
||||||
|
@@ -136,8 +136,6 @@ class PlainDumper:
|
|||||||
printer = self.printer.gen_printer(value.nativeValue)
|
printer = self.printer.gen_printer(value.nativeValue)
|
||||||
except:
|
except:
|
||||||
printer = self.printer.invoke(value.nativeValue)
|
printer = self.printer.invoke(value.nativeValue)
|
||||||
lister = getattr(printer, 'children', None)
|
|
||||||
children = [] if lister is None else list(lister())
|
|
||||||
d.putType(value.nativeValue.type.name)
|
d.putType(value.nativeValue.type.name)
|
||||||
val = printer.to_string()
|
val = printer.to_string()
|
||||||
if isinstance(val, str):
|
if isinstance(val, str):
|
||||||
@@ -149,11 +147,20 @@ class PlainDumper:
|
|||||||
d.putCharArrayValue(val.address, val.length,
|
d.putCharArrayValue(val.address, val.length,
|
||||||
val.type.target().sizeof)
|
val.type.target().sizeof)
|
||||||
|
|
||||||
d.putNumChild(len(children))
|
lister = getattr(printer, 'children', None)
|
||||||
if d.isExpanded():
|
if lister is None:
|
||||||
with Children(d):
|
d.putNumChild(0)
|
||||||
for child in children:
|
else:
|
||||||
d.putSubItem(child[0], d.fromNativeValue(gdb.Value(child[1])))
|
if d.isExpanded():
|
||||||
|
children = lister()
|
||||||
|
with Children(d):
|
||||||
|
i = 0
|
||||||
|
for (name, child) in children:
|
||||||
|
d.putSubItem(name, d.fromNativeValue(child))
|
||||||
|
i += 1
|
||||||
|
if i > 1000:
|
||||||
|
break
|
||||||
|
d.putNumChild(1)
|
||||||
|
|
||||||
def importPlainDumpers(args):
|
def importPlainDumpers(args):
|
||||||
if args == 'off':
|
if args == 'off':
|
||||||
|
@@ -44,8 +44,8 @@ QString FakeMetaEnum::name() const
|
|||||||
void FakeMetaEnum::setName(const QString &name)
|
void FakeMetaEnum::setName(const QString &name)
|
||||||
{ m_name = name; }
|
{ m_name = name; }
|
||||||
|
|
||||||
void FakeMetaEnum::addKey(const QString &key, int value)
|
void FakeMetaEnum::addKey(const QString &key)
|
||||||
{ m_keys.append(key); m_values.append(value); }
|
{ m_keys.append(key); }
|
||||||
|
|
||||||
QString FakeMetaEnum::key(int index) const
|
QString FakeMetaEnum::key(int index) const
|
||||||
{ return m_keys.at(index); }
|
{ return m_keys.at(index); }
|
||||||
@@ -71,10 +71,6 @@ void FakeMetaEnum::addToHash(QCryptographicHash &hash) const
|
|||||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
||||||
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
|
hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
|
||||||
}
|
}
|
||||||
len = m_values.size();
|
|
||||||
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
||||||
foreach (int value, m_values)
|
|
||||||
hash.addData(reinterpret_cast<const char *>(&value), sizeof(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FakeMetaEnum::describe(int baseIndent) const
|
QString FakeMetaEnum::describe(int baseIndent) const
|
||||||
@@ -82,16 +78,14 @@ QString FakeMetaEnum::describe(int baseIndent) const
|
|||||||
QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
|
QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
|
||||||
QString res = QLatin1String("Enum ");
|
QString res = QLatin1String("Enum ");
|
||||||
res += name();
|
res += name();
|
||||||
res += QLatin1String(":{");
|
res += QLatin1String(": [");
|
||||||
for (int i = 0; i < keyCount(); ++i) {
|
for (int i = 0; i < keyCount(); ++i) {
|
||||||
res += newLine;
|
res += newLine;
|
||||||
res += QLatin1String(" ");
|
res += QLatin1String(" ");
|
||||||
res += key(i);
|
res += key(i);
|
||||||
res += QLatin1String(": ");
|
|
||||||
res += QString::number(m_values.value(i, -1));
|
|
||||||
}
|
}
|
||||||
res += newLine;
|
res += newLine;
|
||||||
res += QLatin1Char('}');
|
res += QLatin1Char(']');
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,7 +43,6 @@ namespace LanguageUtils {
|
|||||||
class LANGUAGEUTILS_EXPORT FakeMetaEnum {
|
class LANGUAGEUTILS_EXPORT FakeMetaEnum {
|
||||||
QString m_name;
|
QString m_name;
|
||||||
QStringList m_keys;
|
QStringList m_keys;
|
||||||
QList<int> m_values;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FakeMetaEnum();
|
FakeMetaEnum();
|
||||||
@@ -54,7 +53,7 @@ public:
|
|||||||
QString name() const;
|
QString name() const;
|
||||||
void setName(const QString &name);
|
void setName(const QString &name);
|
||||||
|
|
||||||
void addKey(const QString &key, int value);
|
void addKey(const QString &key);
|
||||||
QString key(int index) const;
|
QString key(int index) const;
|
||||||
int keyCount() const;
|
int keyCount() const;
|
||||||
QStringList keys() const;
|
QStringList keys() const;
|
||||||
|
@@ -737,7 +737,7 @@ static LanguageUtils::FakeMetaObject::Ptr buildFakeMetaObject(
|
|||||||
Symbol *enumMember = e->memberAt(j);
|
Symbol *enumMember = e->memberAt(j);
|
||||||
if (!enumMember->name())
|
if (!enumMember->name())
|
||||||
continue;
|
continue;
|
||||||
metaEnum.addKey(namePrinter.prettyName(enumMember->name()), 0);
|
metaEnum.addKey(namePrinter.prettyName(enumMember->name()));
|
||||||
}
|
}
|
||||||
fmo->addEnum(metaEnum);
|
fmo->addEnum(metaEnum);
|
||||||
}
|
}
|
||||||
|
@@ -649,39 +649,34 @@ void TypeDescriptionReader::readEnumValues(AST::UiScriptBinding *ast, LanguageUt
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionStatement *expStmt = AST::cast<ExpressionStatement *>(ast->statement);
|
auto *expStmt = AST::cast<ExpressionStatement *>(ast->statement);
|
||||||
if (!expStmt) {
|
if (!expStmt) {
|
||||||
addError(ast->statement->firstSourceLocation(), tr("Expected object literal after colon."));
|
addError(ast->statement->firstSourceLocation(), tr("Expected expression after colon."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectPattern *objectLit = AST::cast<ObjectPattern *>(expStmt->expression);
|
if (auto *objectLit = AST::cast<ObjectPattern *>(expStmt->expression)) {
|
||||||
if (!objectLit) {
|
for (PatternPropertyList *it = objectLit->properties; it; it = it->next) {
|
||||||
addError(expStmt->firstSourceLocation(), tr("Expected object literal after colon."));
|
if (PatternProperty *assignement = it->property) {
|
||||||
return;
|
if (auto *name = AST::cast<StringLiteralPropertyName *>(assignement->name)) {
|
||||||
}
|
fme->addKey(name->id.toString());
|
||||||
|
continue;
|
||||||
for (PatternPropertyList *it = objectLit->properties; it; it = it->next) {
|
}
|
||||||
PatternProperty *assignement = AST::cast<PatternProperty *>(it->property);
|
|
||||||
if (assignement) {
|
|
||||||
StringLiteralPropertyName *propName = AST::cast<StringLiteralPropertyName *>(assignement->name);
|
|
||||||
NumericLiteral *value = AST::cast<NumericLiteral *>(assignement->initializer);
|
|
||||||
UnaryMinusExpression *minus = AST::cast<UnaryMinusExpression *>(assignement->initializer);
|
|
||||||
if (minus)
|
|
||||||
value = AST::cast<NumericLiteral *>(minus->expression);
|
|
||||||
if (!propName || !value) {
|
|
||||||
addError(objectLit->firstSourceLocation(), tr("Expected object literal to contain only 'string: number' elements."));
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
addError(it->firstSourceLocation(), tr("Expected strings as enum keys."));
|
||||||
double v = value->value;
|
|
||||||
if (minus)
|
|
||||||
v = -v;
|
|
||||||
fme->addKey(propName->id.toString(), v);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
PatternPropertyList *getterSetter = AST::cast<PatternPropertyList *>(it->next);
|
} else if (auto *arrayLit = AST::cast<ArrayPattern *>(expStmt->expression)) {
|
||||||
if (getterSetter)
|
for (PatternElementList *it = arrayLit->elements; it; it = it->next) {
|
||||||
addError(objectLit->firstSourceLocation(), tr("Enum should not contain getter and setters, but only 'string: number' elements."));
|
if (PatternElement *element = it->element) {
|
||||||
|
if (auto *name = AST::cast<StringLiteral *>(element->initializer)) {
|
||||||
|
fme->addKey(name->value.toString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addError(it->firstSourceLocation(), tr("Expected strings as enum keys."));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addError(ast->statement->firstSourceLocation(),
|
||||||
|
tr("Expected either array or object literal as enum definition."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -381,27 +381,41 @@ QList<ToolChain *> SdccToolChainFactory::autoDetect(const QList<ToolChain *> &al
|
|||||||
|
|
||||||
if (Utils::HostOsInfo::isWindowsHost()) {
|
if (Utils::HostOsInfo::isWindowsHost()) {
|
||||||
|
|
||||||
#ifdef Q_OS_WIN64
|
// Tries to detect the candidate from the 32-bit
|
||||||
static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\SDCC";
|
// or 64-bit system registry format.
|
||||||
#else
|
auto probeCandidate = [](QSettings::Format format) {
|
||||||
static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\SDCC";
|
QSettings registry("HKEY_LOCAL_MACHINE\\SOFTWARE\\SDCC",
|
||||||
#endif
|
format);
|
||||||
|
QString compilerPath = registry.value("Default").toString();
|
||||||
QSettings registry(kRegistryNode, QSettings::NativeFormat);
|
if (compilerPath.isEmpty())
|
||||||
QString compilerPath = registry.value("Default").toString();
|
return Candidate{};
|
||||||
if (!compilerPath.isEmpty()) {
|
|
||||||
// Build full compiler path.
|
// Build full compiler path.
|
||||||
compilerPath += "\\bin\\sdcc.exe";
|
compilerPath += "\\bin\\sdcc.exe";
|
||||||
const FilePath fn = FilePath::fromString(
|
const FilePath fn = FilePath::fromString(
|
||||||
QFileInfo(compilerPath).absoluteFilePath());
|
QFileInfo(compilerPath).absoluteFilePath());
|
||||||
if (compilerExists(fn)) {
|
if (!compilerExists(fn))
|
||||||
// Build compiler version.
|
return Candidate{};
|
||||||
const QString version = QString("%1.%2.%3").arg(
|
// Build compiler version.
|
||||||
registry.value("VersionMajor").toString(),
|
const QString version = QString("%1.%2.%3").arg(
|
||||||
registry.value("VersionMinor").toString(),
|
registry.value("VersionMajor").toString(),
|
||||||
registry.value("VersionRevision").toString());
|
registry.value("VersionMinor").toString(),
|
||||||
candidates.push_back({fn, version});
|
registry.value("VersionRevision").toString());
|
||||||
}
|
return Candidate{fn, version};
|
||||||
|
};
|
||||||
|
|
||||||
|
const QSettings::Format allowedFormats[] = {
|
||||||
|
QSettings::NativeFormat,
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QSettings::Registry32Format,
|
||||||
|
QSettings::Registry64Format
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const QSettings::Format format : allowedFormats) {
|
||||||
|
const auto candidate = probeCandidate(format);
|
||||||
|
if (candidate.compilerPath.isEmpty() || candidates.contains(candidate))
|
||||||
|
continue;
|
||||||
|
candidates.push_back(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,8 +33,9 @@
|
|||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
|
|
||||||
#include <remotelinux/genericdirectuploadstep.h>
|
#include <remotelinux/genericdirectuploadstep.h>
|
||||||
|
#include <remotelinux/makeinstallstep.h>
|
||||||
|
#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
|
||||||
#include <remotelinux/remotelinuxdeployconfiguration.h>
|
#include <remotelinux/remotelinuxdeployconfiguration.h>
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
@@ -51,6 +52,11 @@ QdbDeployConfigurationFactory::QdbDeployConfigurationFactory()
|
|||||||
"Deploy to Boot2Qt target"));
|
"Deploy to Boot2Qt target"));
|
||||||
setUseDeploymentDataView();
|
setUseDeploymentDataView();
|
||||||
|
|
||||||
|
addInitialStep(RemoteLinux::MakeInstallStep::stepId(), [](Target *target) {
|
||||||
|
const Project * const prj = target->project();
|
||||||
|
return prj->deploymentKnowledge() == DeploymentKnowledge::Bad
|
||||||
|
&& prj->hasMakeInstallEquivalent();
|
||||||
|
});
|
||||||
addInitialStep(RemoteLinuxCheckForFreeDiskSpaceStep::stepId());
|
addInitialStep(RemoteLinuxCheckForFreeDiskSpaceStep::stepId());
|
||||||
addInitialStep(QdbStopApplicationStep::stepId());
|
addInitialStep(QdbStopApplicationStep::stepId());
|
||||||
addInitialStep(GenericDirectUploadStep::stepId());
|
addInitialStep(GenericDirectUploadStep::stepId());
|
||||||
|
@@ -46,6 +46,7 @@
|
|||||||
|
|
||||||
#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
|
#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
|
||||||
#include <remotelinux/genericdirectuploadstep.h>
|
#include <remotelinux/genericdirectuploadstep.h>
|
||||||
|
#include <remotelinux/makeinstallstep.h>
|
||||||
|
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
@@ -175,8 +176,8 @@ public:
|
|||||||
|
|
||||||
QdbDeployStepFactory<RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep>
|
QdbDeployStepFactory<RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep>
|
||||||
m_checkForFreeDiskSpaceStepFactory;
|
m_checkForFreeDiskSpaceStepFactory;
|
||||||
QdbDeployStepFactory<RemoteLinux::GenericDirectUploadStep>
|
QdbDeployStepFactory<RemoteLinux::GenericDirectUploadStep> m_directUploadStepFactory;
|
||||||
m_directUploadStepFactory;
|
QdbDeployStepFactory<RemoteLinux::MakeInstallStep> m_makeInstallStepFactory;
|
||||||
|
|
||||||
const QList<Core::Id> supportedRunConfigs {
|
const QList<Core::Id> supportedRunConfigs {
|
||||||
m_runConfigFactory.id(),
|
m_runConfigFactory.id(),
|
||||||
|
@@ -2285,8 +2285,8 @@ void DebuggerEngine::openDisassemblerView(const Location &location)
|
|||||||
|
|
||||||
void DebuggerEngine::raiseWatchersWindow()
|
void DebuggerEngine::raiseWatchersWindow()
|
||||||
{
|
{
|
||||||
if (d->m_watchersView) {
|
if (d->m_watchersView && d->m_watchersWindow) {
|
||||||
if (auto dock = qobject_cast<QDockWidget *>(d->m_watchersView->parentWidget())) {
|
if (auto dock = qobject_cast<QDockWidget *>(d->m_watchersWindow->parentWidget())) {
|
||||||
if (QAction *act = dock->toggleViewAction()) {
|
if (QAction *act = dock->toggleViewAction()) {
|
||||||
if (!act->isChecked())
|
if (!act->isChecked())
|
||||||
QTimer::singleShot(1, act, [act] { act->trigger(); });
|
QTimer::singleShot(1, act, [act] { act->trigger(); });
|
||||||
|
@@ -45,11 +45,13 @@
|
|||||||
#include <texteditor/texteditoractionhandler.h>
|
#include <texteditor/texteditoractionhandler.h>
|
||||||
#include <texteditor/texteditorconstants.h>
|
#include <texteditor/texteditorconstants.h>
|
||||||
|
|
||||||
|
#include <utils/executeondestruction.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
@@ -58,6 +60,7 @@ namespace Python {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
static constexpr char startPylsInfoBarId[] = "PythonEditor::StartPyls";
|
static constexpr char startPylsInfoBarId[] = "PythonEditor::StartPyls";
|
||||||
|
static constexpr char installPylsInfoBarId[] = "PythonEditor::InstallPyls";
|
||||||
|
|
||||||
struct PythonForProject
|
struct PythonForProject
|
||||||
{
|
{
|
||||||
@@ -193,6 +196,90 @@ static LanguageClient::Client *registerLanguageServer(const PythonForProject &py
|
|||||||
return LanguageClient::LanguageClientManager::clientForSetting(settings).value(0);
|
return LanguageClient::LanguageClientManager::clientForSetting(settings).value(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PythonLSInstallHelper : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
PythonLSInstallHelper(const PythonForProject &python, QPointer<TextEditor::TextDocument> document)
|
||||||
|
: m_python(python)
|
||||||
|
, m_document(document)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
auto killTimer = new QTimer(&m_process);
|
||||||
|
|
||||||
|
connect(&m_process,
|
||||||
|
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
||||||
|
this,
|
||||||
|
&PythonLSInstallHelper::installFinished);
|
||||||
|
connect(&m_process,
|
||||||
|
&QProcess::readyReadStandardError,
|
||||||
|
this,
|
||||||
|
&PythonLSInstallHelper::errorAvailable);
|
||||||
|
connect(&m_process,
|
||||||
|
&QProcess::readyReadStandardOutput,
|
||||||
|
this,
|
||||||
|
&PythonLSInstallHelper::outputAvailable);
|
||||||
|
connect(killTimer, &QTimer::timeout, [this]() {
|
||||||
|
SynchronousProcess::stopProcess(m_process);
|
||||||
|
Core::MessageManager::write(tr("The Python language server installation timed out."));
|
||||||
|
});
|
||||||
|
|
||||||
|
// on windows the pyls 0.28.3 crashes with pylint so just install the pyflakes linter
|
||||||
|
const QString &pylsVersion = HostOsInfo::isWindowsHost()
|
||||||
|
? QString{"python-language-server[pyflakes]"}
|
||||||
|
: QString{"python-language-server[all]"};
|
||||||
|
|
||||||
|
m_process.start(m_python.path.toString(),
|
||||||
|
{"-m", "pip", "install", pylsVersion});
|
||||||
|
|
||||||
|
Core::MessageManager::write(tr("Running '%1 %2' to install python language server")
|
||||||
|
.arg(m_process.program(), m_process.arguments().join(' ')));
|
||||||
|
|
||||||
|
killTimer->start(5 /*minutes*/ * 60 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void installFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
|
{
|
||||||
|
if (exitStatus == QProcess::NormalExit && exitCode == 0) {
|
||||||
|
if (LanguageClient::Client *client = registerLanguageServer(m_python))
|
||||||
|
LanguageClient::LanguageClientManager::reOpenDocumentWithClient(m_document, client);
|
||||||
|
} else {
|
||||||
|
Core::MessageManager::write(
|
||||||
|
tr("Installing the Python language server failed with exit code %1").arg(exitCode));
|
||||||
|
}
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
void outputAvailable()
|
||||||
|
{
|
||||||
|
const QString &stdOut = QString::fromLocal8Bit(m_process.readAllStandardOutput().trimmed());
|
||||||
|
if (!stdOut.isEmpty())
|
||||||
|
Core::MessageManager::write(stdOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
void errorAvailable()
|
||||||
|
{
|
||||||
|
const QString &stdErr = QString::fromLocal8Bit(m_process.readAllStandardError().trimmed());
|
||||||
|
if (!stdErr.isEmpty())
|
||||||
|
Core::MessageManager::write(stdErr);
|
||||||
|
}
|
||||||
|
|
||||||
|
QProcess m_process;
|
||||||
|
const PythonForProject m_python;
|
||||||
|
QPointer<TextEditor::TextDocument> m_document;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void installPythonLanguageServer(const PythonForProject &python,
|
||||||
|
QPointer<TextEditor::TextDocument> document)
|
||||||
|
{
|
||||||
|
document->infoBar()->removeInfo(installPylsInfoBarId);
|
||||||
|
|
||||||
|
auto install = new PythonLSInstallHelper(python, document);
|
||||||
|
install->run();
|
||||||
|
}
|
||||||
|
|
||||||
static void setupPythonLanguageServer(const PythonForProject &python,
|
static void setupPythonLanguageServer(const PythonForProject &python,
|
||||||
QPointer<TextEditor::TextDocument> document)
|
QPointer<TextEditor::TextDocument> document)
|
||||||
{
|
{
|
||||||
@@ -206,13 +293,25 @@ static void updateEditorInfoBar(const PythonForProject &python, TextEditor::Text
|
|||||||
const PythonLanguageServerState &lsState = checkPythonLanguageServer(python.path, document);
|
const PythonLanguageServerState &lsState = checkPythonLanguageServer(python.path, document);
|
||||||
|
|
||||||
if (lsState.state == PythonLanguageServerState::CanNotBeInstalled
|
if (lsState.state == PythonLanguageServerState::CanNotBeInstalled
|
||||||
|| lsState.state == PythonLanguageServerState::AlreadyConfigured
|
|| lsState.state == PythonLanguageServerState::AlreadyConfigured) {
|
||||||
|| lsState.state == PythonLanguageServerState::CanBeInstalled /* TODO */) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::InfoBar *infoBar = document->infoBar();
|
Core::InfoBar *infoBar = document->infoBar();
|
||||||
if (lsState.state == PythonLanguageServerState::AlreadyInstalled
|
if (lsState.state == PythonLanguageServerState::CanBeInstalled
|
||||||
|
&& infoBar->canInfoBeAdded(installPylsInfoBarId)) {
|
||||||
|
auto message
|
||||||
|
= PythonEditorFactory::tr(
|
||||||
|
"Install and set up Python language server for %1 (%2). "
|
||||||
|
"The language server provides Python specific completions and annotations.")
|
||||||
|
.arg(python.name(), python.path.toUserOutput());
|
||||||
|
Core::InfoBarEntry info(installPylsInfoBarId,
|
||||||
|
message,
|
||||||
|
Core::InfoBarEntry::GlobalSuppression::Enabled);
|
||||||
|
info.setCustomButtonInfo(TextEditor::BaseTextEditor::tr("Install"),
|
||||||
|
[=]() { installPythonLanguageServer(python, document); });
|
||||||
|
infoBar->addInfo(info);
|
||||||
|
} else if (lsState.state == PythonLanguageServerState::AlreadyInstalled
|
||||||
&& infoBar->canInfoBeAdded(startPylsInfoBarId)) {
|
&& infoBar->canInfoBeAdded(startPylsInfoBarId)) {
|
||||||
auto message = PythonEditorFactory::tr("Found a Python language server for %1 (%2). "
|
auto message = PythonEditorFactory::tr("Found a Python language server for %1 (%2). "
|
||||||
"Should this one be set up for this document?")
|
"Should this one be set up for this document?")
|
||||||
@@ -264,3 +363,5 @@ PythonEditorFactory::PythonEditorFactory()
|
|||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Python
|
} // namespace Python
|
||||||
|
|
||||||
|
#include "pythoneditor.moc"
|
||||||
|
@@ -267,6 +267,17 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
itemlibrarysectionmodel.cpp itemlibrarysectionmodel.h
|
itemlibrarysectionmodel.cpp itemlibrarysectionmodel.h
|
||||||
itemlibraryview.cpp itemlibraryview.h
|
itemlibraryview.cpp itemlibraryview.h
|
||||||
itemlibrarywidget.cpp itemlibrarywidget.h
|
itemlibrarywidget.cpp itemlibrarywidget.h
|
||||||
|
itemlibraryassetimportdialog.cpp itemlibraryassetimportdialog.h
|
||||||
|
itemlibraryassetimportdialog.ui
|
||||||
|
itemlibraryassetimporter.cpp itemlibraryassetimporter.h
|
||||||
|
)
|
||||||
|
|
||||||
|
find_package(Qt5 COMPONENTS Quick3DAssetImport QUIET)
|
||||||
|
extend_qtc_plugin(QmlDesigner
|
||||||
|
CONDITION TARGET Qt5::Quick3DAssetImport
|
||||||
|
FEATURE_INFO "Qt Quick 3D asset import"
|
||||||
|
DEPENDS Qt5::Quick3DAssetImportPrivate
|
||||||
|
DEFINES IMPORT_QUICK3D_ASSETS
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 492 B |
Binary file not shown.
After Width: | Height: | Size: 942 B |
@@ -1,5 +1,10 @@
|
|||||||
VPATH += $$PWD
|
VPATH += $$PWD
|
||||||
|
|
||||||
|
qtHaveModule(quick3dassetimport) {
|
||||||
|
QT *= quick3dassetimport-private
|
||||||
|
DEFINES *= IMPORT_QUICK3D_ASSETS
|
||||||
|
}
|
||||||
|
|
||||||
# Input
|
# Input
|
||||||
HEADERS += itemlibraryview.h \
|
HEADERS += itemlibraryview.h \
|
||||||
itemlibrarywidget.h \
|
itemlibrarywidget.h \
|
||||||
@@ -9,6 +14,8 @@ HEADERS += itemlibraryview.h \
|
|||||||
itemlibrarysectionmodel.h \
|
itemlibrarysectionmodel.h \
|
||||||
itemlibraryitem.h \
|
itemlibraryitem.h \
|
||||||
itemlibrarysection.h \
|
itemlibrarysection.h \
|
||||||
|
itemlibraryassetimportdialog.h \
|
||||||
|
itemlibraryassetimporter.h \
|
||||||
customfilesystemmodel.h
|
customfilesystemmodel.h
|
||||||
|
|
||||||
SOURCES += itemlibraryview.cpp \
|
SOURCES += itemlibraryview.cpp \
|
||||||
@@ -19,6 +26,9 @@ SOURCES += itemlibraryview.cpp \
|
|||||||
itemlibrarysectionmodel.cpp \
|
itemlibrarysectionmodel.cpp \
|
||||||
itemlibraryitem.cpp \
|
itemlibraryitem.cpp \
|
||||||
itemlibrarysection.cpp \
|
itemlibrarysection.cpp \
|
||||||
|
itemlibraryassetimportdialog.cpp \
|
||||||
|
itemlibraryassetimporter.cpp \
|
||||||
customfilesystemmodel.cpp
|
customfilesystemmodel.cpp
|
||||||
|
|
||||||
RESOURCES += itemlibrary.qrc
|
RESOURCES += itemlibrary.qrc
|
||||||
|
|
||||||
|
FORMS += itemlibraryassetimportdialog.ui
|
||||||
|
@@ -3,5 +3,7 @@
|
|||||||
<file>images/item-default-icon.png</file>
|
<file>images/item-default-icon.png</file>
|
||||||
<file>images/item-invalid-icon.png</file>
|
<file>images/item-invalid-icon.png</file>
|
||||||
<file>images/item-default-icon@2x.png</file>
|
<file>images/item-default-icon@2x.png</file>
|
||||||
|
<file>images/item-3D_model-icon.png</file>
|
||||||
|
<file>images/item-3D_model-icon@2x.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -0,0 +1,229 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "itemlibraryassetimportdialog.h"
|
||||||
|
#include "ui_itemlibraryassetimportdialog.h"
|
||||||
|
|
||||||
|
#include "qmldesignerplugin.h"
|
||||||
|
#include "qmldesignerconstants.h"
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
|
#include "utils/outputformatter.h"
|
||||||
|
|
||||||
|
#include <QtCore/qfileinfo.h>
|
||||||
|
#include <QtCore/qdir.h>
|
||||||
|
#include <QtCore/qloggingcategory.h>
|
||||||
|
#include <QtCore/qtimer.h>
|
||||||
|
#include <QtWidgets/qpushbutton.h>
|
||||||
|
#include <QtWidgets/qformlayout.h>
|
||||||
|
#include <QtWidgets/qlabel.h>
|
||||||
|
#include <QtWidgets/qscrollbar.h>
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static void addFormattedMessage(Utils::OutputFormatter *formatter, const QString &str,
|
||||||
|
const QString &srcPath, Utils::OutputFormat format) {
|
||||||
|
if (!formatter)
|
||||||
|
return;
|
||||||
|
QString msg = str;
|
||||||
|
if (!srcPath.isEmpty())
|
||||||
|
msg += QStringLiteral(": \"%1\"").arg(srcPath);
|
||||||
|
msg += QLatin1Char('\n');
|
||||||
|
formatter->appendMessage(msg, format);
|
||||||
|
formatter->plainTextEdit()->verticalScrollBar()->setValue(
|
||||||
|
formatter->plainTextEdit()->verticalScrollBar()->maximum());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &importFiles,
|
||||||
|
const QString &defaulTargetDirectory, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::ItemLibraryAssetImportDialog),
|
||||||
|
m_importer(this)
|
||||||
|
{
|
||||||
|
setModal(true);
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
m_outputFormatter = new Utils::OutputFormatter;
|
||||||
|
m_outputFormatter->setPlainTextEdit(ui->plainTextEdit);
|
||||||
|
|
||||||
|
// Skip unsupported assets
|
||||||
|
bool skipSome = false;
|
||||||
|
for (const auto &file : importFiles) {
|
||||||
|
if (m_importer.isQuick3DAsset(file))
|
||||||
|
m_quick3DFiles << file;
|
||||||
|
else
|
||||||
|
skipSome = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipSome)
|
||||||
|
addWarning("Cannot import 3D and other assets simultaneously. Skipping non-3D assets.");
|
||||||
|
|
||||||
|
// Import button will be used in near future when we add import options. Hide for now.
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Ok)->hide();
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Import"));
|
||||||
|
connect(ui->buttonBox->button(QDialogButtonBox::Ok), &QPushButton::clicked,
|
||||||
|
this, &ItemLibraryAssetImportDialog::onImport);
|
||||||
|
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
|
||||||
|
|
||||||
|
// Import is always done under known folder. The order of preference for folder is:
|
||||||
|
// 1) An existing QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path
|
||||||
|
// 2) An existing QUICK_3D_ASSETS_FOLDER under any project import path
|
||||||
|
// 3) New QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path
|
||||||
|
// 4) New QUICK_3D_ASSETS_FOLDER under any project import path
|
||||||
|
// 5) New QUICK_3D_ASSETS_FOLDER under new DEFAULT_ASSET_IMPORT_FOLDER under project
|
||||||
|
const QString defaultAssetFolder = QLatin1String(Constants::DEFAULT_ASSET_IMPORT_FOLDER);
|
||||||
|
const QString quick3DFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
|
||||||
|
QString candidatePath = defaulTargetDirectory + defaultAssetFolder + quick3DFolder;
|
||||||
|
int candidatePriority = 5;
|
||||||
|
QStringList importPaths;
|
||||||
|
|
||||||
|
auto doc = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||||
|
if (doc) {
|
||||||
|
Model *model = doc->currentModel();
|
||||||
|
if (model)
|
||||||
|
importPaths = model->importPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto importPath : qAsConst(importPaths)) {
|
||||||
|
if (importPath.startsWith(defaulTargetDirectory)) {
|
||||||
|
const bool isDefaultFolder = importPath.endsWith(defaultAssetFolder);
|
||||||
|
const QString assetFolder = importPath + quick3DFolder;
|
||||||
|
const bool exists = QFileInfo(assetFolder).exists();
|
||||||
|
if (exists) {
|
||||||
|
if (isDefaultFolder) {
|
||||||
|
// Priority one location, stop looking
|
||||||
|
candidatePath = assetFolder;
|
||||||
|
break;
|
||||||
|
} else if (candidatePriority > 2) {
|
||||||
|
candidatePriority = 2;
|
||||||
|
candidatePath = assetFolder;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (candidatePriority > 3 && isDefaultFolder) {
|
||||||
|
candidatePriority = 3;
|
||||||
|
candidatePath = assetFolder;
|
||||||
|
} else if (candidatePriority > 4) {
|
||||||
|
candidatePriority = 4;
|
||||||
|
candidatePath = assetFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_quick3DImportPath = candidatePath;
|
||||||
|
|
||||||
|
// Queue import immediately until we have some options
|
||||||
|
QTimer::singleShot(0, this, &ItemLibraryAssetImportDialog::onImport);
|
||||||
|
|
||||||
|
connect(ui->buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked,
|
||||||
|
this, &ItemLibraryAssetImportDialog::onClose);
|
||||||
|
|
||||||
|
connect(&m_importer, &ItemLibraryAssetImporter::errorReported,
|
||||||
|
this, &ItemLibraryAssetImportDialog::addError);
|
||||||
|
connect(&m_importer, &ItemLibraryAssetImporter::warningReported,
|
||||||
|
this, &ItemLibraryAssetImportDialog::addWarning);
|
||||||
|
connect(&m_importer, &ItemLibraryAssetImporter::infoReported,
|
||||||
|
this, &ItemLibraryAssetImportDialog::addInfo);
|
||||||
|
connect(&m_importer, &ItemLibraryAssetImporter::importFinished,
|
||||||
|
this, &ItemLibraryAssetImportDialog::onImportFinished);
|
||||||
|
connect(&m_importer, &ItemLibraryAssetImporter::progressChanged,
|
||||||
|
this, &ItemLibraryAssetImportDialog::setImportProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemLibraryAssetImportDialog::~ItemLibraryAssetImportDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImportDialog::setImportUiState(bool importing)
|
||||||
|
{
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!importing);
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Close)->setText(importing ? tr("Cancel") : tr("Close"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImportDialog::addError(const QString &error, const QString &srcPath)
|
||||||
|
{
|
||||||
|
addFormattedMessage(m_outputFormatter, error, srcPath, Utils::StdErrFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImportDialog::addWarning(const QString &warning, const QString &srcPath)
|
||||||
|
{
|
||||||
|
addFormattedMessage(m_outputFormatter, warning, srcPath, Utils::StdOutFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImportDialog::addInfo(const QString &info, const QString &srcPath)
|
||||||
|
{
|
||||||
|
addFormattedMessage(m_outputFormatter, info, srcPath, Utils::NormalMessageFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImportDialog::onImport()
|
||||||
|
{
|
||||||
|
setImportUiState(true);
|
||||||
|
ui->progressBar->setValue(0);
|
||||||
|
ui->plainTextEdit->clear();
|
||||||
|
|
||||||
|
if (!m_quick3DFiles.isEmpty())
|
||||||
|
m_importer.importQuick3D(m_quick3DFiles, m_quick3DImportPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImportDialog::setImportProgress(int value, const QString &text)
|
||||||
|
{
|
||||||
|
ui->progressLabel->setText(text);
|
||||||
|
if (value < 0)
|
||||||
|
ui->progressBar->setRange(0, 0);
|
||||||
|
else
|
||||||
|
ui->progressBar->setRange(0, 100);
|
||||||
|
ui->progressBar->setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImportDialog::onImportFinished()
|
||||||
|
{
|
||||||
|
setImportUiState(false);
|
||||||
|
if (m_importer.isCancelled()) {
|
||||||
|
QString interruptStr = tr("Import interrupted.");
|
||||||
|
addError(interruptStr);
|
||||||
|
setImportProgress(0, interruptStr);
|
||||||
|
} else {
|
||||||
|
QString doneStr = tr("Import done.");
|
||||||
|
addInfo(doneStr);
|
||||||
|
setImportProgress(100, doneStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImportDialog::onClose()
|
||||||
|
{
|
||||||
|
if (m_importer.isImporting()) {
|
||||||
|
addInfo(tr("Canceling import."));
|
||||||
|
m_importer.cancelImport();
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
}
|
@@ -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 "itemlibraryassetimporter.h"
|
||||||
|
|
||||||
|
#include <QtWidgets/qdialog.h>
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
class OutputFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
class ItemLibraryAssetImporter;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class ItemLibraryAssetImportDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemLibraryAssetImportDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ItemLibraryAssetImportDialog(const QStringList &importFiles,
|
||||||
|
const QString &defaulTargetDirectory, QWidget *parent = nullptr);
|
||||||
|
~ItemLibraryAssetImportDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void addError(const QString &error, const QString &srcPath = {});
|
||||||
|
void addWarning(const QString &warning, const QString &srcPath = {});
|
||||||
|
void addInfo(const QString &info, const QString &srcPath = {});
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setImportUiState(bool importing);
|
||||||
|
|
||||||
|
void onImport();
|
||||||
|
void setImportProgress(int value, const QString &text);
|
||||||
|
void onImportFinished();
|
||||||
|
void onClose();
|
||||||
|
|
||||||
|
Ui::ItemLibraryAssetImportDialog *ui = nullptr;
|
||||||
|
Utils::OutputFormatter *m_outputFormatter = nullptr;
|
||||||
|
|
||||||
|
QStringList m_quick3DFiles;
|
||||||
|
QString m_quick3DImportPath;
|
||||||
|
ItemLibraryAssetImporter m_importer;
|
||||||
|
};
|
||||||
|
}
|
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>QmlDesigner::ItemLibraryAssetImportDialog</class>
|
||||||
|
<widget class="QDialog" name="QmlDesigner::ItemLibraryAssetImportDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>480</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Asset Import</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPlainTextEdit" name="plainTextEdit">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="progressLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progressBar">
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@@ -0,0 +1,322 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 "itemlibraryassetimporter.h"
|
||||||
|
#include "qmldesignerplugin.h"
|
||||||
|
#include "qmldesignerconstants.h"
|
||||||
|
|
||||||
|
#include "rewriterview.h"
|
||||||
|
#include "model.h"
|
||||||
|
|
||||||
|
#include <QtCore/qdir.h>
|
||||||
|
#include <QtCore/qsavefile.h>
|
||||||
|
#include <QtCore/qloggingcategory.h>
|
||||||
|
#include <QtWidgets/qapplication.h>
|
||||||
|
#include <QtWidgets/qmessagebox.h>
|
||||||
|
|
||||||
|
#ifdef IMPORT_QUICK3D_ASSETS
|
||||||
|
#include <QtQuick3DAssetImport/private/qssgassetimportmanager_p.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
Q_LOGGING_CATEGORY(importerLog, "qtc.itemlibrary.assetImporter", QtWarningMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
ItemLibraryAssetImporter::ItemLibraryAssetImporter(QObject *parent) :
|
||||||
|
QObject (parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemLibraryAssetImporter::~ItemLibraryAssetImporter() {
|
||||||
|
cancelImport();
|
||||||
|
};
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::importQuick3D(const QStringList &inputFiles,
|
||||||
|
const QString &importPath)
|
||||||
|
{
|
||||||
|
if (m_isImporting)
|
||||||
|
cancelImport();
|
||||||
|
reset();
|
||||||
|
m_isImporting = true;
|
||||||
|
|
||||||
|
#ifdef IMPORT_QUICK3D_ASSETS
|
||||||
|
if (!QDir().mkpath(importPath)) {
|
||||||
|
addError(tr("Cannot create import directory."), importPath);
|
||||||
|
notifyFinished();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_importPath = importPath;
|
||||||
|
|
||||||
|
parseFiles(inputFiles);
|
||||||
|
|
||||||
|
if (!isCancelled()) {
|
||||||
|
auto doc = QmlDesignerPlugin::instance()->currentDesignDocument();
|
||||||
|
Model *model = doc ? doc->currentModel() : nullptr;
|
||||||
|
if (model && !m_quick3DAddedImports.isEmpty()) {
|
||||||
|
const QString progressTitle = tr("Updating data model.");
|
||||||
|
addInfo(progressTitle);
|
||||||
|
notifyProgress(0, progressTitle);
|
||||||
|
|
||||||
|
// Trigger underlying qmljs snapshot update by making a non-change to the doc
|
||||||
|
model->rewriterView()->textModifier()->replace(0, 0, {});
|
||||||
|
|
||||||
|
// There is a inbuilt delay before rewriter change actually updates the data model,
|
||||||
|
// so we need to wait for a moment to allow the change to take effect.
|
||||||
|
// Otherwise subsequent subcomponent manager update won't detect new imports properly.
|
||||||
|
QTimer *timer = new QTimer(parent());
|
||||||
|
static int counter;
|
||||||
|
counter = 0;
|
||||||
|
timer->callOnTimeout([this, timer, progressTitle, doc]() {
|
||||||
|
if (!isCancelled()) {
|
||||||
|
notifyProgress(++counter * 10, progressTitle);
|
||||||
|
if (counter >= 10) {
|
||||||
|
doc->updateSubcomponentManager();
|
||||||
|
timer->stop();
|
||||||
|
notifyFinished();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timer->stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
timer->start(100);
|
||||||
|
} else {
|
||||||
|
notifyFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Q_UNUSED(inputFiles)
|
||||||
|
Q_UNUSED(importPath)
|
||||||
|
addError(tr("Importing 3D assets requires building against Qt Quick 3D module."));
|
||||||
|
notifyFinished();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemLibraryAssetImporter::isImporting() const
|
||||||
|
{
|
||||||
|
return m_isImporting;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::cancelImport()
|
||||||
|
{
|
||||||
|
m_cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::addError(const QString &errMsg, const QString &srcPath) const
|
||||||
|
{
|
||||||
|
qCDebug(importerLog) << "Error: "<< errMsg << srcPath;
|
||||||
|
emit errorReported(errMsg, srcPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::addWarning(const QString &warningMsg, const QString &srcPath) const
|
||||||
|
{
|
||||||
|
qCDebug(importerLog) << "Warning: " << warningMsg << srcPath;
|
||||||
|
emit warningReported(warningMsg, srcPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::addInfo(const QString &infoMsg, const QString &srcPath) const
|
||||||
|
{
|
||||||
|
qCDebug(importerLog) << "Info: " << infoMsg << srcPath;
|
||||||
|
emit infoReported(infoMsg, srcPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemLibraryAssetImporter::isQuick3DAsset(const QString &fileName) const
|
||||||
|
{
|
||||||
|
static QStringList quick3DExt;
|
||||||
|
if (quick3DExt.isEmpty()) {
|
||||||
|
quick3DExt << QString(Constants::FbxExtension)
|
||||||
|
<< QString(Constants::ColladaExtension)
|
||||||
|
<< QString(Constants::ObjExtension)
|
||||||
|
<< QString(Constants::BlenderExtension)
|
||||||
|
<< QString(Constants::GltfExtension);
|
||||||
|
}
|
||||||
|
return quick3DExt.contains(QFileInfo(fileName).suffix());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::notifyFinished()
|
||||||
|
{
|
||||||
|
m_isImporting = false;
|
||||||
|
emit importFinished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::reset()
|
||||||
|
{
|
||||||
|
m_isImporting = false;
|
||||||
|
m_cancelled = false;
|
||||||
|
|
||||||
|
#ifdef IMPORT_QUICK3D_ASSETS
|
||||||
|
m_quick3DAddedImports.clear();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::parseFiles(const QStringList &filePaths)
|
||||||
|
{
|
||||||
|
if (isCancelled())
|
||||||
|
return;
|
||||||
|
const QString progressTitle = tr("Parsing files.");
|
||||||
|
addInfo(progressTitle);
|
||||||
|
notifyProgress(0, progressTitle);
|
||||||
|
uint count = 0;
|
||||||
|
double quota = 100.0 / filePaths.count();
|
||||||
|
std::function<void(double)> progress = [this, quota, &count, &progressTitle](double value) {
|
||||||
|
notifyProgress(qRound(quota * (count + value)), progressTitle);
|
||||||
|
};
|
||||||
|
for (const QString &file : filePaths) {
|
||||||
|
if (isCancelled())
|
||||||
|
return;
|
||||||
|
if (isQuick3DAsset(file))
|
||||||
|
parseQuick3DAsset(file);
|
||||||
|
notifyProgress(qRound(++count * quota), progressTitle);
|
||||||
|
}
|
||||||
|
notifyProgress(100, progressTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file)
|
||||||
|
{
|
||||||
|
#ifdef IMPORT_QUICK3D_ASSETS
|
||||||
|
addInfo(tr("Parsing 3D Model"), file);
|
||||||
|
if (!m_quick3DAssetImporter)
|
||||||
|
m_quick3DAssetImporter.reset(new QSSGAssetImportManager);
|
||||||
|
|
||||||
|
QString errorString;
|
||||||
|
|
||||||
|
QDir rootDir(m_importPath);
|
||||||
|
QFileInfo sourceInfo(file);
|
||||||
|
QString assetName = sourceInfo.completeBaseName();
|
||||||
|
|
||||||
|
if (!assetName.isEmpty()) {
|
||||||
|
// Fix name so it plays nice with imports
|
||||||
|
for (QChar ¤tChar : assetName) {
|
||||||
|
if (!currentChar.isLetter() && !currentChar.isDigit())
|
||||||
|
currentChar = QLatin1Char('_');
|
||||||
|
}
|
||||||
|
QCharRef firstChar = assetName[0];
|
||||||
|
if (firstChar.isDigit())
|
||||||
|
firstChar = QLatin1Char('_');
|
||||||
|
if (firstChar.isLower())
|
||||||
|
firstChar = firstChar.toUpper();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir outDir = rootDir;
|
||||||
|
if (outDir.exists(assetName)) {
|
||||||
|
if (confirmAssetOverwrite(assetName)) {
|
||||||
|
if (outDir.cd(assetName)) {
|
||||||
|
outDir.removeRecursively();
|
||||||
|
outDir.cdUp();
|
||||||
|
outDir.mkpath(assetName);
|
||||||
|
} // If cd fails here, it will fail below, too, so no error handling here
|
||||||
|
} else {
|
||||||
|
addWarning(tr("Skipped import of existing asset: \"%1\"").arg(assetName));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outDir.mkpath(assetName);
|
||||||
|
}
|
||||||
|
if (!outDir.cd(assetName)) {
|
||||||
|
addError(tr("Could not access asset directory: \"%1\"").arg(outDir.filePath(assetName)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addInfo(tr("Generating 3D assets into: \"%1\"").arg(outDir.absolutePath()));
|
||||||
|
|
||||||
|
if (m_quick3DAssetImporter->importFile(
|
||||||
|
sourceInfo.absoluteFilePath(), outDir,
|
||||||
|
&errorString) != QSSGAssetImportManager::ImportState::Success) {
|
||||||
|
addError(tr("Failed to import 3D asset with error: %1").arg(errorString),
|
||||||
|
sourceInfo.absoluteFilePath());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate qmldir file
|
||||||
|
outDir.setNameFilters({QStringLiteral("*.qml")});
|
||||||
|
const QFileInfoList qmlFiles = outDir.entryInfoList(QDir::Files);
|
||||||
|
|
||||||
|
if (!qmlFiles.isEmpty()) {
|
||||||
|
QString qmldirFileName = outDir.absoluteFilePath(QStringLiteral("qmldir"));
|
||||||
|
QSaveFile qmldirFile(qmldirFileName);
|
||||||
|
QString version = QStringLiteral("1.0");
|
||||||
|
if (qmldirFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
|
for (const auto &fi : qmlFiles) {
|
||||||
|
QString qmlInfo;
|
||||||
|
qmlInfo.append(fi.baseName());
|
||||||
|
qmlInfo.append(QLatin1Char(' '));
|
||||||
|
qmlInfo.append(version);
|
||||||
|
qmlInfo.append(QLatin1Char(' '));
|
||||||
|
qmlInfo.append(fi.fileName());
|
||||||
|
qmldirFile.write(qmlInfo.toUtf8());
|
||||||
|
}
|
||||||
|
QString assetFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
|
||||||
|
assetFolder = assetFolder.mid(assetFolder.lastIndexOf(QLatin1Char('/')) + 1);
|
||||||
|
m_quick3DAddedImports.insert(
|
||||||
|
qmldirFileName,
|
||||||
|
Import::createLibraryImport(
|
||||||
|
QStringLiteral("%1.%2").arg(assetFolder).arg(assetName), version));
|
||||||
|
qmldirFile.commit();
|
||||||
|
} else {
|
||||||
|
addError(tr("Failed to create qmldir file for asset: \"%1\"").arg(assetName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the original asset into a subdirectory
|
||||||
|
QString origAssetDirName = QStringLiteral("source model");
|
||||||
|
QDir origAssetDir = outDir;
|
||||||
|
|
||||||
|
origAssetDir.mkpath(origAssetDirName);
|
||||||
|
origAssetDir.cd(origAssetDirName);
|
||||||
|
QFile::copy(sourceInfo.absoluteFilePath(), origAssetDir.filePath(sourceInfo.fileName()));
|
||||||
|
#else
|
||||||
|
Q_UNUSED(file)
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::notifyProgress(int value, const QString &text) const
|
||||||
|
{
|
||||||
|
emit progressChanged(value, text);
|
||||||
|
keepUiAlive();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemLibraryAssetImporter::keepUiAlive() const
|
||||||
|
{
|
||||||
|
QApplication::processEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemLibraryAssetImporter::confirmAssetOverwrite(const QString &assetName)
|
||||||
|
{
|
||||||
|
const QString title = tr("Overwrite Existing Asset?");
|
||||||
|
const QString question = tr("Asset already exists. Overwrite?\n\"%1\"").arg(assetName);
|
||||||
|
return QMessageBox::question(qobject_cast<QWidget *>(parent()),
|
||||||
|
title, question,
|
||||||
|
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ItemLibraryAssetImporter::isCancelled() const
|
||||||
|
{
|
||||||
|
keepUiAlive();
|
||||||
|
return m_cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // QmlDesigner
|
@@ -0,0 +1,84 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** 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 <QtCore/qobject.h>
|
||||||
|
#include <QtCore/qstringlist.h>
|
||||||
|
#include <QtCore/qhash.h>
|
||||||
|
|
||||||
|
#include "import.h"
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QSSGAssetImportManager;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace QmlDesigner {
|
||||||
|
|
||||||
|
class ItemLibraryAssetImporter : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ItemLibraryAssetImporter(QObject *parent = nullptr);
|
||||||
|
~ItemLibraryAssetImporter();
|
||||||
|
|
||||||
|
void importQuick3D(const QStringList &inputFiles, const QString &importPath);
|
||||||
|
|
||||||
|
bool isImporting() const;
|
||||||
|
void cancelImport();
|
||||||
|
bool isCancelled() const;
|
||||||
|
|
||||||
|
void addError(const QString &errMsg, const QString &srcPath = {}) const;
|
||||||
|
void addWarning(const QString &warningMsg, const QString &srcPath = {}) const;
|
||||||
|
void addInfo(const QString &infoMsg, const QString &srcPath = {}) const;
|
||||||
|
|
||||||
|
bool isQuick3DAsset(const QString &fileName) const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void errorReported(const QString &, const QString &) const;
|
||||||
|
void warningReported(const QString &, const QString &) const;
|
||||||
|
void infoReported(const QString &, const QString &) const;
|
||||||
|
void progressChanged(int value, const QString &text) const;
|
||||||
|
void importFinished();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void notifyFinished();
|
||||||
|
void reset();
|
||||||
|
void parseFiles(const QStringList &filePaths);
|
||||||
|
void parseQuick3DAsset(const QString &file);
|
||||||
|
|
||||||
|
void notifyProgress(int value, const QString &text) const;
|
||||||
|
void keepUiAlive() const;
|
||||||
|
bool confirmAssetOverwrite(const QString &assetName);
|
||||||
|
|
||||||
|
#ifdef IMPORT_QUICK3D_ASSETS
|
||||||
|
QScopedPointer<QSSGAssetImportManager> m_quick3DAssetImporter;
|
||||||
|
QHash<QString, Import> m_quick3DAddedImports;
|
||||||
|
#endif
|
||||||
|
bool m_isImporting = false;
|
||||||
|
bool m_cancelled = false;
|
||||||
|
QString m_importPath;
|
||||||
|
};
|
||||||
|
} // QmlDesigner
|
@@ -26,6 +26,7 @@
|
|||||||
#include "itemlibrarywidget.h"
|
#include "itemlibrarywidget.h"
|
||||||
|
|
||||||
#include "customfilesystemmodel.h"
|
#include "customfilesystemmodel.h"
|
||||||
|
#include "itemlibraryassetimportdialog.h"
|
||||||
|
|
||||||
#include <theme.h>
|
#include <theme.h>
|
||||||
|
|
||||||
@@ -36,6 +37,8 @@
|
|||||||
#include <model.h>
|
#include <model.h>
|
||||||
#include <rewritingexception.h>
|
#include <rewritingexception.h>
|
||||||
#include <qmldesignerplugin.h>
|
#include <qmldesignerplugin.h>
|
||||||
|
#include <qmldesignerconstants.h>
|
||||||
|
#include <designeractionmanager.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/flowlayout.h>
|
#include <utils/flowlayout.h>
|
||||||
@@ -183,6 +186,43 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
|
|||||||
flowLayout->addWidget(button);
|
flowLayout->addWidget(button);
|
||||||
connect(button, &QToolButton::clicked, this, &ItemLibraryWidget::addResources);
|
connect(button, &QToolButton::clicked, this, &ItemLibraryWidget::addResources);
|
||||||
|
|
||||||
|
#ifdef IMPORT_QUICK3D_ASSETS
|
||||||
|
DesignerActionManager *actionManager =
|
||||||
|
&QmlDesignerPlugin::instance()->viewManager().designerActionManager();
|
||||||
|
|
||||||
|
auto handle3DModel = [](const QStringList &fileNames, const QString &defaultDir) -> bool {
|
||||||
|
auto importDlg = new ItemLibraryAssetImportDialog(fileNames, defaultDir);
|
||||||
|
importDlg->show();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const QString category = tr("3D Models");
|
||||||
|
|
||||||
|
auto add3DHandler = [&actionManager, &handle3DModel, &category](const char *ext) {
|
||||||
|
const QString filter = QStringLiteral("*.%1").arg(QString::fromLatin1(ext));
|
||||||
|
actionManager->registerAddResourceHandler(
|
||||||
|
AddResourceHandler(category, filter, handle3DModel, 10));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Skip if 3D model handlers have already been added
|
||||||
|
const QList<AddResourceHandler> handlers = actionManager->addResourceHandler();
|
||||||
|
bool categoryAlreadyAdded = false;
|
||||||
|
for (const auto &handler : handlers) {
|
||||||
|
if (handler.category == category) {
|
||||||
|
categoryAlreadyAdded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!categoryAlreadyAdded) {
|
||||||
|
add3DHandler(Constants::FbxExtension);
|
||||||
|
add3DHandler(Constants::ColladaExtension);
|
||||||
|
add3DHandler(Constants::ObjExtension);
|
||||||
|
add3DHandler(Constants::BlenderExtension);
|
||||||
|
add3DHandler(Constants::GltfExtension);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// init the first load of the QML UI elements
|
// init the first load of the QML UI elements
|
||||||
reloadQmlSource();
|
reloadQmlSource();
|
||||||
}
|
}
|
||||||
@@ -192,13 +232,19 @@ void ItemLibraryWidget::setItemLibraryInfo(ItemLibraryInfo *itemLibraryInfo)
|
|||||||
if (m_itemLibraryInfo.data() == itemLibraryInfo)
|
if (m_itemLibraryInfo.data() == itemLibraryInfo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_itemLibraryInfo)
|
if (m_itemLibraryInfo) {
|
||||||
disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
|
disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
|
||||||
this, &ItemLibraryWidget::delayedUpdateModel);
|
this, &ItemLibraryWidget::delayedUpdateModel);
|
||||||
|
disconnect(m_itemLibraryInfo.data(), &ItemLibraryInfo::importTagsChanged,
|
||||||
|
this, &ItemLibraryWidget::delayedUpdateModel);
|
||||||
|
}
|
||||||
m_itemLibraryInfo = itemLibraryInfo;
|
m_itemLibraryInfo = itemLibraryInfo;
|
||||||
if (itemLibraryInfo)
|
if (itemLibraryInfo) {
|
||||||
connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
|
connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::entriesChanged,
|
||||||
this, &ItemLibraryWidget::delayedUpdateModel);
|
this, &ItemLibraryWidget::delayedUpdateModel);
|
||||||
|
connect(m_itemLibraryInfo.data(), &ItemLibraryInfo::importTagsChanged,
|
||||||
|
this, &ItemLibraryWidget::delayedUpdateModel);
|
||||||
|
}
|
||||||
delayedUpdateModel();
|
delayedUpdateModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +429,22 @@ void ItemLibraryWidget::addPossibleImport(const QString &name)
|
|||||||
QTC_ASSERT(m_model, return);
|
QTC_ASSERT(m_model, return);
|
||||||
const Import import = m_model->highestPossibleImport(name);
|
const Import import = m_model->highestPossibleImport(name);
|
||||||
try {
|
try {
|
||||||
m_model->changeImports({Import::createLibraryImport(name, import.version())}, {});
|
QList<Import> addedImports = {Import::createLibraryImport(name, import.version())};
|
||||||
|
// Special case for adding an import for 3D asset - also add QtQuick3D import
|
||||||
|
const QString asset3DPrefix = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER + 1)
|
||||||
|
+ QLatin1Char('.');
|
||||||
|
if (name.startsWith(asset3DPrefix)) {
|
||||||
|
const QString q3Dlib = QLatin1String(Constants::QT_QUICK_3D_MODULE_NAME);
|
||||||
|
Import q3DImport = m_model->highestPossibleImport(q3Dlib);
|
||||||
|
if (q3DImport.url() == q3Dlib)
|
||||||
|
addedImports.prepend(Import::createLibraryImport(q3Dlib, q3DImport.version()));
|
||||||
|
}
|
||||||
|
RewriterTransaction transaction
|
||||||
|
= m_model->rewriterView()->beginRewriterTransaction(
|
||||||
|
QByteArrayLiteral("ItemLibraryWidget::addPossibleImport"));
|
||||||
|
|
||||||
|
m_model->changeImports(addedImports, {});
|
||||||
|
transaction.commit();
|
||||||
}
|
}
|
||||||
catch (const RewritingException &e) {
|
catch (const RewritingException &e) {
|
||||||
e.showException();
|
e.showException();
|
||||||
|
@@ -114,6 +114,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void entriesChanged();
|
void entriesChanged();
|
||||||
|
void importTagsChanged();
|
||||||
|
|
||||||
private: // functions
|
private: // functions
|
||||||
ItemLibraryInfo(QObject *parent = nullptr);
|
ItemLibraryInfo(QObject *parent = nullptr);
|
||||||
|
@@ -65,6 +65,8 @@ private: // functions
|
|||||||
void registerQmlFile(const QFileInfo &fileInfo, const QString &qualifier, bool addToLibrary);
|
void registerQmlFile(const QFileInfo &fileInfo, const QString &qualifier, bool addToLibrary);
|
||||||
Model *model() const;
|
Model *model() const;
|
||||||
QStringList importPaths() const;
|
QStringList importPaths() const;
|
||||||
|
void parseQuick3DAssetDir(const QString &assetPath);
|
||||||
|
QStringList quick3DAssetPaths() const;
|
||||||
|
|
||||||
private: // variables
|
private: // variables
|
||||||
QFileSystemWatcher m_watcher;
|
QFileSystemWatcher m_watcher;
|
||||||
|
@@ -356,7 +356,10 @@ void ItemLibraryInfo::addBlacklistImports(const QStringList &list)
|
|||||||
|
|
||||||
void ItemLibraryInfo::addShowTagsForImports(const QStringList &list)
|
void ItemLibraryInfo::addShowTagsForImports(const QStringList &list)
|
||||||
{
|
{
|
||||||
m_showTagsForImports.append(list);
|
if (!list.isEmpty()) {
|
||||||
|
m_showTagsForImports.append(list);
|
||||||
|
emit importTagsChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemLibraryInfo::setBaseInfo(ItemLibraryInfo *baseInfo)
|
void ItemLibraryInfo::setBaseInfo(ItemLibraryInfo *baseInfo)
|
||||||
|
@@ -85,8 +85,7 @@ void SubComponentManager::addImport(int pos, const Import &import)
|
|||||||
url.replace(QLatin1Char('.'), QLatin1Char('/'));
|
url.replace(QLatin1Char('.'), QLatin1Char('/'));
|
||||||
|
|
||||||
foreach (const QString &path, importPaths()) {
|
foreach (const QString &path, importPaths()) {
|
||||||
url = path + QLatin1Char('/') + url;
|
QFileInfo dirInfo = QFileInfo(path + QLatin1Char('/') + url);
|
||||||
QFileInfo dirInfo = QFileInfo(url);
|
|
||||||
if (dirInfo.exists() && dirInfo.isDir()) {
|
if (dirInfo.exists() && dirInfo.isDir()) {
|
||||||
const QString canonicalDirPath = dirInfo.canonicalFilePath();
|
const QString canonicalDirPath = dirInfo.canonicalFilePath();
|
||||||
m_watcher.addPath(canonicalDirPath);
|
m_watcher.addPath(canonicalDirPath);
|
||||||
@@ -126,14 +125,19 @@ void SubComponentManager::parseDirectories()
|
|||||||
if (!m_filePath.isEmpty()) {
|
if (!m_filePath.isEmpty()) {
|
||||||
const QString file = m_filePath.toLocalFile();
|
const QString file = m_filePath.toLocalFile();
|
||||||
QFileInfo dirInfo = QFileInfo(QFileInfo(file).path());
|
QFileInfo dirInfo = QFileInfo(QFileInfo(file).path());
|
||||||
|
const QString canonicalPath = dirInfo.canonicalFilePath();
|
||||||
if (dirInfo.exists() && dirInfo.isDir())
|
if (dirInfo.exists() && dirInfo.isDir())
|
||||||
parseDirectory(dirInfo.canonicalFilePath());
|
parseDirectory(canonicalPath);
|
||||||
|
|
||||||
foreach (const QString &subDir, QDir(QFileInfo(file).path()).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot)) {
|
foreach (const QString &subDir, QDir(QFileInfo(file).path()).entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot)) {
|
||||||
parseDirectory(dirInfo.canonicalFilePath() + QLatin1String("/") + subDir, true, subDir.toUtf8());
|
parseDirectory(canonicalPath + QLatin1Char('/') + subDir, true, subDir.toUtf8());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QStringList assetPaths = quick3DAssetPaths();
|
||||||
|
for (const auto &assetPath : assetPaths)
|
||||||
|
parseDirectory(assetPath);
|
||||||
|
|
||||||
foreach (const Import &import, m_imports) {
|
foreach (const Import &import, m_imports) {
|
||||||
if (import.isFileImport()) {
|
if (import.isFileImport()) {
|
||||||
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
|
QFileInfo dirInfo = QFileInfo(m_filePath.resolved(import.file()).toLocalFile());
|
||||||
@@ -169,6 +173,11 @@ void SubComponentManager::parseDirectory(const QString &canonicalDirPath, bool a
|
|||||||
if (!model() || !model()->rewriterView())
|
if (!model() || !model()->rewriterView())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (canonicalDirPath.endsWith(QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER))) {
|
||||||
|
parseQuick3DAssetDir(canonicalDirPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QDir designerDir(canonicalDirPath + QLatin1String(Constants::QML_DESIGNER_SUBFOLDER));
|
QDir designerDir(canonicalDirPath + QLatin1String(Constants::QML_DESIGNER_SUBFOLDER));
|
||||||
if (designerDir.exists()) {
|
if (designerDir.exists()) {
|
||||||
QStringList filter;
|
QStringList filter;
|
||||||
@@ -325,7 +334,7 @@ void SubComponentManager::registerQmlFile(const QFileInfo &fileInfo, const QStri
|
|||||||
ItemLibraryEntry itemLibraryEntry;
|
ItemLibraryEntry itemLibraryEntry;
|
||||||
itemLibraryEntry.setType(componentName.toUtf8());
|
itemLibraryEntry.setType(componentName.toUtf8());
|
||||||
itemLibraryEntry.setName(baseComponentName);
|
itemLibraryEntry.setName(baseComponentName);
|
||||||
itemLibraryEntry.setCategory(QLatin1String("My QML Components"));
|
itemLibraryEntry.setCategory(tr("My QML Components"));
|
||||||
if (!qualifier.isEmpty()) {
|
if (!qualifier.isEmpty()) {
|
||||||
itemLibraryEntry.setRequiredImport(fixedQualifier);
|
itemLibraryEntry.setRequiredImport(fixedQualifier);
|
||||||
}
|
}
|
||||||
@@ -348,6 +357,75 @@ QStringList SubComponentManager::importPaths() const
|
|||||||
return QStringList();
|
return QStringList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SubComponentManager::parseQuick3DAssetDir(const QString &assetPath)
|
||||||
|
{
|
||||||
|
QDir assetDir(assetPath);
|
||||||
|
const QString assetImportRoot = assetPath.mid(assetPath.lastIndexOf(QLatin1Char('/')) + 1);
|
||||||
|
QStringList assets = assetDir.entryList(QDir::Dirs | QDir::NoDot | QDir::NoDotDot);
|
||||||
|
for (QString &asset : assets)
|
||||||
|
asset.prepend(assetImportRoot + QLatin1Char('.'));
|
||||||
|
|
||||||
|
QStringList newFlowTags;
|
||||||
|
const QStringList flowTags = model()->metaInfo().itemLibraryInfo()->showTagsForImports();
|
||||||
|
const QString quick3Dlib = QLatin1String(Constants::QT_QUICK_3D_MODULE_NAME);
|
||||||
|
const QList<Import> possibleImports = model()->possibleImports();
|
||||||
|
|
||||||
|
auto isPossibleImport = [&possibleImports](const QString &asset) {
|
||||||
|
for (const Import &import : possibleImports) {
|
||||||
|
if (import.url() == asset)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// If there are 3D assets in import path, add a flow tag for QtQuick3D
|
||||||
|
if (!assets.isEmpty() && !flowTags.contains(quick3Dlib) && isPossibleImport(quick3Dlib))
|
||||||
|
newFlowTags << quick3Dlib;
|
||||||
|
|
||||||
|
// Create item library entries for Quick3D assets that are imported by document
|
||||||
|
const QString iconPath = QStringLiteral(":/ItemLibrary/images/item-3D_model-icon.png");
|
||||||
|
for (auto &import : qAsConst(m_imports)) {
|
||||||
|
if (import.isLibraryImport() && assets.contains(import.url())) {
|
||||||
|
assets.removeOne(import.url());
|
||||||
|
ItemLibraryEntry itemLibraryEntry;
|
||||||
|
const QString name = import.url().mid(import.url().indexOf(QLatin1Char('.')) + 1);
|
||||||
|
const QString type = import.url() + QLatin1Char('.') + name;
|
||||||
|
// For now we assume version is always 1.0 as that's what importer hardcodes
|
||||||
|
itemLibraryEntry.setType(type.toUtf8(), 1, 0);
|
||||||
|
itemLibraryEntry.setName(name);
|
||||||
|
itemLibraryEntry.setCategory(tr("My Quick3D Components"));
|
||||||
|
itemLibraryEntry.setRequiredImport(import.url());
|
||||||
|
itemLibraryEntry.setLibraryEntryIconPath(iconPath);
|
||||||
|
itemLibraryEntry.setTypeIcon(QIcon(iconPath));
|
||||||
|
|
||||||
|
if (!model()->metaInfo().itemLibraryInfo()->containsEntry(itemLibraryEntry))
|
||||||
|
model()->metaInfo().itemLibraryInfo()->addEntries({itemLibraryEntry});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create flow tags for the rest, if they are possible imports
|
||||||
|
if (!assets.isEmpty()) {
|
||||||
|
for (const QString &asset : qAsConst(assets)) {
|
||||||
|
if (!flowTags.contains(asset) && isPossibleImport(asset))
|
||||||
|
newFlowTags << asset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!newFlowTags.isEmpty())
|
||||||
|
model()->metaInfo().itemLibraryInfo()->addShowTagsForImports(newFlowTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SubComponentManager::quick3DAssetPaths() const
|
||||||
|
{
|
||||||
|
const auto impPaths = importPaths();
|
||||||
|
QStringList retPaths;
|
||||||
|
for (const auto &impPath : impPaths) {
|
||||||
|
const QString assetPath = impPath + QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
|
||||||
|
if (QFileInfo(assetPath).exists())
|
||||||
|
retPaths << assetPath;
|
||||||
|
}
|
||||||
|
return retPaths;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class SubComponentManager
|
\class SubComponentManager
|
||||||
@@ -392,6 +470,14 @@ void SubComponentManager::update(const QUrl &filePath, const QList<Import> &impo
|
|||||||
m_dirToQualifier.remove(oldDir.canonicalFilePath(), QString());
|
m_dirToQualifier.remove(oldDir.canonicalFilePath(), QString());
|
||||||
if (!m_dirToQualifier.contains(oldDir.canonicalFilePath()))
|
if (!m_dirToQualifier.contains(oldDir.canonicalFilePath()))
|
||||||
m_watcher.removePath(oldDir.filePath());
|
m_watcher.removePath(oldDir.filePath());
|
||||||
|
|
||||||
|
// Remove old watched asset paths
|
||||||
|
const QStringList watchPaths = m_watcher.directories();
|
||||||
|
const QString &quick3DAssetFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
|
||||||
|
for (const auto &watchPath : watchPaths) {
|
||||||
|
if (watchPath.endsWith(quick3DAssetFolder))
|
||||||
|
m_watcher.removePath(watchPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newDir.filePath().isEmpty())
|
if (!newDir.filePath().isEmpty())
|
||||||
@@ -417,7 +503,13 @@ void SubComponentManager::update(const QUrl &filePath, const QList<Import> &impo
|
|||||||
addImport(ii, imports.at(ii));
|
addImport(ii, imports.at(ii));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_watcher.addPath(newDir.absoluteFilePath());
|
const QString newPath = newDir.absoluteFilePath();
|
||||||
|
m_watcher.addPath(newPath);
|
||||||
|
|
||||||
|
// Watch existing asset paths, including a global ones if they exist
|
||||||
|
const auto assetPaths = quick3DAssetPaths();
|
||||||
|
for (const auto &assetPath : assetPaths)
|
||||||
|
m_watcher.addPath(assetPath);
|
||||||
|
|
||||||
parseDirectories();
|
parseDirectories();
|
||||||
}
|
}
|
||||||
|
@@ -50,6 +50,15 @@ const char GO_INTO_COMPONENT[] = "QmlDesigner.GoIntoComponent";
|
|||||||
const char EXPORT_AS_IMAGE[] = "QmlDesigner.ExportAsImage";
|
const char EXPORT_AS_IMAGE[] = "QmlDesigner.ExportAsImage";
|
||||||
|
|
||||||
const char QML_DESIGNER_SUBFOLDER[] = "/designer/";
|
const char QML_DESIGNER_SUBFOLDER[] = "/designer/";
|
||||||
|
const char QUICK_3D_ASSETS_FOLDER[] = "/Quick3DAssets";
|
||||||
|
const char DEFAULT_ASSET_IMPORT_FOLDER[] = "/asset_imports";
|
||||||
|
const char QT_QUICK_3D_MODULE_NAME[] = "QtQuick3D";
|
||||||
|
|
||||||
|
const char FbxExtension[] = "fbx";
|
||||||
|
const char ColladaExtension[] = "dae";
|
||||||
|
const char ObjExtension[] = "obj";
|
||||||
|
const char BlenderExtension[] = "blend";
|
||||||
|
const char GltfExtension[] = "gltf";
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
enum { debug = 0 };
|
enum { debug = 0 };
|
||||||
|
@@ -524,6 +524,11 @@ Project {
|
|||||||
"integration/utilitypanelcontroller.cpp",
|
"integration/utilitypanelcontroller.cpp",
|
||||||
"integration/utilitypanelcontroller.h",
|
"integration/utilitypanelcontroller.h",
|
||||||
"itemlibrary/itemlibrary.qrc",
|
"itemlibrary/itemlibrary.qrc",
|
||||||
|
"itemlibrary/itemlibraryassetimportdialog.cpp",
|
||||||
|
"itemlibrary/itemlibraryassetimportdialog.h",
|
||||||
|
"itemlibrary/itemlibraryassetimportdialog.ui",
|
||||||
|
"itemlibrary/itemlibraryassetimporter.cpp",
|
||||||
|
"itemlibrary/itemlibraryassetimporter.h",
|
||||||
"itemlibrary/itemlibraryimageprovider.cpp",
|
"itemlibrary/itemlibraryimageprovider.cpp",
|
||||||
"itemlibrary/itemlibraryimageprovider.h",
|
"itemlibrary/itemlibraryimageprovider.h",
|
||||||
"itemlibrary/itemlibraryitem.cpp",
|
"itemlibrary/itemlibraryitem.cpp",
|
||||||
|
@@ -55,6 +55,7 @@
|
|||||||
#include <projectexplorer/toolchain.h>
|
#include <projectexplorer/toolchain.h>
|
||||||
|
|
||||||
#include <remotelinux/genericdirectuploadstep.h>
|
#include <remotelinux/genericdirectuploadstep.h>
|
||||||
|
#include <remotelinux/makeinstallstep.h>
|
||||||
#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
|
#include <remotelinux/remotelinuxcheckforfreediskspacestep.h>
|
||||||
|
|
||||||
#include <qtsupport/qtkitinformation.h>
|
#include <qtsupport/qtkitinformation.h>
|
||||||
@@ -90,6 +91,11 @@ public:
|
|||||||
addSupportedTargetDeviceType(Constants::QNX_QNX_OS_TYPE);
|
addSupportedTargetDeviceType(Constants::QNX_QNX_OS_TYPE);
|
||||||
setUseDeploymentDataView();
|
setUseDeploymentDataView();
|
||||||
|
|
||||||
|
addInitialStep(RemoteLinux::MakeInstallStep::stepId(), [](Target *target) {
|
||||||
|
const Project * const prj = target->project();
|
||||||
|
return prj->deploymentKnowledge() == DeploymentKnowledge::Bad
|
||||||
|
&& prj->hasMakeInstallEquivalent();
|
||||||
|
});
|
||||||
addInitialStep(DeviceCheckBuildStep::stepId());
|
addInitialStep(DeviceCheckBuildStep::stepId());
|
||||||
addInitialStep(RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep::stepId());
|
addInitialStep(RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep::stepId());
|
||||||
addInitialStep(RemoteLinux::GenericDirectUploadStep::stepId());
|
addInitialStep(RemoteLinux::GenericDirectUploadStep::stepId());
|
||||||
@@ -110,6 +116,7 @@ public:
|
|||||||
QnxDeployConfigurationFactory deployConfigFactory;
|
QnxDeployConfigurationFactory deployConfigFactory;
|
||||||
GenericQnxDeployStepFactory<RemoteLinux::GenericDirectUploadStep> directUploadDeployFactory;
|
GenericQnxDeployStepFactory<RemoteLinux::GenericDirectUploadStep> directUploadDeployFactory;
|
||||||
GenericQnxDeployStepFactory<RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep> checkForFreeDiskSpaceDeployFactory;
|
GenericQnxDeployStepFactory<RemoteLinux::RemoteLinuxCheckForFreeDiskSpaceStep> checkForFreeDiskSpaceDeployFactory;
|
||||||
|
GenericQnxDeployStepFactory<RemoteLinux::MakeInstallStep> makeInstallDeployFactory;
|
||||||
GenericQnxDeployStepFactory<DeviceCheckBuildStep> checkBuildDeployFactory;
|
GenericQnxDeployStepFactory<DeviceCheckBuildStep> checkBuildDeployFactory;
|
||||||
QnxRunConfigurationFactory runConfigFactory;
|
QnxRunConfigurationFactory runConfigFactory;
|
||||||
QnxSettingsPage settingsPage;
|
QnxSettingsPage settingsPage;
|
||||||
|
@@ -45,7 +45,6 @@ using namespace ProjectExplorer;
|
|||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace RemoteLinux {
|
namespace RemoteLinux {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
const char MakeAspectId[] = "RemoteLinux.MakeInstall.Make";
|
const char MakeAspectId[] = "RemoteLinux.MakeInstall.Make";
|
||||||
const char InstallRootAspectId[] = "RemoteLinux.MakeInstall.InstallRoot";
|
const char InstallRootAspectId[] = "RemoteLinux.MakeInstall.InstallRoot";
|
||||||
@@ -228,5 +227,4 @@ bool MakeInstallStep::fromMap(const QVariantMap &map)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace RemoteLinux
|
} // namespace RemoteLinux
|
||||||
|
@@ -25,15 +25,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "remotelinux_export.h"
|
||||||
|
|
||||||
#include <projectexplorer/deploymentdata.h>
|
#include <projectexplorer/deploymentdata.h>
|
||||||
#include <projectexplorer/makestep.h>
|
#include <projectexplorer/makestep.h>
|
||||||
|
|
||||||
namespace Utils { class FilePath; }
|
namespace Utils { class FilePath; }
|
||||||
|
|
||||||
namespace RemoteLinux {
|
namespace RemoteLinux {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class MakeInstallStep : public ProjectExplorer::MakeStep
|
class REMOTELINUX_EXPORT MakeInstallStep : public ProjectExplorer::MakeStep
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -62,5 +63,4 @@ private:
|
|||||||
bool m_isCmakeProject = false;
|
bool m_isCmakeProject = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace RemoteLinux
|
} // namespace RemoteLinux
|
||||||
|
Submodule src/shared/qbs updated: 94fe404a5a...aec975a3f9
Reference in New Issue
Block a user