forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/15.0'
Change-Id: I1894a1f935fa8bfdc4126db35e3f94849527866a
This commit is contained in:
@@ -146,7 +146,8 @@
|
||||
|
||||
\generatelist studio-how-to-debug
|
||||
\else
|
||||
\sa {Debug}{How To: Debug}, {Debugging}, {Debuggers}, {Debugger}
|
||||
\sa {Add breakpoints}, {Debug}{How To: Debug}, {Debugging}, {Debuggers},
|
||||
{Debugger}
|
||||
\endif
|
||||
*/
|
||||
|
||||
|
@@ -612,11 +612,11 @@
|
||||
"QDocModule": "qtcreator",
|
||||
"QtParts": ["tools"],
|
||||
"QtUsage": "Used for async/await support in Lua modules.",
|
||||
"Path": "src/plugins/lua/bindings",
|
||||
"Path": "src/plugins/lua/scripts",
|
||||
"Description": "lua-async-await implements the async/await pattern in Lua.",
|
||||
"Homepage": "https://github.com/ms-jpq/lua-async-await",
|
||||
"License": "MIT License",
|
||||
"LicenseFile": "src/plugins/lua/bindings/ASYNC-LICENSE.txt",
|
||||
"LicenseFile": "src/plugins/lua/scripts/ASYNC-LICENSE.txt",
|
||||
"Copyright": "Copyright (c) 2008 Paul Evans"
|
||||
},
|
||||
{
|
||||
@@ -625,11 +625,11 @@
|
||||
"QDocModule": "qtcreator",
|
||||
"QtParts": ["tools"],
|
||||
"QtUsage": "Used for pretty printing from Lua scripts.",
|
||||
"Path": "share/qtcreator/lua-plugins/luatests",
|
||||
"Path": "src/plugins/lua/scripts",
|
||||
"Description": "inspect.lua is a library for pretty printing complex objects in Lua.",
|
||||
"Homepage": "https://github.com/kikito/inspect.lua",
|
||||
"License": "MIT License",
|
||||
"LicenseFile": "share/qtcreator/lua-plugins/luatests/INSPECT-LICENSE.txt",
|
||||
"LicenseFile": "src/plugins/lua/scripts/INSPECT-LICENSE.txt",
|
||||
"Copyright": "Copyright (c) 2022 Enrique García Cota"
|
||||
},
|
||||
{
|
||||
@@ -662,4 +662,3 @@
|
||||
"Copyright": "Copyright 2011 The Apache Software Foundation"
|
||||
}
|
||||
]
|
||||
|
||||
|
@@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.19)
|
||||
project(%{ProjectName} LANGUAGES CXX)
|
||||
|
||||
@if %{HasTranslation}
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core LinguistTools)
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Core LinguistTools)
|
||||
@else
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core)
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Core)
|
||||
@endif
|
||||
|
||||
qt_standard_project_setup()
|
||||
@@ -25,6 +25,8 @@ target_link_libraries(%{ProjectName}
|
||||
Qt::Core
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS %{ProjectName}
|
||||
BUNDLE DESTINATION .
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
|
@@ -58,7 +58,7 @@
|
||||
"condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
|
||||
},
|
||||
{
|
||||
"trKey": "CMake for Qt 6",
|
||||
"trKey": "CMake for Qt 6.5 and Later",
|
||||
"value": "cmake-qt6",
|
||||
"condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
|
||||
},
|
||||
|
@@ -152,11 +152,6 @@
|
||||
"target": "%{ProjectDirectory}/%{ImportModuleName}/Constants.qml",
|
||||
"condition": "%{QdsProjectStyle}"
|
||||
},
|
||||
{
|
||||
"source": "%{QdsWizardPath}/shared-plugin/name/DirectoryFontLoader.qml.tpl",
|
||||
"target": "%{ProjectDirectory}/%{ImportModuleName}/DirectoryFontLoader.qml",
|
||||
"condition": "%{QdsProjectStyle}"
|
||||
},
|
||||
{
|
||||
"source": "%{QdsWizardPath}/shared-plugin/name/EventListModel.qml.tpl",
|
||||
"target": "%{ProjectDirectory}/%{ImportModuleName}/EventListModel.qml",
|
||||
|
@@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.19)
|
||||
project(%{ProjectName} LANGUAGES CXX)
|
||||
|
||||
@if %{HasTranslation}
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets LinguistTools)
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets LinguistTools)
|
||||
@else
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets)
|
||||
@endif
|
||||
|
||||
qt_standard_project_setup()
|
||||
@@ -32,6 +32,8 @@ target_link_libraries(%{ProjectName}
|
||||
Qt::Widgets
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(TARGETS %{ProjectName}
|
||||
BUNDLE DESTINATION .
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
|
@@ -64,7 +64,7 @@
|
||||
"condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
|
||||
},
|
||||
{
|
||||
"trKey": "CMake for Qt 6",
|
||||
"trKey": "CMake for Qt 6.5 and Later",
|
||||
"value": "cmake-qt6",
|
||||
"condition": "%{JS: value('Plugins').indexOf('CMakeProjectManager') >= 0}"
|
||||
},
|
||||
|
@@ -15239,12 +15239,12 @@ Zum Beispiel bewirkt die Angabe "Revision: 15" dass der Branch auf Rev
|
||||
<translation>Fallback-Stil:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clang Format command:</source>
|
||||
<translation>Ausführbare Datei von Clang Format:</translation>
|
||||
<source>ClangFormat command:</source>
|
||||
<translation>Ausführbare Datei von ClangFormat:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clang Format</source>
|
||||
<translation>Clang Format</translation>
|
||||
<source>ClangFormat</source>
|
||||
<translation>ClangFormat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Use file uncrustify.cfg defined in project files</source>
|
||||
|
@@ -15352,12 +15352,12 @@ Par exemple, « Revision : 15 » laissera la branche à la révis
|
||||
<translation>Style de repli :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clang Format command:</source>
|
||||
<translation>Commande de Clang Format :</translation>
|
||||
<source>ClangFormat command:</source>
|
||||
<translation>Commande de ClangFormat :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Clang Format</source>
|
||||
<translation>Clang Format</translation>
|
||||
<source>ClangFormat</source>
|
||||
<translation>ClangFormat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>No description available.</source>
|
||||
|
@@ -418,12 +418,11 @@ bool startCrashpad(const AppInfo &appInfo, bool crashReportingEnabled)
|
||||
const QString databasePath = appInfo.crashReports.path();
|
||||
const QString handlerPath = (appInfo.libexec / "crashpad_handler").path();
|
||||
#ifdef Q_OS_WIN
|
||||
handlerPath += ".exe";
|
||||
base::FilePath database(databasePath.toStdWString());
|
||||
base::FilePath handler(handlerPath.toStdWString());
|
||||
base::FilePath handler(HostOsInfo::withExecutableSuffix(handlerPath).toStdWString());
|
||||
#elif defined(Q_OS_MACOS) || defined(Q_OS_LINUX)
|
||||
base::FilePath database(databasePath.toStdString());
|
||||
base::FilePath handler(handlerPath.toStdString());
|
||||
base::FilePath handler(HostOsInfo::withExecutableSuffix(handlerPath).toStdString());
|
||||
#endif
|
||||
|
||||
std::unique_ptr<CrashReportDatabase> db = CrashReportDatabase::Initialize(database);
|
||||
|
@@ -1311,7 +1311,7 @@ expected_str<QString> DockManager::cloneWorkspace(const QString &originalFileNam
|
||||
|
||||
const FilePath clonePath = workspaceNameToFilePath(cloneName);
|
||||
|
||||
const expected_str<void> copyResult = originalPath.copyFile(clonePath);
|
||||
const Result copyResult = originalPath.copyFile(clonePath);
|
||||
if (!copyResult)
|
||||
return make_unexpected(Tr::tr("Could not clone \"%1\" due to: %2")
|
||||
.arg(originalPath.toUserOutput(), copyResult.error()));
|
||||
@@ -1337,21 +1337,21 @@ expected_str<QString> DockManager::renameWorkspace(const QString &originalFileNa
|
||||
return originalFileName;
|
||||
}
|
||||
|
||||
expected_str<void> DockManager::resetWorkspacePreset(const QString &fileName)
|
||||
Result DockManager::resetWorkspacePreset(const QString &fileName)
|
||||
{
|
||||
qCInfo(adsLog) << "Reset workspace" << fileName;
|
||||
|
||||
Workspace *w = workspace(fileName);
|
||||
if (!w)
|
||||
return make_unexpected(Tr::tr("Workspace \"%1\" does not exist.").arg(fileName));
|
||||
return Result::Error(Tr::tr("Workspace \"%1\" does not exist.").arg(fileName));
|
||||
|
||||
if (!w->isPreset())
|
||||
return make_unexpected(Tr::tr("Workspace \"%1\" is not a preset.").arg(fileName));
|
||||
return Result::Error(Tr::tr("Workspace \"%1\" is not a preset.").arg(fileName));
|
||||
|
||||
const FilePath filePath = w->filePath();
|
||||
|
||||
if (!filePath.removeFile())
|
||||
return make_unexpected(Tr::tr("Cannot remove \"%1\".").arg(filePath.toUserOutput()));
|
||||
return Result::Error(Tr::tr("Cannot remove \"%1\".").arg(filePath.toUserOutput()));
|
||||
|
||||
return presetDirectory().pathAppended(fileName).copyFile(filePath);
|
||||
}
|
||||
@@ -1400,7 +1400,7 @@ expected_str<QString> DockManager::importWorkspace(const QString &filePath)
|
||||
|
||||
const FilePath targetFilePath = userDirectory().pathAppended(fileName);
|
||||
|
||||
const expected_str<void> copyResult = sourceFilePath.copyFile(targetFilePath);
|
||||
const Result copyResult = sourceFilePath.copyFile(targetFilePath);
|
||||
if (!copyResult)
|
||||
return make_unexpected(
|
||||
Tr::tr("Could not copy \"%1\" to \"%2\" due to: %3")
|
||||
@@ -1441,7 +1441,7 @@ expected_str<QString> DockManager::exportWorkspace(const QString &targetFilePath
|
||||
Tr::tr("The workspace \"%1\" does not exist ").arg(workspaceFile.toUserOutput()));
|
||||
|
||||
// Finally copy the workspace to the target
|
||||
const expected_str<void> copyResult = workspaceFile.copyFile(targetFile);
|
||||
const Result copyResult = workspaceFile.copyFile(targetFile);
|
||||
if (!copyResult)
|
||||
return make_unexpected(
|
||||
Tr::tr("Could not copy \"%1\" to \"%2\" due to: %3")
|
||||
@@ -1675,7 +1675,7 @@ void DockManager::syncWorkspacePresets()
|
||||
continue;
|
||||
}
|
||||
|
||||
const expected_str<void> copyResult = filePath.copyFile(
|
||||
const Result copyResult = filePath.copyFile(
|
||||
userDirectory().pathAppended(filePath.fileName()));
|
||||
if (!copyResult)
|
||||
qWarning() << QString("Could not copy '%1' to '%2' due to %3")
|
||||
|
@@ -739,7 +739,7 @@ public:
|
||||
Utils::expected_str<QString> renameWorkspace(const QString &originalFileName,
|
||||
const QString &newName);
|
||||
|
||||
Utils::expected_str<void> resetWorkspacePreset(const QString &fileName);
|
||||
Utils::Result resetWorkspacePreset(const QString &fileName);
|
||||
|
||||
/**
|
||||
* \brief Save the currently active workspace.
|
||||
|
@@ -33,61 +33,60 @@ expected_str<QString> run(const CommandLine &cmdLine, const QByteArray &inputDat
|
||||
return p.readAllStandardOutput().trimmed();
|
||||
}
|
||||
|
||||
Utils::expected_str<void> FileAccess::init(const Utils::FilePath &pathToBridge)
|
||||
Result FileAccess::init(const FilePath &pathToBridge)
|
||||
{
|
||||
m_client = std::make_unique<Client>(pathToBridge);
|
||||
|
||||
auto startResult = m_client->start();
|
||||
if (!startResult)
|
||||
return make_unexpected(QString("Could not start cmdbridge: %1").arg(startResult.error()));
|
||||
return Result::Error(QString("Could not start cmdbridge: %1").arg(startResult.error()));
|
||||
|
||||
try {
|
||||
if (!startResult->isValid())
|
||||
startResult->waitForFinished();
|
||||
m_environment = startResult->takeResult();
|
||||
} catch (const std::exception &e) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Error starting cmdbridge: %1").arg(QString::fromLocal8Bit(e.what())));
|
||||
}
|
||||
return {};
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
expected_str<void> FileAccess::deployAndInit(
|
||||
const FilePath &libExecPath, const FilePath &remoteRootPath)
|
||||
Result FileAccess::deployAndInit(const FilePath &libExecPath, const FilePath &remoteRootPath)
|
||||
{
|
||||
if (remoteRootPath.isEmpty())
|
||||
return make_unexpected(Tr::tr("Remote root path is empty"));
|
||||
return Result::Error(Tr::tr("Remote root path is empty"));
|
||||
|
||||
if (!remoteRootPath.isAbsolutePath())
|
||||
return make_unexpected(Tr::tr("Remote root path is not absolute"));
|
||||
return Result::Error(Tr::tr("Remote root path is not absolute"));
|
||||
|
||||
const auto whichDD = run({remoteRootPath.withNewPath("which"), {"dd"}});
|
||||
|
||||
if (!whichDD) // TODO: Support Windows?
|
||||
return make_unexpected(Tr::tr("Could not find dd on remote host: %1").arg(whichDD.error()));
|
||||
return Result::Error(Tr::tr("Could not find dd on remote host: %1").arg(whichDD.error()));
|
||||
|
||||
qCDebug(faLog) << "Found dd on remote host:" << *whichDD;
|
||||
|
||||
const expected_str<QString> unameOs = run({remoteRootPath.withNewPath("uname"), {"-s"}});
|
||||
if (!unameOs) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
QString("Could not determine OS on remote host: %1").arg(unameOs.error()));
|
||||
}
|
||||
Utils::expected_str<OsType> osType = osTypeFromString(*unameOs);
|
||||
if (!osType)
|
||||
return make_unexpected(osType.error());
|
||||
return Result::Error(osType.error());
|
||||
|
||||
qCDebug(faLog) << "Remote host OS:" << *unameOs;
|
||||
|
||||
const expected_str<QString> unameArch = run({remoteRootPath.withNewPath("uname"), {"-m"}});
|
||||
if (!unameArch) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
QString("Could not determine architecture on remote host: %1").arg(unameArch.error()));
|
||||
}
|
||||
|
||||
const Utils::expected_str<OsArch> osArch = osArchFromString(*unameArch);
|
||||
if (!osArch)
|
||||
return make_unexpected(osArch.error());
|
||||
return Result::Error(osArch.error());
|
||||
|
||||
qCDebug(faLog) << "Remote host architecture:" << *unameArch;
|
||||
|
||||
@@ -95,7 +94,7 @@ expected_str<void> FileAccess::deployAndInit(
|
||||
= Client::getCmdBridgePath(*osType, *osArch, libExecPath);
|
||||
|
||||
if (!cmdBridgePath) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
QString("Could not determine compatible cmdbridge for remote host: %1")
|
||||
.arg(cmdBridgePath.error()));
|
||||
}
|
||||
@@ -106,7 +105,7 @@ expected_str<void> FileAccess::deployAndInit(
|
||||
const auto cmdBridgeFileData = cmdBridgePath->fileContents();
|
||||
|
||||
if (!cmdBridgeFileData) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
QString("Could not read cmdbridge file: %1").arg(cmdBridgeFileData.error()));
|
||||
}
|
||||
|
||||
@@ -114,7 +113,7 @@ expected_str<void> FileAccess::deployAndInit(
|
||||
{remoteRootPath.withNewPath("mktemp"), {"-t", "cmdbridge.XXXXXXXXXX"}});
|
||||
|
||||
if (!tmpFile) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
QString("Could not create temporary file: %1").arg(tmpFile.error()));
|
||||
}
|
||||
|
||||
@@ -125,7 +124,7 @@ expected_str<void> FileAccess::deployAndInit(
|
||||
const auto makeExecutable = run({remoteRootPath.withNewPath("chmod"), {"+x", *tmpFile}});
|
||||
|
||||
if (!makeExecutable) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
QString("Could not make temporary file executable: %1").arg(makeExecutable.error()));
|
||||
}
|
||||
|
||||
@@ -468,26 +467,26 @@ expected_str<qint64> FileAccess::writeFileContents(const FilePath &filePath,
|
||||
}
|
||||
}
|
||||
|
||||
expected_str<void> FileAccess::removeFile(const Utils::FilePath &filePath) const
|
||||
Result FileAccess::removeFile(const FilePath &filePath) const
|
||||
{
|
||||
try {
|
||||
Utils::expected_str<QFuture<void>> f = m_client->removeFile(filePath.nativePath());
|
||||
if (!f)
|
||||
return make_unexpected(f.error());
|
||||
return Result::Error(f.error());
|
||||
f->waitForFinished();
|
||||
} catch (const std::system_error &e) {
|
||||
if (e.code().value() == ENOENT)
|
||||
return make_unexpected(Tr::tr("File does not exist"));
|
||||
return Result::Error(Tr::tr("File does not exist"));
|
||||
qCWarning(faLog) << "Error removing file:" << e.what();
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Error removing file: %1").arg(QString::fromLocal8Bit(e.what())));
|
||||
} catch (const std::exception &e) {
|
||||
qCWarning(faLog) << "Error removing file:" << e.what();
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Error removing file: %1").arg(QString::fromLocal8Bit(e.what())));
|
||||
}
|
||||
|
||||
return {};
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
bool FileAccess::removeRecursively(const Utils::FilePath &filePath, QString *error) const
|
||||
@@ -530,37 +529,35 @@ bool FileAccess::createDirectory(const Utils::FilePath &filePath) const
|
||||
}
|
||||
}
|
||||
|
||||
expected_str<void> FileAccess::copyFile(const Utils::FilePath &filePath,
|
||||
const Utils::FilePath &target) const
|
||||
Result FileAccess::copyFile(const FilePath &filePath, const FilePath &target) const
|
||||
{
|
||||
try {
|
||||
auto f = m_client->copyFile(filePath.nativePath(), target.nativePath());
|
||||
QTC_ASSERT_EXPECTED(f, return {});
|
||||
QTC_ASSERT_EXPECTED(f, return Result::Ok);
|
||||
f->waitForFinished();
|
||||
return {};
|
||||
return Result::Ok;
|
||||
} catch (const std::exception &e) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Error copying file: %1").arg(QString::fromLocal8Bit(e.what())));
|
||||
}
|
||||
}
|
||||
|
||||
expected_str<void> FileAccess::renameFile(
|
||||
const Utils::FilePath &filePath, const Utils::FilePath &target) const
|
||||
Result FileAccess::renameFile(const FilePath &filePath, const FilePath &target) const
|
||||
{
|
||||
try {
|
||||
Utils::expected_str<QFuture<void>> f
|
||||
= m_client->renameFile(filePath.nativePath(), target.nativePath());
|
||||
if (!f)
|
||||
return make_unexpected(f.error());
|
||||
return Result::Error(f.error());
|
||||
f->waitForFinished();
|
||||
if (!f)
|
||||
return make_unexpected(f.error());
|
||||
return Result::Error(f.error());
|
||||
} catch (const std::exception &e) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Error renaming file: %1").arg(QString::fromLocal8Bit(e.what())));
|
||||
}
|
||||
|
||||
return {};
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
Environment FileAccess::deviceEnvironment() const
|
||||
@@ -574,15 +571,15 @@ expected_str<std::unique_ptr<FilePathWatcher>> FileAccess::watch(const FilePath
|
||||
return m_client->watch(filePath.nativePath());
|
||||
}
|
||||
|
||||
Utils::expected_str<void> FileAccess::signalProcess(int pid, ControlSignal signal) const
|
||||
Result FileAccess::signalProcess(int pid, ControlSignal signal) const
|
||||
{
|
||||
try {
|
||||
auto f = m_client->signalProcess(pid, signal);
|
||||
QTC_ASSERT_EXPECTED(f, return {});
|
||||
QTC_ASSERT_EXPECTED(f, return Result::Ok);
|
||||
f->waitForFinished();
|
||||
return {};
|
||||
return Result::Ok;
|
||||
} catch (const std::exception &e) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Error killing process: %1").arg(QString::fromLocal8Bit(e.what())));
|
||||
};
|
||||
}
|
||||
|
@@ -27,17 +27,17 @@ class QTCREATOR_CMDBRIDGE_EXPORT FileAccess : public Utils::DeviceFileAccess
|
||||
public:
|
||||
~FileAccess() override;
|
||||
|
||||
Utils::expected_str<void> deployAndInit(
|
||||
Utils::Result deployAndInit(
|
||||
const Utils::FilePath &libExecPath, const Utils::FilePath &remoteRootPath);
|
||||
|
||||
Utils::expected_str<void> init(const Utils::FilePath &pathToBridge);
|
||||
Utils::Result init(const Utils::FilePath &pathToBridge);
|
||||
|
||||
Utils::expected_str<void> signalProcess(int pid, Utils::ControlSignal signal) const;
|
||||
Utils::Result signalProcess(int pid, Utils::ControlSignal signal) const;
|
||||
|
||||
Utils::Environment deviceEnvironment() const override;
|
||||
|
||||
protected:
|
||||
Utils::expected_str<void> reinit();
|
||||
Utils::Result reinit();
|
||||
|
||||
void iterateDirectory(const Utils::FilePath &filePath,
|
||||
const Utils::FilePath::IterateDirCallback &callBack,
|
||||
@@ -69,16 +69,16 @@ protected:
|
||||
Utils::expected_str<qint64> writeFileContents(const Utils::FilePath &filePath,
|
||||
const QByteArray &data) const override;
|
||||
|
||||
Utils::expected_str<void> removeFile(const Utils::FilePath &filePath) const override;
|
||||
Utils::Result removeFile(const Utils::FilePath &filePath) const override;
|
||||
bool removeRecursively(const Utils::FilePath &filePath, QString *error) const override;
|
||||
|
||||
bool ensureExistingFile(const Utils::FilePath &filePath) const override;
|
||||
bool createDirectory(const Utils::FilePath &filePath) const override;
|
||||
|
||||
Utils::expected_str<void> copyFile(const Utils::FilePath &filePath,
|
||||
const Utils::FilePath &target) const override;
|
||||
Utils::Result copyFile(const Utils::FilePath &filePath,
|
||||
const Utils::FilePath &target) const override;
|
||||
|
||||
Utils::expected_str<void> renameFile(
|
||||
Utils::Result renameFile(
|
||||
const Utils::FilePath &filePath, const Utils::FilePath &target) const override;
|
||||
|
||||
Utils::expected_str<Utils::FilePath> createTempFile(const Utils::FilePath &filePath) override;
|
||||
|
@@ -294,6 +294,14 @@ void BaseAspect::addLabeledItem(Layout &parent, QWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
void BaseAspect::addLabeledItems(Layouting::Layout &parent, const QList<QWidget *> &widgets)
|
||||
{
|
||||
if (QLabel *l = createLabel())
|
||||
parent.addItem(l);
|
||||
for (auto widget : widgets)
|
||||
parent.addItem(widget);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets \a labelText as text for the separate label in the visual
|
||||
representation of this aspect.
|
||||
@@ -3162,6 +3170,7 @@ void AspectContainer::addToLayoutImpl(Layouting::Layout &parent)
|
||||
void AspectContainer::registerAspect(BaseAspect *aspect, bool takeOwnership)
|
||||
{
|
||||
aspect->setAutoApply(isAutoApply());
|
||||
aspect->setEnabled(isEnabled());
|
||||
d->m_items.append(aspect);
|
||||
if (takeOwnership)
|
||||
d->m_ownedItems.append(aspect);
|
||||
@@ -3316,6 +3325,14 @@ void AspectContainer::setUndoStack(QUndoStack *undoStack)
|
||||
aspect->setUndoStack(undoStack);
|
||||
}
|
||||
|
||||
void AspectContainer::setEnabled(bool enabled)
|
||||
{
|
||||
BaseAspect::setEnabled(enabled);
|
||||
|
||||
for (BaseAspect *aspect : std::as_const(d->m_items))
|
||||
aspect->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void AspectContainer::setMacroExpander(MacroExpander *expander)
|
||||
{
|
||||
BaseAspect::setMacroExpander(expander);
|
||||
|
@@ -98,7 +98,7 @@ public:
|
||||
QUndoStack *undoStack() const;
|
||||
|
||||
bool isEnabled() const;
|
||||
void setEnabled(bool enabled);
|
||||
virtual void setEnabled(bool enabled);
|
||||
void setEnabler(BoolAspect *checker);
|
||||
|
||||
bool isReadOnly() const;
|
||||
@@ -237,6 +237,7 @@ protected:
|
||||
|
||||
QLabel *createLabel();
|
||||
void addLabeledItem(Layouting::Layout &parent, QWidget *widget);
|
||||
void addLabeledItems(Layouting::Layout &parent, const QList<QWidget *> &widgets);
|
||||
|
||||
void setDataCreatorHelper(const DataCreator &creator) const;
|
||||
void setDataClonerHelper(const DataCloner &cloner) const;
|
||||
@@ -996,6 +997,7 @@ public:
|
||||
void setAutoApply(bool on) override;
|
||||
bool isDirty() override;
|
||||
void setUndoStack(QUndoStack *undoStack) override;
|
||||
void setEnabled(bool enabled) override;
|
||||
|
||||
void setMacroExpander(MacroExpander *expander);
|
||||
|
||||
|
@@ -117,22 +117,21 @@ bool DeviceFileAccess::hasHardLinks(const FilePath &filePath) const
|
||||
return false;
|
||||
}
|
||||
|
||||
expected_str<void> DeviceFileAccess::ensureWritableDirectory(const FilePath &filePath) const
|
||||
Result DeviceFileAccess::ensureWritableDirectory(const FilePath &filePath) const
|
||||
{
|
||||
if (isWritableDirectory(filePath))
|
||||
return {};
|
||||
return Result::Ok;
|
||||
|
||||
if (exists(filePath)) {
|
||||
return make_unexpected(Tr::tr("Path \"%1\" exists but is not a writable directory.")
|
||||
return Result::Error(Tr::tr("Path \"%1\" exists but is not a writable directory.")
|
||||
.arg(filePath.toUserOutput()));
|
||||
}
|
||||
|
||||
const bool result = createDirectory(filePath);
|
||||
if (result)
|
||||
return {};
|
||||
return Result::Ok;
|
||||
|
||||
return make_unexpected(
|
||||
Tr::tr("Failed to create directory \"%1\".").arg(filePath.toUserOutput()));
|
||||
return Result::Error(Tr::tr("Failed to create directory \"%1\".").arg(filePath.toUserOutput()));
|
||||
}
|
||||
|
||||
bool DeviceFileAccess::ensureExistingFile(const FilePath &filePath) const
|
||||
@@ -155,11 +154,10 @@ bool DeviceFileAccess::exists(const FilePath &filePath) const
|
||||
return false;
|
||||
}
|
||||
|
||||
expected_str<void> DeviceFileAccess::removeFile(const FilePath &filePath) const
|
||||
Result DeviceFileAccess::removeFile(const FilePath &filePath) const
|
||||
{
|
||||
Q_UNUSED(filePath)
|
||||
QTC_CHECK(false);
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("removeFile is not implemented for \"%1\".").arg(filePath.toUserOutput()));
|
||||
}
|
||||
|
||||
@@ -171,18 +169,17 @@ bool DeviceFileAccess::removeRecursively(const FilePath &filePath, QString *erro
|
||||
return false;
|
||||
}
|
||||
|
||||
expected_str<void> DeviceFileAccess::copyFile(const FilePath &filePath, const FilePath &target) const
|
||||
Result DeviceFileAccess::copyFile(const FilePath &filePath, const FilePath &target) const
|
||||
{
|
||||
Q_UNUSED(filePath)
|
||||
Q_UNUSED(target)
|
||||
QTC_CHECK(false);
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("copyFile is not implemented for \"%1\".").arg(filePath.toUserOutput()));
|
||||
}
|
||||
|
||||
expected_str<void> copyRecursively_fallback(const FilePath &src, const FilePath &target)
|
||||
static Result copyRecursively_fallback(const FilePath &src, const FilePath &target)
|
||||
{
|
||||
expected_str<void> result;
|
||||
Result result = Result::Ok;
|
||||
src.iterateDirectory(
|
||||
[&target, &src, &result](const FilePath &path) {
|
||||
const FilePath relative = path.relativePathFrom(src);
|
||||
@@ -202,16 +199,15 @@ expected_str<void> copyRecursively_fallback(const FilePath &src, const FilePath
|
||||
return result;
|
||||
}
|
||||
|
||||
expected_str<void> DeviceFileAccess::copyRecursively(const FilePath &src,
|
||||
const FilePath &target) const
|
||||
Result DeviceFileAccess::copyRecursively(const FilePath &src, const FilePath &target) const
|
||||
{
|
||||
if (!src.isDir()) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Cannot copy from \"%1\", it is not a directory.").arg(src.toUserOutput()));
|
||||
}
|
||||
const expected_str<void> result = target.ensureWritableDir();
|
||||
const Result result = target.ensureWritableDir();
|
||||
if (!result) {
|
||||
return make_unexpected(Tr::tr("Cannot copy \"%1\" to \"%2\": %3")
|
||||
return Result::Error(Tr::tr("Cannot copy \"%1\" to \"%2\": %3")
|
||||
.arg(src.toUserOutput())
|
||||
.arg(target.toUserOutput())
|
||||
.arg(result.error()));
|
||||
@@ -254,7 +250,7 @@ expected_str<void> DeviceFileAccess::copyRecursively(const FilePath &src,
|
||||
|
||||
if (srcProcess.result() != ProcessResult::FinishedWithSuccess) {
|
||||
targetProcess.kill();
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Failed to copy recursively from \"%1\" to \"%2\" while "
|
||||
"trying to create tar archive from source: %3")
|
||||
.arg(src.toUserOutput(), target.toUserOutput(), srcProcess.readAllStandardError()));
|
||||
@@ -263,23 +259,22 @@ expected_str<void> DeviceFileAccess::copyRecursively(const FilePath &src,
|
||||
targetProcess.waitForFinished();
|
||||
|
||||
if (targetProcess.result() != ProcessResult::FinishedWithSuccess) {
|
||||
return make_unexpected(Tr::tr("Failed to copy recursively from \"%1\" to \"%2\" while "
|
||||
return Result::Error(Tr::tr("Failed to copy recursively from \"%1\" to \"%2\" while "
|
||||
"trying to extract tar archive to target: %3")
|
||||
.arg(src.toUserOutput(),
|
||||
target.toUserOutput(),
|
||||
targetProcess.readAllStandardError()));
|
||||
}
|
||||
|
||||
return {};
|
||||
return Result::Ok;
|
||||
#endif
|
||||
}
|
||||
|
||||
expected_str<void> DeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const
|
||||
Result DeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const
|
||||
{
|
||||
Q_UNUSED(filePath)
|
||||
Q_UNUSED(target)
|
||||
QTC_CHECK(false);
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("renameFile is not implemented for \"%1\".").arg(filePath.toUserOutput()));
|
||||
}
|
||||
|
||||
@@ -684,22 +679,22 @@ bool DesktopDeviceFileAccess::hasHardLinks(const FilePath &filePath) const
|
||||
return false;
|
||||
}
|
||||
|
||||
expected_str<void> DesktopDeviceFileAccess::ensureWritableDirectory(const FilePath &filePath) const
|
||||
Result DesktopDeviceFileAccess::ensureWritableDirectory(const FilePath &filePath) const
|
||||
{
|
||||
const QFileInfo fi(filePath.path());
|
||||
if (fi.isDir() && fi.isWritable())
|
||||
return {};
|
||||
return Result::Ok;
|
||||
|
||||
if (fi.exists()) {
|
||||
return make_unexpected(Tr::tr("Path \"%1\" exists but is not a writable directory.")
|
||||
return Result::Error(Tr::tr("Path \"%1\" exists but is not a writable directory.")
|
||||
.arg(filePath.toUserOutput()));
|
||||
}
|
||||
|
||||
const bool result = QDir().mkpath(filePath.path());
|
||||
if (result)
|
||||
return {};
|
||||
return Result::Ok;
|
||||
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Failed to create directory \"%1\".").arg(filePath.toUserOutput()));
|
||||
}
|
||||
|
||||
@@ -724,12 +719,12 @@ bool DesktopDeviceFileAccess::exists(const FilePath &filePath) const
|
||||
return !filePath.isEmpty() && QFileInfo::exists(filePath.path());
|
||||
}
|
||||
|
||||
expected_str<void> DesktopDeviceFileAccess::removeFile(const FilePath &filePath) const
|
||||
Result DesktopDeviceFileAccess::removeFile(const FilePath &filePath) const
|
||||
{
|
||||
QFile f(filePath.path());
|
||||
if (!f.remove())
|
||||
return make_unexpected(f.errorString());
|
||||
return {};
|
||||
return Result::Error(f.errorString());
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
static bool checkToRefuseRemoveStandardLocationDirectory(const QString &dirPath,
|
||||
@@ -806,26 +801,26 @@ bool DesktopDeviceFileAccess::removeRecursively(const FilePath &filePath, QStrin
|
||||
return true;
|
||||
}
|
||||
|
||||
expected_str<void> DesktopDeviceFileAccess::copyFile(const FilePath &filePath,
|
||||
Result DesktopDeviceFileAccess::copyFile(const FilePath &filePath,
|
||||
const FilePath &target) const
|
||||
{
|
||||
QFile srcFile(filePath.path());
|
||||
|
||||
if (srcFile.copy(target.path()))
|
||||
return {};
|
||||
return make_unexpected(
|
||||
return Result::Ok;
|
||||
return Result::Error(
|
||||
Tr::tr("Failed to copy file \"%1\" to \"%2\": %3")
|
||||
.arg(filePath.toUserOutput(), target.toUserOutput(), srcFile.errorString()));
|
||||
}
|
||||
|
||||
expected_str<void> DesktopDeviceFileAccess::renameFile(
|
||||
Result DesktopDeviceFileAccess::renameFile(
|
||||
const FilePath &filePath, const FilePath &target) const
|
||||
{
|
||||
QFile f(filePath.path());
|
||||
|
||||
if (f.rename(target.path()))
|
||||
return {};
|
||||
return make_unexpected(
|
||||
return Result::Ok;
|
||||
return Result::Error(
|
||||
Tr::tr("Failed to rename file \"%1\" to \"%2\": %3")
|
||||
.arg(filePath.toUserOutput(), target.toUserOutput(), f.errorString()));
|
||||
}
|
||||
@@ -1060,9 +1055,14 @@ QByteArray DesktopDeviceFileAccess::fileId(const FilePath &filePath) const
|
||||
|
||||
// UnixDeviceAccess
|
||||
|
||||
static QString disconnectedMessage()
|
||||
{
|
||||
return Tr::tr("Device is not connected");
|
||||
}
|
||||
|
||||
static Utils::unexpected<QString> make_unexpected_disconnected()
|
||||
{
|
||||
return make_unexpected(Tr::tr("Device is not connected"));
|
||||
return make_unexpected(disconnectedMessage());
|
||||
}
|
||||
|
||||
UnixDeviceFileAccess::~UnixDeviceFileAccess() = default;
|
||||
@@ -1175,20 +1175,21 @@ bool UnixDeviceFileAccess::exists(const FilePath &filePath) const
|
||||
return runInShellSuccess({"test", {"-e", path}, OsType::OsTypeLinux});
|
||||
}
|
||||
|
||||
expected_str<void> UnixDeviceFileAccess::removeFile(const FilePath &filePath) const
|
||||
Result UnixDeviceFileAccess::removeFile(const FilePath &filePath) const
|
||||
{
|
||||
if (disconnected())
|
||||
return make_unexpected_disconnected();
|
||||
return Result::Error(disconnectedMessage());
|
||||
RunResult result = runInShell({"rm", {filePath.path()}, OsType::OsTypeLinux});
|
||||
if (result.exitCode != 0)
|
||||
return make_unexpected(QString::fromUtf8(result.stdErr));
|
||||
return {};
|
||||
return Result::Error(QString::fromUtf8(result.stdErr));
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString *error) const
|
||||
{
|
||||
if (disconnected())
|
||||
return false;
|
||||
|
||||
QTC_ASSERT(filePath.path().startsWith('/'), return false);
|
||||
|
||||
const QString path = filePath.cleanPath().path();
|
||||
@@ -1206,36 +1207,35 @@ bool UnixDeviceFileAccess::removeRecursively(const FilePath &filePath, QString *
|
||||
return result.exitCode == 0;
|
||||
}
|
||||
|
||||
expected_str<void> UnixDeviceFileAccess::copyFile(const FilePath &filePath,
|
||||
const FilePath &target) const
|
||||
Result UnixDeviceFileAccess::copyFile(const FilePath &filePath, const FilePath &target) const
|
||||
{
|
||||
if (disconnected())
|
||||
return make_unexpected_disconnected();
|
||||
return Result::Error(disconnectedMessage());
|
||||
const RunResult result = runInShell(
|
||||
{"cp", {filePath.path(), target.path()}, OsType::OsTypeLinux});
|
||||
|
||||
if (result.exitCode != 0) {
|
||||
return make_unexpected(Tr::tr("Failed to copy file \"%1\" to \"%2\": %3")
|
||||
return Result::Error(Tr::tr("Failed to copy file \"%1\" to \"%2\": %3")
|
||||
.arg(filePath.toUserOutput(),
|
||||
target.toUserOutput(),
|
||||
QString::fromUtf8(result.stdErr)));
|
||||
}
|
||||
return {};
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
expected_str<void> UnixDeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const
|
||||
Result UnixDeviceFileAccess::renameFile(const FilePath &filePath, const FilePath &target) const
|
||||
{
|
||||
if (disconnected())
|
||||
return make_unexpected_disconnected();
|
||||
return Result::Error(disconnectedMessage());
|
||||
|
||||
auto result = runInShell({"mv", {filePath.path(), target.path()}, OsType::OsTypeLinux});
|
||||
RunResult result = runInShell({"mv", {filePath.path(), target.path()}, OsType::OsTypeLinux});
|
||||
if (result.exitCode != 0) {
|
||||
return make_unexpected(Tr::tr("Failed to rename file \"%1\" to \"%2\": %3")
|
||||
return Result::Error(Tr::tr("Failed to rename file \"%1\" to \"%2\": %3")
|
||||
.arg(filePath.toUserOutput(),
|
||||
target.toUserOutput(),
|
||||
QString::fromUtf8(result.stdErr)));
|
||||
}
|
||||
return {};
|
||||
return Result::Ok;
|
||||
}
|
||||
|
||||
FilePath UnixDeviceFileAccess::symLinkTarget(const FilePath &filePath) const
|
||||
|
@@ -38,16 +38,15 @@ protected:
|
||||
virtual bool isDirectory(const FilePath &filePath) const;
|
||||
virtual bool isSymLink(const FilePath &filePath) const;
|
||||
virtual bool hasHardLinks(const FilePath &filePath) const;
|
||||
virtual expected_str<void> ensureWritableDirectory(const FilePath &filePath) const;
|
||||
virtual Result ensureWritableDirectory(const FilePath &filePath) const;
|
||||
virtual bool ensureExistingFile(const FilePath &filePath) const;
|
||||
virtual bool createDirectory(const FilePath &filePath) const;
|
||||
virtual bool exists(const FilePath &filePath) const;
|
||||
virtual expected_str<void> removeFile(const FilePath &filePath) const;
|
||||
virtual Result removeFile(const FilePath &filePath) const;
|
||||
virtual bool removeRecursively(const FilePath &filePath, QString *error) const;
|
||||
virtual expected_str<void> copyFile(const FilePath &filePath, const FilePath &target) const;
|
||||
virtual expected_str<void> copyRecursively(const FilePath &filePath,
|
||||
const FilePath &target) const;
|
||||
virtual expected_str<void> renameFile(const FilePath &filePath, const FilePath &target) const;
|
||||
virtual Result copyFile(const FilePath &filePath, const FilePath &target) const;
|
||||
virtual Result copyRecursively(const FilePath &filePath, const FilePath &target) const;
|
||||
virtual Result renameFile(const FilePath &filePath, const FilePath &target) const;
|
||||
|
||||
virtual FilePath symLinkTarget(const FilePath &filePath) const;
|
||||
virtual FilePathInfo filePathInfo(const FilePath &filePath) const;
|
||||
@@ -97,14 +96,14 @@ protected:
|
||||
bool isDirectory(const FilePath &filePath) const override;
|
||||
bool isSymLink(const FilePath &filePath) const override;
|
||||
bool hasHardLinks(const FilePath &filePath) const override;
|
||||
expected_str<void> ensureWritableDirectory(const FilePath &filePath) const override;
|
||||
Result ensureWritableDirectory(const FilePath &filePath) const override;
|
||||
bool ensureExistingFile(const FilePath &filePath) const override;
|
||||
bool createDirectory(const FilePath &filePath) const override;
|
||||
bool exists(const FilePath &filePath) const override;
|
||||
expected_str<void> removeFile(const FilePath &filePath) const override;
|
||||
Result removeFile(const FilePath &filePath) const override;
|
||||
bool removeRecursively(const FilePath &filePath, QString *error) const override;
|
||||
expected_str<void> copyFile(const FilePath &filePath, const FilePath &target) const override;
|
||||
expected_str<void> renameFile(const FilePath &filePath, const FilePath &target) const override;
|
||||
Result copyFile(const FilePath &filePath, const FilePath &target) const override;
|
||||
Result renameFile(const FilePath &filePath, const FilePath &target) const override;
|
||||
|
||||
FilePath symLinkTarget(const FilePath &filePath) const override;
|
||||
FilePathInfo filePathInfo(const FilePath &filePath) const override;
|
||||
@@ -159,10 +158,10 @@ protected:
|
||||
bool ensureExistingFile(const FilePath &filePath) const override;
|
||||
bool createDirectory(const FilePath &filePath) const override;
|
||||
bool exists(const FilePath &filePath) const override;
|
||||
expected_str<void> removeFile(const FilePath &filePath) const override;
|
||||
Result removeFile(const FilePath &filePath) const override;
|
||||
bool removeRecursively(const FilePath &filePath, QString *error) const override;
|
||||
expected_str<void> copyFile(const FilePath &filePath, const FilePath &target) const override;
|
||||
expected_str<void> renameFile(const FilePath &filePath, const FilePath &target) const override;
|
||||
Result copyFile(const FilePath &filePath, const FilePath &target) const override;
|
||||
Result renameFile(const FilePath &filePath, const FilePath &target) const override;
|
||||
|
||||
FilePathInfo filePathInfo(const FilePath &filePath) const override;
|
||||
FilePath symLinkTarget(const FilePath &filePath) const override;
|
||||
|
@@ -551,7 +551,7 @@ void FilePath::setParts(const QStringView scheme, const QStringView host, QStrin
|
||||
|
||||
\sa createDir()
|
||||
*/
|
||||
expected_str<void> FilePath::ensureWritableDir() const
|
||||
Result FilePath::ensureWritableDir() const
|
||||
{
|
||||
return fileAccess()->ensureWritableDirectory(*this);
|
||||
}
|
||||
@@ -1980,7 +1980,7 @@ OsType FilePath::osType() const
|
||||
return s_deviceHooks.osType(*this);
|
||||
}
|
||||
|
||||
expected_str<void> FilePath::removeFile() const
|
||||
Result FilePath::removeFile() const
|
||||
{
|
||||
return fileAccess()->removeFile(*this);
|
||||
}
|
||||
@@ -1997,18 +1997,18 @@ bool FilePath::removeRecursively(QString *error) const
|
||||
return fileAccess()->removeRecursively(*this, error);
|
||||
}
|
||||
|
||||
expected_str<void> FilePath::copyRecursively(const FilePath &target) const
|
||||
Result FilePath::copyRecursively(const FilePath &target) const
|
||||
{
|
||||
return fileAccess()->copyRecursively(*this, target);
|
||||
}
|
||||
|
||||
expected_str<void> FilePath::copyFile(const FilePath &target) const
|
||||
Result FilePath::copyFile(const FilePath &target) const
|
||||
{
|
||||
if (!isSameDevice(target)) {
|
||||
// FIXME: This does not scale.
|
||||
const expected_str<QByteArray> contents = fileContents();
|
||||
if (!contents) {
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Error while trying to copy file: %1").arg(contents.error()));
|
||||
}
|
||||
|
||||
@@ -2016,38 +2016,41 @@ expected_str<void> FilePath::copyFile(const FilePath &target) const
|
||||
const expected_str<qint64> copyResult = target.writeFileContents(*contents);
|
||||
|
||||
if (!copyResult)
|
||||
return make_unexpected(Tr::tr("Could not copy file: %1").arg(copyResult.error()));
|
||||
return Result::Error(Tr::tr("Could not copy file: %1").arg(copyResult.error()));
|
||||
|
||||
if (!target.setPermissions(perms)) {
|
||||
target.removeFile();
|
||||
return make_unexpected(
|
||||
return Result::Error(
|
||||
Tr::tr("Could not set permissions on \"%1\"").arg(target.toString()));
|
||||
}
|
||||
|
||||
return {};
|
||||
return Result::Ok;
|
||||
}
|
||||
return fileAccess()->copyFile(*this, target);
|
||||
}
|
||||
|
||||
expected_str<void> FilePath::renameFile(const FilePath &target) const
|
||||
Result FilePath::renameFile(const FilePath &target) const
|
||||
{
|
||||
if (isSameDevice(target))
|
||||
return fileAccess()->renameFile(*this, target);
|
||||
|
||||
return copyFile(target).and_then([this, &target] {
|
||||
return removeFile().or_else(
|
||||
[this, &target](const QString &removeError) -> expected_str<void> {
|
||||
// If we fail to remove the source file, we remove the target file to return to the
|
||||
// original state.
|
||||
expected_str<void> rmResult = target.removeFile();
|
||||
QTC_CHECK_EXPECTED(rmResult);
|
||||
return make_unexpected(
|
||||
Tr::tr("Failed to move %1 to %2. Removing the source file failed: %3")
|
||||
.arg(toUserOutput())
|
||||
.arg(target.toUserOutput())
|
||||
.arg(removeError));
|
||||
});
|
||||
});
|
||||
const Result copyResult = copyFile(target);
|
||||
if (!copyResult)
|
||||
return copyResult;
|
||||
|
||||
const Result removeResult = removeFile();
|
||||
if (removeResult)
|
||||
return Result::Ok;
|
||||
|
||||
// If we fail to remove the source file, we remove the target file to return to the
|
||||
// original state.
|
||||
Result rmResult = target.removeFile();
|
||||
QTC_CHECK_EXPECTED(rmResult);
|
||||
return Result::Error(
|
||||
Tr::tr("Failed to move %1 to %2. Removing the source file failed: %3")
|
||||
.arg(toUserOutput())
|
||||
.arg(target.toUserOutput())
|
||||
.arg(rmResult.error()));
|
||||
}
|
||||
|
||||
qint64 FilePath::fileSize() const
|
||||
|
@@ -152,7 +152,7 @@ public:
|
||||
|
||||
bool isWritableDir() const;
|
||||
bool isWritableFile() const;
|
||||
expected_str<void> ensureWritableDir() const;
|
||||
Result ensureWritableDir() const;
|
||||
bool ensureExistingFile() const;
|
||||
bool isExecutableFile() const;
|
||||
bool isReadableFile() const;
|
||||
@@ -170,11 +170,11 @@ public:
|
||||
QFile::Permissions permissions() const;
|
||||
bool setPermissions(QFile::Permissions permissions) const;
|
||||
OsType osType() const;
|
||||
expected_str<void> removeFile() const;
|
||||
Result removeFile() const;
|
||||
bool removeRecursively(QString *error = nullptr) const;
|
||||
expected_str<void> copyRecursively(const FilePath &target) const;
|
||||
expected_str<void> copyFile(const FilePath &target) const;
|
||||
expected_str<void> renameFile(const FilePath &target) const;
|
||||
Result copyRecursively(const FilePath &target) const;
|
||||
Result copyFile(const FilePath &target) const;
|
||||
Result renameFile(const FilePath &target) const;
|
||||
qint64 fileSize() const;
|
||||
qint64 bytesAvailable() const;
|
||||
bool createDir() const;
|
||||
|
@@ -735,7 +735,7 @@ bool FileUtils::copyIfDifferent(const FilePath &srcFilePath, const FilePath &tgt
|
||||
tgtFilePath.removeFile();
|
||||
}
|
||||
|
||||
const expected_str<void> copyResult = srcFilePath.copyFile(tgtFilePath);
|
||||
const Result copyResult = srcFilePath.copyFile(tgtFilePath);
|
||||
|
||||
// TODO forward error to caller instead of assert, since IO errors can always be expected
|
||||
QTC_ASSERT_EXPECTED(copyResult, return false);
|
||||
|
@@ -220,18 +220,18 @@ bool FSEngineImpl::remove()
|
||||
|
||||
bool FSEngineImpl::copy(const QString &newName)
|
||||
{
|
||||
expected_str<void> result = m_filePath.copyFile(FilePath::fromString(newName));
|
||||
Result result = m_filePath.copyFile(FilePath::fromString(newName));
|
||||
if (!result)
|
||||
setError(QFile::CopyError, result.error());
|
||||
return result.has_value();
|
||||
return bool(result);
|
||||
}
|
||||
|
||||
bool FSEngineImpl::rename(const QString &newName)
|
||||
{
|
||||
auto result = m_filePath.renameFile(FilePath::fromString(newName));
|
||||
Result result = m_filePath.renameFile(FilePath::fromString(newName));
|
||||
if (!result)
|
||||
setError(QFile::RenameError, result.error());
|
||||
return result.has_value();
|
||||
return bool(result);
|
||||
}
|
||||
|
||||
bool FSEngineImpl::renameOverwrite(const QString &newName)
|
||||
|
@@ -740,6 +740,26 @@ void Widget::show()
|
||||
access(this)->show();
|
||||
}
|
||||
|
||||
bool Widget::isVisible() const
|
||||
{
|
||||
return access(this)->isVisible();
|
||||
}
|
||||
|
||||
bool Widget::isEnabled() const
|
||||
{
|
||||
return access(this)->isEnabled();
|
||||
}
|
||||
|
||||
void Widget::setVisible(bool visible)
|
||||
{
|
||||
access(this)-> setVisible(visible);
|
||||
}
|
||||
|
||||
void Widget::setEnabled(bool enabled)
|
||||
{
|
||||
access(this)->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void Widget::setNoMargins(int)
|
||||
{
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
|
@@ -231,6 +231,12 @@ public:
|
||||
QWidget *emerge() const;
|
||||
void show();
|
||||
|
||||
bool isVisible() const;
|
||||
bool isEnabled() const;
|
||||
|
||||
void setVisible(bool);
|
||||
void setEnabled(bool);
|
||||
|
||||
void setAutoFillBackground(bool);
|
||||
void setLayout(const Layout &layout);
|
||||
void setSize(int, int);
|
||||
|
@@ -197,7 +197,7 @@ bool SaveFile::commit()
|
||||
}
|
||||
}
|
||||
|
||||
expected_str<void> renameResult = m_tempFile->filePath().renameFile(finalFileName);
|
||||
Result renameResult = m_tempFile->filePath().renameFile(finalFileName);
|
||||
if (!renameResult) {
|
||||
// The case when someone else was able to create finalFileName after we've renamed it.
|
||||
// Higher level call may try to save this file again but here we do nothing and
|
||||
|
@@ -176,6 +176,10 @@ QColor StyleHelper::borderColor(bool lightColored)
|
||||
|
||||
QColor StyleHelper::toolBarBorderColor()
|
||||
{
|
||||
if (const QColor sepColor = creatorColor(Theme::FancyToolBarSeparatorColor);
|
||||
sepColor == creatorColor(Theme::SplitterColor))
|
||||
return sepColor; // QTCREATORBUG-31682: Unify all separating line colors if two are the same
|
||||
|
||||
const QColor base = baseColor();
|
||||
return QColor::fromHsv(base.hue(),
|
||||
base.saturation() ,
|
||||
|
@@ -27,7 +27,6 @@ add_qtc_plugin(Android
|
||||
androidqmltoolingsupport.cpp androidqmltoolingsupport.h
|
||||
androidqtversion.cpp androidqtversion.h
|
||||
androidrunconfiguration.cpp androidrunconfiguration.h
|
||||
androidruncontrol.cpp androidruncontrol.h
|
||||
androidrunner.cpp androidrunner.h
|
||||
androidrunnerworker.cpp androidrunnerworker.h
|
||||
androidsdkdownloader.cpp androidsdkdownloader.h
|
||||
|
@@ -55,8 +55,6 @@ QtcPlugin {
|
||||
"androidqtversion.h",
|
||||
"androidrunconfiguration.cpp",
|
||||
"androidrunconfiguration.h",
|
||||
"androidruncontrol.cpp",
|
||||
"androidruncontrol.h",
|
||||
"androidrunner.cpp",
|
||||
"androidrunner.h",
|
||||
"androidrunnerworker.cpp",
|
||||
|
@@ -679,7 +679,7 @@ static bool copyFileIfNewer(const FilePath &sourceFilePath,
|
||||
|
||||
if (!destinationFilePath.parentDir().ensureWritableDir())
|
||||
return false;
|
||||
expected_str<void> result = sourceFilePath.copyFile(destinationFilePath);
|
||||
Result result = sourceFilePath.copyFile(destinationFilePath);
|
||||
QTC_ASSERT_EXPECTED(result, return false);
|
||||
return true;
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@
|
||||
#include "androidqmltoolingsupport.h"
|
||||
#include "androidqtversion.h"
|
||||
#include "androidrunconfiguration.h"
|
||||
#include "androidruncontrol.h"
|
||||
#include "androidrunner.h"
|
||||
#include "androidsettingswidget.h"
|
||||
#include "androidtoolchain.h"
|
||||
#include "androidtr.h"
|
||||
|
@@ -100,7 +100,7 @@ class AndroidRunConfigurationFactory : public RunConfigurationFactory
|
||||
public:
|
||||
AndroidRunConfigurationFactory()
|
||||
{
|
||||
registerRunConfiguration<AndroidRunConfiguration>("Qt4ProjectManager.AndroidRunConfiguration:");
|
||||
registerRunConfiguration<AndroidRunConfiguration>(Android::Constants::ANDROID_RUNCONFIG_ID);
|
||||
addSupportedTargetDeviceType(Android::Constants::ANDROID_DEVICE_TYPE);
|
||||
}
|
||||
};
|
||||
|
@@ -1,53 +0,0 @@
|
||||
// Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "androidruncontrol.h"
|
||||
|
||||
#include "androidconstants.h"
|
||||
#include "androidglobal.h"
|
||||
#include "androidrunconfiguration.h"
|
||||
#include "androidrunner.h"
|
||||
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace Android::Internal {
|
||||
|
||||
class AndroidRunSupport final : public AndroidRunner
|
||||
{
|
||||
public:
|
||||
explicit AndroidRunSupport(RunControl *runControl);
|
||||
~AndroidRunSupport() override;
|
||||
};
|
||||
|
||||
AndroidRunSupport::AndroidRunSupport(RunControl *runControl)
|
||||
: AndroidRunner(runControl)
|
||||
{
|
||||
runControl->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR);
|
||||
}
|
||||
|
||||
AndroidRunSupport::~AndroidRunSupport()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
class AndroidRunWorkerFactory final : public RunWorkerFactory
|
||||
{
|
||||
public:
|
||||
AndroidRunWorkerFactory()
|
||||
{
|
||||
setProduct<AndroidRunSupport>();
|
||||
addSupportedRunMode(ProjectExplorer::Constants::NORMAL_RUN_MODE);
|
||||
addSupportedRunConfig(Constants::ANDROID_RUNCONFIG_ID);
|
||||
}
|
||||
};
|
||||
|
||||
void setupAndroidRunWorker()
|
||||
{
|
||||
static AndroidRunWorkerFactory theAndroidRunWorkerFactory;
|
||||
}
|
||||
|
||||
} // Android::Internal
|
@@ -1,10 +0,0 @@
|
||||
// Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Android::Internal {
|
||||
|
||||
void setupAndroidRunWorker();
|
||||
|
||||
} // Android::Internal
|
@@ -5,6 +5,7 @@
|
||||
#include "androidrunner.h"
|
||||
|
||||
#include "androidavdmanager.h"
|
||||
#include "androidconstants.h"
|
||||
#include "androiddevice.h"
|
||||
#include "androidmanager.h"
|
||||
#include "androidrunnerworker.h"
|
||||
@@ -12,8 +13,11 @@
|
||||
|
||||
#include <projectexplorer/projectexplorersettings.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <qtsupport/qtkitaspect.h>
|
||||
|
||||
#include <utils/url.h>
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
#include <QHostAddress>
|
||||
#include <QLoggingCategory>
|
||||
@@ -31,6 +35,7 @@ namespace Android::Internal {
|
||||
AndroidRunner::AndroidRunner(RunControl *runControl)
|
||||
: RunWorker(runControl)
|
||||
{
|
||||
runControl->setIcon(Utils::Icons::RUN_SMALL_TOOLBAR);
|
||||
setId("AndroidRunner");
|
||||
static const int metaTypes[] = {
|
||||
qRegisterMetaType<QList<QStringList>>("QList<QStringList>"),
|
||||
@@ -101,7 +106,6 @@ void AndroidRunner::start()
|
||||
runnerRecipe(glueStorage)
|
||||
};
|
||||
m_taskTreeRunner.start(recipe);
|
||||
m_packageName = AndroidManager::packageName(target);
|
||||
}
|
||||
|
||||
void AndroidRunner::stop()
|
||||
@@ -110,8 +114,6 @@ void AndroidRunner::stop()
|
||||
return;
|
||||
|
||||
emit canceled();
|
||||
appendMessage(Tr::tr("Android target \"%1\" terminated.").arg(m_packageName),
|
||||
Utils::NormalMessageFormat);
|
||||
}
|
||||
|
||||
void AndroidRunner::qmlServerPortReady(Port port)
|
||||
@@ -155,4 +157,20 @@ void AndroidRunner::remoteStdErr(const QString &output)
|
||||
m_outputParser.processOutput(output);
|
||||
}
|
||||
|
||||
class AndroidRunWorkerFactory final : public RunWorkerFactory
|
||||
{
|
||||
public:
|
||||
AndroidRunWorkerFactory()
|
||||
{
|
||||
setProduct<AndroidRunner>();
|
||||
addSupportedRunMode(ProjectExplorer::Constants::NORMAL_RUN_MODE);
|
||||
addSupportedRunConfig(Constants::ANDROID_RUNCONFIG_ID);
|
||||
}
|
||||
};
|
||||
|
||||
void setupAndroidRunWorker()
|
||||
{
|
||||
static AndroidRunWorkerFactory theAndroidRunWorkerFactory;
|
||||
}
|
||||
|
||||
} // namespace Android::Internal
|
||||
|
@@ -46,7 +46,8 @@ private:
|
||||
Utils::ProcessHandle m_pid;
|
||||
QmlDebug::QmlOutputParser m_outputParser;
|
||||
Tasking::TaskTreeRunner m_taskTreeRunner;
|
||||
QString m_packageName;
|
||||
};
|
||||
|
||||
void setupAndroidRunWorker();
|
||||
|
||||
} // namespace Android::Internal
|
||||
|
@@ -581,10 +581,11 @@ static ExecutableItem postDoneRecipe(const Storage<RunnerStorage> &storage)
|
||||
const auto onDone = [storage] {
|
||||
storage->m_processPID = -1;
|
||||
storage->m_processUser = -1;
|
||||
if (!storage->m_glue->wasCancelled()) {
|
||||
storage->m_glue->setFinished(Tr::tr("Android target \"%1\" died.")
|
||||
.arg(storage->m_packageName));
|
||||
}
|
||||
const QString package = storage->m_packageName;
|
||||
const QString message = storage->m_glue->wasCancelled()
|
||||
? Tr::tr("Android target \"%1\" terminated.").arg(package)
|
||||
: Tr::tr("Android target \"%1\" died.").arg(package);
|
||||
storage->m_glue->setFinished(message);
|
||||
};
|
||||
|
||||
return Group {
|
||||
|
@@ -1,99 +1,73 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "androidconfigurations.h"
|
||||
#include "androidsignaloperation.h"
|
||||
|
||||
#include "androidconfigurations.h"
|
||||
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
namespace Android::Internal {
|
||||
|
||||
AndroidSignalOperation::AndroidSignalOperation()
|
||||
: m_adbPath(AndroidConfig::adbToolPath())
|
||||
, m_timeout(new QTimer(this))
|
||||
{
|
||||
m_timeout->setInterval(5000);
|
||||
connect(m_timeout, &QTimer::timeout, this, &AndroidSignalOperation::handleTimeout);
|
||||
}
|
||||
|
||||
AndroidSignalOperation::~AndroidSignalOperation() = default;
|
||||
|
||||
bool AndroidSignalOperation::handleCrashMessage()
|
||||
{
|
||||
if (m_adbProcess->exitStatus() == QProcess::NormalExit)
|
||||
return false;
|
||||
m_errorMessage = QLatin1String(" adb process exit code: ") + QString::number(m_adbProcess->exitCode());
|
||||
const QString adbError = m_adbProcess->errorString();
|
||||
if (!adbError.isEmpty())
|
||||
m_errorMessage += QLatin1String(" adb process error: ") + adbError;
|
||||
return true;
|
||||
}
|
||||
|
||||
void AndroidSignalOperation::adbFindRunAsFinished()
|
||||
{
|
||||
QTC_ASSERT(m_state == RunAs, return);
|
||||
m_timeout->stop();
|
||||
|
||||
handleCrashMessage();
|
||||
const QString runAs = QString::fromLatin1(m_adbProcess->readAllRawStandardOutput());
|
||||
m_adbProcess.release()->deleteLater();
|
||||
if (runAs.isEmpty() || !m_errorMessage.isEmpty()) {
|
||||
m_errorMessage.prepend(QLatin1String("Cannot find User for process: ")
|
||||
+ QString::number(m_pid));
|
||||
m_state = Idle;
|
||||
emit finished(m_errorMessage);
|
||||
} else {
|
||||
startAdbProcess(Kill, {m_adbPath, {"shell", "run-as", runAs, "kill",
|
||||
QString("-%1").arg(m_signal), QString::number(m_pid)}},
|
||||
[this] { adbKillFinished(); });
|
||||
}
|
||||
}
|
||||
|
||||
void AndroidSignalOperation::adbKillFinished()
|
||||
{
|
||||
QTC_ASSERT(m_state == Kill, return);
|
||||
m_timeout->stop();
|
||||
|
||||
if (!handleCrashMessage())
|
||||
m_errorMessage = QString::fromLatin1(m_adbProcess->readAllRawStandardError());
|
||||
m_adbProcess.release()->deleteLater();
|
||||
if (!m_errorMessage.isEmpty())
|
||||
m_errorMessage.prepend(QLatin1String("Cannot kill process: ") + QString::number(m_pid));
|
||||
m_state = Idle;
|
||||
emit finished(m_errorMessage);
|
||||
}
|
||||
|
||||
void AndroidSignalOperation::handleTimeout()
|
||||
{
|
||||
m_adbProcess.reset();
|
||||
m_timeout->stop();
|
||||
m_state = Idle;
|
||||
m_errorMessage = QLatin1String("adb process timed out");
|
||||
emit finished(m_errorMessage);
|
||||
}
|
||||
AndroidSignalOperation::AndroidSignalOperation() = default;
|
||||
|
||||
void AndroidSignalOperation::signalOperationViaADB(qint64 pid, int signal)
|
||||
{
|
||||
QTC_ASSERT(m_state == Idle, return);
|
||||
m_pid = pid;
|
||||
m_signal = signal;
|
||||
startAdbProcess(RunAs, {m_adbPath, {"shell", "cat", QString("/proc/%1/cmdline").arg(m_pid)}},
|
||||
[this] { adbFindRunAsFinished(); });
|
||||
}
|
||||
struct InternalStorage {
|
||||
FilePath adbPath;
|
||||
QString runAs = {};
|
||||
QString errorMessage = {};
|
||||
};
|
||||
|
||||
void AndroidSignalOperation::startAdbProcess(State state, const Utils::CommandLine &commandLine,
|
||||
FinishHandler handler)
|
||||
{
|
||||
m_state = state;
|
||||
m_timeout->start();
|
||||
m_adbProcess.reset(new Process);
|
||||
connect(m_adbProcess.get(), &Process::done, this, handler);
|
||||
m_adbProcess->setCommand(commandLine);
|
||||
m_adbProcess->start();
|
||||
const Storage<InternalStorage> storage({AndroidConfig::adbToolPath()});
|
||||
|
||||
const auto onCatSetup = [storage, pid](Process &process) {
|
||||
process.setCommand({storage->adbPath, {"shell", "cat", QString("/proc/%1/cmdline").arg(pid)}});
|
||||
};
|
||||
const auto onCatDone = [storage, pid](const Process &process, DoneWith result) {
|
||||
if (result == DoneWith::Success) {
|
||||
storage->runAs = process.stdOut();
|
||||
if (!storage->runAs.isEmpty())
|
||||
return true;
|
||||
storage->errorMessage = QLatin1String("Cannot find User for process: ")
|
||||
+ QString::number(pid);
|
||||
} else if (result == DoneWith::Error) {
|
||||
storage->errorMessage = QLatin1String(" adb process exit code: ")
|
||||
+ QString::number(process.exitCode());
|
||||
const QString adbError = process.errorString();
|
||||
if (!adbError.isEmpty())
|
||||
storage->errorMessage += QLatin1String(" adb process error: ") + adbError;
|
||||
} else {
|
||||
storage->errorMessage = QLatin1String("adb process timed out");
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const auto onKillSetup = [storage, pid, signal](Process &process) {
|
||||
process.setCommand({storage->adbPath, {"shell", "run-as", storage->runAs, "kill",
|
||||
QString("-%1").arg(signal), QString::number(pid)}});
|
||||
};
|
||||
const auto onKillDone = [storage, pid](const Process &process, DoneWith result) {
|
||||
if (result == DoneWith::Error) {
|
||||
storage->errorMessage = QLatin1String("Cannot kill process: ") + QString::number(pid)
|
||||
+ process.stdErr();
|
||||
} else if (result == DoneWith::Cancel) {
|
||||
storage->errorMessage = QLatin1String("adb process timed out");
|
||||
}
|
||||
};
|
||||
|
||||
const auto onDone = [this, storage] { emit finished(storage->errorMessage); };
|
||||
|
||||
const Group recipe {
|
||||
ProcessTask(onCatSetup, onCatDone).withTimeout(5s),
|
||||
ProcessTask(onKillSetup, onKillDone).withTimeout(5s),
|
||||
onGroupDone(onDone)
|
||||
};
|
||||
m_taskTreeRunner.start(recipe);
|
||||
}
|
||||
|
||||
void AndroidSignalOperation::killProcess(qint64 pid)
|
||||
@@ -114,5 +88,4 @@ void AndroidSignalOperation::interruptProcess(qint64 pid)
|
||||
signalOperationViaADB(pid, 2);
|
||||
}
|
||||
|
||||
} // Internal
|
||||
} // Android
|
||||
} // namespace Android::Internal
|
||||
|
@@ -5,16 +5,13 @@
|
||||
|
||||
#include <projectexplorer/devicesupport/idevice.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <solutions/tasking/tasktreerunner.h>
|
||||
|
||||
namespace Android {
|
||||
namespace Internal {
|
||||
namespace Android::Internal {
|
||||
|
||||
class AndroidSignalOperation : public ProjectExplorer::DeviceProcessSignalOperation
|
||||
{
|
||||
public:
|
||||
~AndroidSignalOperation() override;
|
||||
void killProcess(qint64 pid) override;
|
||||
void killProcess(const QString &filePath) override;
|
||||
void interruptProcess(qint64 pid) override;
|
||||
@@ -23,32 +20,11 @@ protected:
|
||||
explicit AndroidSignalOperation();
|
||||
|
||||
private:
|
||||
enum State {
|
||||
Idle,
|
||||
RunAs,
|
||||
Kill
|
||||
};
|
||||
|
||||
using FinishHandler = std::function<void()>;
|
||||
|
||||
bool handleCrashMessage();
|
||||
void adbFindRunAsFinished();
|
||||
void adbKillFinished();
|
||||
void handleTimeout();
|
||||
|
||||
void signalOperationViaADB(qint64 pid, int signal);
|
||||
void startAdbProcess(State state, const Utils::CommandLine &commandLine, FinishHandler handler);
|
||||
|
||||
Utils::FilePath m_adbPath;
|
||||
std::unique_ptr<Utils::Process> m_adbProcess;
|
||||
QTimer *m_timeout;
|
||||
|
||||
State m_state = Idle;
|
||||
qint64 m_pid = 0;
|
||||
int m_signal = 0;
|
||||
Tasking::TaskTreeRunner m_taskTreeRunner;
|
||||
|
||||
friend class AndroidDevice;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Android
|
||||
} // namespace Android::Internal
|
||||
|
@@ -329,14 +329,36 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
// ------------------------- NullDataProvider --------------------------------
|
||||
|
||||
class NullDataProvider : public IDataProvider
|
||||
{
|
||||
public:
|
||||
NullDataProvider(qint64 pid, QObject *parent = nullptr)
|
||||
: IDataProvider(pid, parent)
|
||||
{}
|
||||
|
||||
double getCpuConsumption()
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double getMemoryConsumption()
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
|
||||
IDataProvider *createDataProvider(qint64 pid)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return new WindowsDataProvider(pid);
|
||||
#elif defined(Q_OS_MACOS)
|
||||
return new MacDataProvider(pid);
|
||||
#else // Q_OS_LINUX
|
||||
#elif defined(Q_OS_LINUX)
|
||||
return new LinuxDataProvider(pid);
|
||||
#else
|
||||
return new NullDataProvider(pid);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -15,34 +15,35 @@
|
||||
|
||||
#include <solutions/tasking/tasktree.h>
|
||||
|
||||
using namespace Core;
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Autotest::Internal {
|
||||
|
||||
static void linkAcceptor(const Utils::Link &link)
|
||||
static void linkAcceptor(const Link &link)
|
||||
{
|
||||
if (link.hasValidTarget())
|
||||
Core::EditorManager::openEditorAt(link);
|
||||
EditorManager::openEditorAt(link);
|
||||
}
|
||||
|
||||
using LinkAcceptor = std::function<void(const Utils::Link &)>;
|
||||
using LinkAcceptor = std::function<void(const Link &)>;
|
||||
|
||||
static Core::LocatorMatcherTasks dataTagMatchers(const LinkAcceptor &acceptor)
|
||||
static LocatorMatcherTasks dataTagMatchers(const LinkAcceptor &acceptor)
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<Core::LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage, acceptor] {
|
||||
const QString input = storage->input();
|
||||
const auto onSetup = [acceptor] {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
const QString input = storage.input();
|
||||
const TestTreeItem *qtTestRoot = theQtTestFramework().rootNode();
|
||||
if (!qtTestRoot)
|
||||
return;
|
||||
|
||||
Core::LocatorFilterEntries entries;
|
||||
LocatorFilterEntries entries;
|
||||
qtTestRoot->forAllChildItems([&entries, &input, acceptor = acceptor](TestTreeItem *it) {
|
||||
if (it->type() != TestTreeItem::TestDataTag)
|
||||
return;
|
||||
if (it->name().contains(input)) {
|
||||
Core::LocatorFilterEntry entry;
|
||||
LocatorFilterEntry entry;
|
||||
entry.displayName = it->data(0, Qt::DisplayRole).toString();
|
||||
{
|
||||
const TestTreeItem *parent = it->parentItem();
|
||||
@@ -52,18 +53,18 @@ static Core::LocatorMatcherTasks dataTagMatchers(const LinkAcceptor &acceptor)
|
||||
entry.displayExtra = grandParent->name() + "::" + parent->name();
|
||||
}
|
||||
}
|
||||
entry.linkForEditor = std::make_optional(it->data(0, LinkRole).value<Utils::Link>());
|
||||
entry.linkForEditor = std::make_optional(it->data(0, LinkRole).value<Link>());
|
||||
entry.acceptor = [link = entry.linkForEditor, acceptor = acceptor] {
|
||||
if (link)
|
||||
acceptor(*link);
|
||||
return Core::AcceptResult();
|
||||
return AcceptResult();
|
||||
};
|
||||
entries.append(entry);
|
||||
}
|
||||
});
|
||||
storage->reportOutput(entries);
|
||||
storage.reportOutput(entries);
|
||||
};
|
||||
return {{Sync(onSetup), storage}};
|
||||
return {Sync(onSetup)};
|
||||
}
|
||||
|
||||
DataTagLocatorFilter::DataTagLocatorFilter()
|
||||
@@ -79,7 +80,7 @@ DataTagLocatorFilter::DataTagLocatorFilter()
|
||||
setEnabled(ProjectManager::startupProject());
|
||||
}
|
||||
|
||||
Core::LocatorMatcherTasks DataTagLocatorFilter::matchers()
|
||||
LocatorMatcherTasks DataTagLocatorFilter::matchers()
|
||||
{
|
||||
return dataTagMatchers(&linkAcceptor);
|
||||
}
|
||||
|
@@ -1,14 +1,13 @@
|
||||
add_qtc_plugin(Axivion
|
||||
PLUGIN_DEPENDS
|
||||
Core Debugger ProjectExplorer TextEditor
|
||||
DEPENDS Qt::Network Qt::Widgets ExtensionSystem Utils qtkeychain
|
||||
DEPENDS Qt::Network Qt::Widgets ExtensionSystem Utils
|
||||
SOURCES
|
||||
axivion.qrc
|
||||
axivionperspective.cpp axivionperspective.h
|
||||
axivionplugin.cpp axivionplugin.h
|
||||
axivionsettings.cpp axivionsettings.h
|
||||
axiviontr.h
|
||||
credentialquery.h credentialquery.cpp
|
||||
dashboard/dto.cpp dashboard/dto.h
|
||||
dashboard/concat.cpp dashboard/concat.h
|
||||
dashboard/error.h dashboard/error.cpp
|
||||
|
@@ -9,7 +9,6 @@ QtcPlugin {
|
||||
Depends { name: "ProjectExplorer" }
|
||||
Depends { name: "TextEditor" }
|
||||
Depends { name: "Utils" }
|
||||
Depends { name: "qtkeychain" }
|
||||
Depends { name: "Qt.widgets" }
|
||||
Depends { name: "Qt.network" }
|
||||
|
||||
@@ -22,8 +21,6 @@ QtcPlugin {
|
||||
"axivionsettings.cpp",
|
||||
"axivionsettings.h",
|
||||
"axiviontr.h",
|
||||
"credentialquery.cpp",
|
||||
"credentialquery.h",
|
||||
"dynamiclistmodel.cpp",
|
||||
"dynamiclistmodel.h",
|
||||
"issueheaderview.cpp",
|
||||
|
@@ -6,10 +6,10 @@
|
||||
#include "axivionperspective.h"
|
||||
#include "axivionsettings.h"
|
||||
#include "axiviontr.h"
|
||||
#include "credentialquery.h"
|
||||
#include "dashboard/dto.h"
|
||||
#include "dashboard/error.h"
|
||||
|
||||
#include <coreplugin/credentialquery.h>
|
||||
#include <coreplugin/editormanager/documentmodel.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
@@ -269,7 +269,7 @@ const QList<PathMapping> AxivionSettings::validPathMappings() const
|
||||
static bool hostValid(const QString &host)
|
||||
{
|
||||
static const QRegularExpression ip(R"(^(\d+).(\d+).(\d+).(\d+)$)");
|
||||
static const QRegularExpression dn(R"(^([a-zA-Z0-9][a-zA-Z0-9-]+\.)+[a-zA-Z0-9][a-zA-Z0-9-]+$)");
|
||||
static const QRegularExpression dn(R"(^([a-zA-Z0-9][a-zA-Z0-9-]+\.)*[a-zA-Z0-9][a-zA-Z0-9-]+$)");
|
||||
const QRegularExpressionMatch match = ip.match(host);
|
||||
if (match.hasMatch()) {
|
||||
for (int i = 1; i < 5; ++i) {
|
||||
@@ -279,7 +279,7 @@ static bool hostValid(const QString &host)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return (host == "localhost") || dn.match(host).hasMatch();
|
||||
return dn.match(host).hasMatch();
|
||||
}
|
||||
|
||||
static bool isUrlValid(const QString &in)
|
||||
@@ -388,17 +388,17 @@ AxivionSettingsWidget::AxivionSettingsWidget()
|
||||
auto addButton = new QPushButton(Tr::tr("Add..."), this);
|
||||
m_edit = new QPushButton(Tr::tr("Edit..."), this);
|
||||
m_remove = new QPushButton(Tr::tr("Remove"), this);
|
||||
Column{
|
||||
Row{
|
||||
Form{Tr::tr("Default dashboard server:"), m_dashboardServers, br},
|
||||
Column {
|
||||
Row {
|
||||
Form { Tr::tr("Default dashboard server:"), m_dashboardServers, br },
|
||||
st,
|
||||
Column{addButton, m_edit, st, m_remove},
|
||||
Column { addButton, m_edit, st, m_remove },
|
||||
},
|
||||
Space(10),
|
||||
br,
|
||||
Row{settings().highlightMarks},
|
||||
st}
|
||||
.attachTo(this);
|
||||
Row {settings().highlightMarks },
|
||||
st
|
||||
}.attachTo(this);
|
||||
|
||||
connect(addButton, &QPushButton::clicked, this, [this] {
|
||||
// add an empty item unconditionally
|
||||
|
@@ -150,7 +150,7 @@ AbstractSettings::AbstractSettings(const QString &name, const QString &ending)
|
||||
command.setSettingsKey("command");
|
||||
command.setExpectedKind(PathChooser::ExistingCommand);
|
||||
command.setCommandVersionArguments({"--version"});
|
||||
command.setPromptDialogTitle(BeautifierTool::msgCommandPromptDialogTitle("Clang Format"));
|
||||
command.setPromptDialogTitle(BeautifierTool::msgCommandPromptDialogTitle("ClangFormat"));
|
||||
command.setValidatePlaceHolder(true);
|
||||
command.addOnChanged(this, [this] { m_version = {}; version(); });
|
||||
|
||||
|
@@ -54,8 +54,8 @@ public:
|
||||
: AbstractSettings(SETTINGS_NAME, ".clang-format")
|
||||
{
|
||||
command.setDefaultValue("clang-format");
|
||||
command.setPromptDialogTitle(BeautifierTool::msgCommandPromptDialogTitle("Clang Format"));
|
||||
command.setLabelText(Tr::tr("Clang Format command:"));
|
||||
command.setPromptDialogTitle(BeautifierTool::msgCommandPromptDialogTitle("ClangFormat"));
|
||||
command.setLabelText(Tr::tr("ClangFormat command:"));
|
||||
|
||||
usePredefinedStyle.setSettingsKey("usePredefinedStyle");
|
||||
usePredefinedStyle.setDefaultValue(true);
|
||||
@@ -530,7 +530,7 @@ public:
|
||||
ClangFormatSettingsPage()
|
||||
{
|
||||
setId("ClangFormat");
|
||||
setDisplayName(Tr::tr("Clang Format"));
|
||||
setDisplayName(Tr::tr("ClangFormat"));
|
||||
setCategory(Constants::OPTION_CATEGORY);
|
||||
setWidgetCreator([] { return new ClangFormatSettingsPageWidget; });
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ using namespace Core;
|
||||
using namespace LanguageClient;
|
||||
using namespace LanguageServerProtocol;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Tasking;
|
||||
using namespace TextEditor;
|
||||
using namespace Utils;
|
||||
|
||||
@@ -171,31 +172,25 @@ static void filterCurrentResults(QPromise<void> &promise, const LocatorStorage &
|
||||
[](const Entry &entry) { return entry.entry; }));
|
||||
}
|
||||
|
||||
static LocatorMatcherTask currentDocumentMatcher()
|
||||
static ExecutableItem currentDocumentMatcher()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
Storage<CurrentDocumentSymbolsData> resultStorage;
|
||||
|
||||
const auto onQuerySetup = [=](CurrentDocumentSymbolsRequest &request) {
|
||||
Q_UNUSED(request)
|
||||
};
|
||||
const auto onQueryDone = [resultStorage](const CurrentDocumentSymbolsRequest &request) {
|
||||
*resultStorage = request.currentDocumentSymbolsData();
|
||||
};
|
||||
|
||||
const auto onFilterSetup = [=](Async<void> &async) {
|
||||
async.setConcurrentCallData(filterCurrentResults, *storage, *resultStorage,
|
||||
const auto onFilterSetup = [resultStorage](Async<void> &async) {
|
||||
async.setConcurrentCallData(filterCurrentResults, *LocatorStorage::storage(), *resultStorage,
|
||||
TextDocument::currentTextDocument()->plainText());
|
||||
};
|
||||
|
||||
const Group root {
|
||||
resultStorage,
|
||||
CurrentDocumentSymbolsRequestTask(onQuerySetup, onQueryDone, CallDoneIf::Success),
|
||||
CurrentDocumentSymbolsRequestTask({}, onQueryDone, CallDoneIf::Success),
|
||||
AsyncTask<void>(onFilterSetup)
|
||||
};
|
||||
return {root, storage};
|
||||
return root;
|
||||
}
|
||||
|
||||
LocatorMatcherTasks ClangdCurrentDocumentFilter::matchers()
|
||||
|
@@ -375,9 +375,11 @@ public:
|
||||
private:
|
||||
void slotImportClicked() final
|
||||
{
|
||||
const FilePath filePath =
|
||||
FileUtils::getOpenFilePath(this, Tr::tr("Import Code Format"), {},
|
||||
Tr::tr("Clang Format (*clang-format*);;All files (*)"));
|
||||
const FilePath filePath = FileUtils::getOpenFilePath(
|
||||
this,
|
||||
Tr::tr("Import Code Format"),
|
||||
{},
|
||||
Tr::tr("ClangFormat (*clang-format*);;All files (*)"));
|
||||
if (!filePath.isEmpty()) {
|
||||
QString name = QInputDialog::getText(
|
||||
this,
|
||||
@@ -407,7 +409,7 @@ private:
|
||||
this,
|
||||
Tr::tr("Export Code Format"),
|
||||
FileUtils::homePath(),
|
||||
Tr::tr("Clang Format (*clang-format*);;All files (*)"));
|
||||
Tr::tr("ClangFormat (*clang-format*);;All files (*)"));
|
||||
if (!filePath.isEmpty()) {
|
||||
FilePath clangFormatFile = filePathToCurrentSettings(currentPreferences);
|
||||
clangFormatFile.copyFile(filePath);
|
||||
|
@@ -1946,7 +1946,7 @@ void CMakeBuildConfiguration::setBuildPresetToBuildSteps(const ProjectExplorer::
|
||||
|
||||
// Leave only the first build step enabled
|
||||
if (i > 0)
|
||||
cbs->setEnabled(false);
|
||||
cbs->setStepEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -187,72 +187,31 @@ class CMakeKitAspectImpl final : public KitAspect
|
||||
{
|
||||
public:
|
||||
CMakeKitAspectImpl(Kit *kit, const KitAspectFactory *factory)
|
||||
: KitAspect(kit, factory), m_comboBox(createSubWidget<QComboBox>())
|
||||
: KitAspect(kit, factory)
|
||||
{
|
||||
setManagingPage(Constants::Settings::TOOLS_ID);
|
||||
m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
|
||||
m_comboBox->setToolTip(factory->description());
|
||||
|
||||
const auto sortModel = new CMakeToolSortModel(this);
|
||||
sortModel->setSourceModel(new CMakeToolListModel(*kit, this));
|
||||
m_comboBox->setModel(sortModel);
|
||||
|
||||
refresh();
|
||||
|
||||
connect(m_comboBox, &QComboBox::currentIndexChanged,
|
||||
this, &CMakeKitAspectImpl::currentCMakeToolChanged);
|
||||
auto getter = [](const Kit &k) { return CMakeKitAspect::cmakeToolId(&k).toSetting(); };
|
||||
auto setter = [](Kit &k, const QVariant &id) {
|
||||
CMakeKitAspect::setCMakeTool(&k, Id::fromSetting(id));
|
||||
};
|
||||
auto resetModel = [](QAbstractItemModel &model) {
|
||||
static_cast<CMakeToolSortModel &>(model).reset();
|
||||
};
|
||||
setListAspectSpec(
|
||||
{sortModel,
|
||||
std::move(getter),
|
||||
std::move(setter),
|
||||
std::move(resetModel),
|
||||
CMakeToolTreeItem::IdRole});
|
||||
|
||||
CMakeToolManager *cmakeMgr = CMakeToolManager::instance();
|
||||
connect(cmakeMgr, &CMakeToolManager::cmakeAdded, this, &CMakeKitAspectImpl::refresh);
|
||||
connect(cmakeMgr, &CMakeToolManager::cmakeRemoved, this, &CMakeKitAspectImpl::refresh);
|
||||
connect(cmakeMgr, &CMakeToolManager::cmakeUpdated, this, &CMakeKitAspectImpl::refresh);
|
||||
}
|
||||
|
||||
~CMakeKitAspectImpl() override
|
||||
{
|
||||
delete m_comboBox;
|
||||
}
|
||||
|
||||
private:
|
||||
// KitAspectWidget interface
|
||||
void makeReadOnly() override { m_comboBox->setEnabled(false); }
|
||||
|
||||
void addToInnerLayout(Layouting::Layout &builder) override
|
||||
{
|
||||
addMutableAction(m_comboBox);
|
||||
builder.addItem(m_comboBox);
|
||||
}
|
||||
|
||||
void refresh() override
|
||||
{
|
||||
const GuardLocker locker(m_ignoreChanges);
|
||||
|
||||
const auto sortModel = static_cast<CMakeToolSortModel *>(m_comboBox->model());
|
||||
sortModel->reset();
|
||||
sortModel->sort(0);
|
||||
m_comboBox->setCurrentIndex(indexOf(CMakeKitAspect::cmakeToolId(m_kit)));
|
||||
}
|
||||
|
||||
int indexOf(Id id)
|
||||
{
|
||||
for (int i = 0; i < m_comboBox->count(); ++i) {
|
||||
if (id == Id::fromSetting(m_comboBox->itemData(i, CMakeToolTreeItem::IdRole)))
|
||||
return i;
|
||||
}
|
||||
|
||||
return m_comboBox->count() - 1;
|
||||
}
|
||||
|
||||
void currentCMakeToolChanged(int index)
|
||||
{
|
||||
if (m_ignoreChanges.isLocked())
|
||||
return;
|
||||
|
||||
const Id id = Id::fromSetting(m_comboBox->itemData(index, CMakeToolTreeItem::IdRole));
|
||||
CMakeKitAspect::setCMakeTool(m_kit, id);
|
||||
}
|
||||
|
||||
Guard m_ignoreChanges;
|
||||
QComboBox *m_comboBox;
|
||||
};
|
||||
|
||||
CMakeKitAspectFactory::CMakeKitAspectFactory()
|
||||
@@ -434,7 +393,7 @@ private:
|
||||
|
||||
void refresh() override
|
||||
{
|
||||
CMakeTool *const tool = CMakeKitAspect::cmakeTool(m_kit);
|
||||
CMakeTool *const tool = CMakeKitAspect::cmakeTool(kit());
|
||||
if (tool != m_currentTool)
|
||||
m_currentTool = tool;
|
||||
|
||||
|
@@ -19,6 +19,7 @@
|
||||
|
||||
using namespace Core;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace CMakeProjectManager::Internal {
|
||||
@@ -29,12 +30,9 @@ using BuildAcceptor = std::function<void(const BuildSystem *, const QString &)>;
|
||||
|
||||
static LocatorMatcherTasks cmakeMatchers(const BuildAcceptor &acceptor)
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage, acceptor] {
|
||||
const QString input = storage->input();
|
||||
const auto onSetup = [acceptor] {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
const QString input = storage.input();
|
||||
const QRegularExpression regexp
|
||||
= ILocatorFilter::createRegExp(input, ILocatorFilter::caseSensitivity(input));
|
||||
if (!regexp.isValid())
|
||||
@@ -90,10 +88,10 @@ static LocatorMatcherTasks cmakeMatchers(const BuildAcceptor &acceptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
storage->reportOutput(
|
||||
storage.reportOutput(
|
||||
std::accumulate(std::begin(entries), std::end(entries), LocatorFilterEntries()));
|
||||
};
|
||||
return {{Sync(onSetup), storage}};
|
||||
return {Sync(onSetup)};
|
||||
}
|
||||
|
||||
static void setupFilter(ILocatorFilter *filter)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
add_qtc_plugin(Core
|
||||
DEPENDS Qt::PrintSupport Qt::Qml Qt::Sql Qt::Gui Qt::GuiPrivate TerminalLib
|
||||
DEPENDS Qt::PrintSupport Qt::Qml Qt::Sql Qt::Gui Qt::GuiPrivate TerminalLib qtkeychain
|
||||
PUBLIC_DEPENDS Aggregation ExtensionSystem Utils
|
||||
SOURCES
|
||||
actionmanager/actioncontainer.cpp
|
||||
@@ -29,6 +29,8 @@ add_qtc_plugin(Core
|
||||
coreplugin.cpp
|
||||
coreplugin.h
|
||||
coreplugintr.h
|
||||
credentialquery.cpp
|
||||
credentialquery.h
|
||||
designmode.cpp
|
||||
designmode.h
|
||||
dialogs/addtovcsdialog.cpp
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <QtConcurrent>
|
||||
#include <QTextDocument>
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
static const char lastTriggeredC[] = "LastTriggeredActions";
|
||||
@@ -174,11 +175,7 @@ static void matches(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
|
||||
LocatorMatcherTasks ActionsFilter::matchers()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [this, storage](Async<void> &async) {
|
||||
const auto onSetup = [this](Async<void> &async) {
|
||||
m_entries.clear();
|
||||
m_indexes.clear();
|
||||
QList<const QMenu *> processedMenus;
|
||||
@@ -186,15 +183,16 @@ LocatorMatcherTasks ActionsFilter::matchers()
|
||||
for (QAction* action : menuBarActions())
|
||||
collectEntriesForAction(action, {}, processedMenus);
|
||||
collectEntriesForCommands();
|
||||
if (storage->input().simplified().isEmpty()) {
|
||||
storage->reportOutput(m_entries);
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
if (storage.input().simplified().isEmpty()) {
|
||||
storage.reportOutput(m_entries);
|
||||
return SetupResult::StopWithSuccess;
|
||||
}
|
||||
async.setConcurrentCallData(matches, *storage, m_entries);
|
||||
async.setConcurrentCallData(matches, storage, m_entries);
|
||||
return SetupResult::Continue;
|
||||
};
|
||||
|
||||
return {{AsyncTask<void>(onSetup), storage}};
|
||||
return {AsyncTask<void>(onSetup)};
|
||||
}
|
||||
|
||||
LocatorFilterEntry::Acceptor ActionsFilter::acceptor(const ActionFilterEntryData &data) const
|
||||
|
@@ -16,6 +16,7 @@ QtcPlugin {
|
||||
Depends { name: "Utils" }
|
||||
Depends { name: "Aggregation" }
|
||||
Depends { name: "TerminalLib" }
|
||||
Depends { name: "qtkeychain" }
|
||||
|
||||
cpp.dynamicLibraries: {
|
||||
if (qbs.targetOS.contains("windows"))
|
||||
@@ -43,6 +44,8 @@ QtcPlugin {
|
||||
"coreplugin.cpp",
|
||||
"coreplugin.h",
|
||||
"coreplugintr.h",
|
||||
"credentialquery.cpp",
|
||||
"credentialquery.h",
|
||||
"designmode.cpp",
|
||||
"designmode.h",
|
||||
"diffservice.cpp",
|
||||
|
@@ -8,7 +8,7 @@
|
||||
using namespace QKeychain;
|
||||
using namespace Tasking;
|
||||
|
||||
namespace Axivion::Internal {
|
||||
namespace Core {
|
||||
|
||||
CredentialQueryTaskAdapter::~CredentialQueryTaskAdapter() = default;
|
||||
|
||||
@@ -51,4 +51,4 @@ void CredentialQueryTaskAdapter::start()
|
||||
job->start();
|
||||
}
|
||||
|
||||
} // Axivion::Internal
|
||||
} // Core
|
@@ -3,13 +3,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core_global.h"
|
||||
|
||||
#include <solutions/tasking/tasktree.h>
|
||||
|
||||
namespace Axivion::Internal {
|
||||
namespace Core {
|
||||
|
||||
enum class CredentialOperation { Get, Set, Delete };
|
||||
|
||||
class CredentialQuery
|
||||
class CORE_EXPORT CredentialQuery
|
||||
{
|
||||
public:
|
||||
void setOperation(CredentialOperation operation) { m_operation = operation; }
|
||||
@@ -30,7 +32,7 @@ private:
|
||||
friend class CredentialQueryTaskAdapter;
|
||||
};
|
||||
|
||||
class CredentialQueryTaskAdapter final : public Tasking::TaskAdapter<CredentialQuery>
|
||||
class CORE_EXPORT CredentialQueryTaskAdapter final : public Tasking::TaskAdapter<CredentialQuery>
|
||||
{
|
||||
private:
|
||||
~CredentialQueryTaskAdapter();
|
||||
@@ -40,4 +42,4 @@ private:
|
||||
|
||||
using CredentialQueryTask = Tasking::CustomTask<CredentialQueryTaskAdapter>;
|
||||
|
||||
} // Axivion::Internal
|
||||
} // Core
|
@@ -42,8 +42,8 @@
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
const int kInitialWidth = 750;
|
||||
const int kInitialHeight = 450;
|
||||
const int kInitialWidth = 800;
|
||||
const int kInitialHeight = 500;
|
||||
const int kMaxMinimumWidth = 250;
|
||||
const int kMaxMinimumHeight = 250;
|
||||
|
||||
|
@@ -187,7 +187,7 @@ bool FileUtils::renameFile(const FilePath &orgFilePath, const FilePath &newFileP
|
||||
if (vc && vc->supportsOperation(IVersionControl::MoveOperation))
|
||||
result = vc->vcsMove(orgFilePath, newFilePath);
|
||||
if (!result) // The moving via vcs failed or the vcs does not support moving, fall back
|
||||
result = orgFilePath.renameFile(newFilePath).has_value();
|
||||
result = bool(orgFilePath.renameFile(newFilePath));
|
||||
if (result) {
|
||||
DocumentManager::renamedFile(orgFilePath, newFilePath);
|
||||
updateHeaderFileGuardIfApplicable(orgFilePath, newFilePath, handleGuards);
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <QAction>
|
||||
#include <QPointer>
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Core {
|
||||
@@ -25,12 +26,9 @@ CommandLocator::CommandLocator(Id id, const QString &displayName, const QString
|
||||
|
||||
LocatorMatcherTasks CommandLocator::matchers()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage, commands = m_commands] {
|
||||
const QString input = storage->input();
|
||||
const auto onSetup = [commands = m_commands] {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
const QString input = storage.input();
|
||||
const Qt::CaseSensitivity inputCaseSensitivity = caseSensitivity(input);
|
||||
LocatorFilterEntries goodEntries;
|
||||
LocatorFilterEntries betterEntries;
|
||||
@@ -63,9 +61,9 @@ LocatorMatcherTasks CommandLocator::matchers()
|
||||
goodEntries.append(entry);
|
||||
}
|
||||
}
|
||||
storage->reportOutput(betterEntries + goodEntries);
|
||||
storage.reportOutput(betterEntries + goodEntries);
|
||||
};
|
||||
return {{Sync(onSetup), storage}};
|
||||
return {Sync(onSetup)};
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <QJsonObject>
|
||||
#include <QMessageBox>
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Core::Internal {
|
||||
@@ -40,12 +41,9 @@ ExecuteFilter::~ExecuteFilter()
|
||||
|
||||
LocatorMatcherTasks ExecuteFilter::matchers()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [this, storage] {
|
||||
const QString input = storage->input();
|
||||
const auto onSetup = [this] {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
const QString input = storage.input();
|
||||
LocatorFilterEntries entries;
|
||||
if (!input.isEmpty()) { // avoid empty entry
|
||||
LocatorFilterEntry entry;
|
||||
@@ -69,9 +67,9 @@ LocatorMatcherTasks ExecuteFilter::matchers()
|
||||
others.append(entry);
|
||||
}
|
||||
}
|
||||
storage->reportOutput(entries + others);
|
||||
storage.reportOutput(entries + others);
|
||||
};
|
||||
return {{Sync(onSetup), storage}};
|
||||
return {Sync(onSetup)};
|
||||
}
|
||||
|
||||
void ExecuteFilter::acceptCommand(const QString &cmd)
|
||||
|
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Tasking;
|
||||
|
||||
namespace Core::Internal {
|
||||
|
||||
ExternalToolsFilter::ExternalToolsFilter()
|
||||
@@ -27,12 +29,9 @@ ExternalToolsFilter::ExternalToolsFilter()
|
||||
|
||||
LocatorMatcherTasks ExternalToolsFilter::matchers()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage] {
|
||||
const QString input = storage->input();
|
||||
const auto onSetup = [] {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
const QString input = storage.input();
|
||||
|
||||
LocatorFilterEntries bestEntries;
|
||||
LocatorFilterEntries betterEntries;
|
||||
@@ -77,10 +76,10 @@ LocatorMatcherTasks ExternalToolsFilter::matchers()
|
||||
return AcceptResult();
|
||||
};
|
||||
|
||||
storage->reportOutput(bestEntries + betterEntries + goodEntries
|
||||
+ LocatorFilterEntries{configEntry});
|
||||
storage.reportOutput(bestEntries + betterEntries + goodEntries
|
||||
+ LocatorFilterEntries{configEntry});
|
||||
};
|
||||
return {{Sync(onSetup), storage}};
|
||||
return {Sync(onSetup)};
|
||||
}
|
||||
|
||||
} // Core::Internal
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <QRegularExpression>
|
||||
#include <QStyle>
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Core::Internal {
|
||||
@@ -304,17 +305,13 @@ static void matches(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
|
||||
LocatorMatcherTasks FileSystemFilter::matchers()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage, includeHidden = m_includeHidden, shortcut = shortcutString()]
|
||||
const auto onSetup = [includeHidden = m_includeHidden, shortcut = shortcutString()]
|
||||
(Async<void> &async) {
|
||||
async.setConcurrentCallData(matches, *storage, shortcut,
|
||||
async.setConcurrentCallData(matches, *LocatorStorage::storage(), shortcut,
|
||||
DocumentManager::fileDialogInitialDirectory(), includeHidden);
|
||||
};
|
||||
|
||||
return {{AsyncTask<void>(onSetup), storage}};
|
||||
return {AsyncTask<void>(onSetup)};
|
||||
}
|
||||
|
||||
class FileSystemFilterOptions : public QDialog
|
||||
|
@@ -291,6 +291,14 @@ void LocatorStorage::reportOutput(const LocatorFilterEntries &outputData) const
|
||||
d->reportOutput(outputData);
|
||||
}
|
||||
|
||||
// Please note the thread_local keyword below guarantees a separate instance per thread.
|
||||
static thread_local Storage<LocatorStorage> s_locatorStorage = {};
|
||||
|
||||
Storage<LocatorStorage> &LocatorStorage::storage()
|
||||
{
|
||||
return s_locatorStorage;
|
||||
}
|
||||
|
||||
void LocatorStorage::finalize() const
|
||||
{
|
||||
QTC_ASSERT(d, return);
|
||||
@@ -366,16 +374,16 @@ void LocatorMatcher::start()
|
||||
|
||||
const auto onTaskTreeSetup = [iterator, input = d->m_input, collectorStorage](TaskTree &taskTree) {
|
||||
const std::shared_ptr<ResultsDeduplicator> deduplicator = collectorStorage->m_deduplicator;
|
||||
const Storage<LocatorStorage> storage = iterator->storage;
|
||||
const auto onSetup = [storage, input, index = iterator.iteration(), deduplicator] {
|
||||
*storage = std::make_shared<LocatorStoragePrivate>(input, index, deduplicator);
|
||||
const auto onSetup = [input, index = iterator.iteration(), deduplicator] {
|
||||
*LocatorStorage::storage()
|
||||
= std::make_shared<LocatorStoragePrivate>(input, index, deduplicator);
|
||||
};
|
||||
taskTree.setRecipe({
|
||||
finishAllAndSuccess,
|
||||
storage,
|
||||
LocatorStorage::storage(),
|
||||
onGroupSetup(onSetup),
|
||||
iterator->task,
|
||||
onGroupDone([storage] { storage->finalize(); })
|
||||
*iterator,
|
||||
onGroupDone([] { LocatorStorage::storage()->finalize(); })
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1357,12 +1365,11 @@ static void filter(QPromise<LocatorFileCachePrivate> &promise, const LocatorStor
|
||||
When this cache started a new search in meantime, the cache was invalidated or even deleted,
|
||||
the update of the cache after a successful run of the task is ignored.
|
||||
*/
|
||||
LocatorMatcherTask LocatorFileCache::matcher() const
|
||||
ExecutableItem LocatorFileCache::matcher() const
|
||||
{
|
||||
Storage<LocatorStorage> storage;
|
||||
std::weak_ptr<LocatorFileCachePrivate> weak = d;
|
||||
|
||||
const auto onSetup = [storage, weak](Async<LocatorFileCachePrivate> &async) {
|
||||
const auto onSetup = [weak](Async<LocatorFileCachePrivate> &async) {
|
||||
auto that = weak.lock();
|
||||
if (!that) // LocatorMatcher is running after *this LocatorFileCache was destructed.
|
||||
return SetupResult::StopWithSuccess;
|
||||
@@ -1372,7 +1379,7 @@ LocatorMatcherTask LocatorFileCache::matcher() const
|
||||
// no provider is set or it returned empty generator
|
||||
that->bumpExecutionId();
|
||||
|
||||
async.setConcurrentCallData(&filter, *storage, *that);
|
||||
async.setConcurrentCallData(&filter, *LocatorStorage::storage(), *that);
|
||||
return SetupResult::Continue;
|
||||
};
|
||||
const auto onDone = [weak](const Async<LocatorFileCachePrivate> &async) {
|
||||
@@ -1392,7 +1399,7 @@ LocatorMatcherTask LocatorFileCache::matcher() const
|
||||
that->update(async.result());
|
||||
};
|
||||
|
||||
return {AsyncTask<LocatorFileCachePrivate>(onSetup, onDone, CallDoneIf::Success), storage};
|
||||
return AsyncTask<LocatorFileCachePrivate>(onSetup, onDone, CallDoneIf::Success);
|
||||
}
|
||||
|
||||
} // Core
|
||||
|
@@ -126,6 +126,8 @@ public:
|
||||
LocatorStorage() = default;
|
||||
QString input() const;
|
||||
void reportOutput(const LocatorFilterEntries &outputData) const;
|
||||
// Only use it from inside the bodies of Task handlers.
|
||||
static Tasking::Storage<LocatorStorage> &storage();
|
||||
|
||||
private:
|
||||
friend class LocatorMatcher;
|
||||
@@ -134,18 +136,7 @@ private:
|
||||
std::shared_ptr<LocatorStoragePrivate> d;
|
||||
};
|
||||
|
||||
class CORE_EXPORT LocatorMatcherTask final
|
||||
{
|
||||
public:
|
||||
// The main task. Initial data (searchTerm) should be taken from storage.input().
|
||||
// Results reporting is done via the storage.reportOutput().
|
||||
Tasking::GroupItem task = Tasking::Group{};
|
||||
|
||||
// When constructing the task, don't place the storage inside the task above.
|
||||
Tasking::Storage<LocatorStorage> storage;
|
||||
};
|
||||
|
||||
using LocatorMatcherTasks = QList<LocatorMatcherTask>;
|
||||
using LocatorMatcherTasks = QList<Tasking::ExecutableItem>;
|
||||
using LocatorMatcherTaskCreator = std::function<LocatorMatcherTasks()>;
|
||||
class LocatorMatcherPrivate;
|
||||
|
||||
@@ -315,7 +306,7 @@ public:
|
||||
std::optional<Utils::FilePaths> filePaths() const;
|
||||
|
||||
static FilePathsGenerator filePathsGenerator(const Utils::FilePaths &filePaths);
|
||||
LocatorMatcherTask matcher() const;
|
||||
Tasking::ExecutableItem matcher() const;
|
||||
|
||||
using MatchedEntries = std::array<LocatorFilterEntries, int(ILocatorFilter::MatchLevel::Count)>;
|
||||
static Utils::FilePaths processFilePaths(const QFuture<void> &future,
|
||||
|
@@ -366,15 +366,15 @@ JavaScriptFilter::~JavaScriptFilter() = default;
|
||||
|
||||
LocatorMatcherTasks JavaScriptFilter::matchers()
|
||||
{
|
||||
Storage<LocatorStorage> storage;
|
||||
if (!m_javaScriptEngine)
|
||||
m_javaScriptEngine.reset(new JavaScriptEngine);
|
||||
QPointer<JavaScriptEngine> engine = m_javaScriptEngine.get();
|
||||
|
||||
const auto onSetup = [storage, engine] {
|
||||
const auto onSetup = [engine] {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
if (!engine)
|
||||
return SetupResult::StopWithError;
|
||||
if (storage->input().trimmed().isEmpty()) {
|
||||
if (storage.input().trimmed().isEmpty()) {
|
||||
LocatorFilterEntry entry;
|
||||
entry.displayName = Tr::tr("Reset Engine");
|
||||
entry.acceptor = [engine] {
|
||||
@@ -385,21 +385,22 @@ LocatorMatcherTasks JavaScriptFilter::matchers()
|
||||
}
|
||||
return AcceptResult();
|
||||
};
|
||||
storage->reportOutput({entry});
|
||||
storage.reportOutput({entry});
|
||||
return SetupResult::StopWithSuccess;
|
||||
}
|
||||
return SetupResult::Continue;
|
||||
};
|
||||
|
||||
const auto onJavaScriptSetup = [storage, engine](JavaScriptRequest &request) {
|
||||
const auto onJavaScriptSetup = [engine](JavaScriptRequest &request) {
|
||||
request.setEngine(engine);
|
||||
request.setEvaluateData(storage->input());
|
||||
request.setEvaluateData(LocatorStorage::storage()->input());
|
||||
};
|
||||
const auto onJavaScriptDone = [storage](const JavaScriptRequest &request, DoneWith result) {
|
||||
const auto onJavaScriptDone = [](const JavaScriptRequest &request, DoneWith result) {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
if (result != DoneWith::Success) {
|
||||
LocatorFilterEntry entry;
|
||||
entry.displayName = request.output().m_output;
|
||||
storage->reportOutput({entry});
|
||||
storage.reportOutput({entry});
|
||||
return;
|
||||
}
|
||||
const auto acceptor = [](const QString &clipboardContents) {
|
||||
@@ -408,7 +409,7 @@ LocatorMatcherTasks JavaScriptFilter::matchers()
|
||||
return AcceptResult();
|
||||
};
|
||||
};
|
||||
const QString input = storage->input();
|
||||
const QString input = storage.input();
|
||||
const QString output = request.output().m_output;
|
||||
const QString expression = input + " = " + output;
|
||||
|
||||
@@ -423,7 +424,7 @@ LocatorMatcherTasks JavaScriptFilter::matchers()
|
||||
copyExpressionEntry.displayName = Tr::tr("Copy to clipboard: %1").arg(expression);
|
||||
copyExpressionEntry.acceptor = acceptor(expression);
|
||||
|
||||
storage->reportOutput({entry, copyResultEntry, copyExpressionEntry});
|
||||
storage.reportOutput({entry, copyResultEntry, copyExpressionEntry});
|
||||
};
|
||||
|
||||
const Group root {
|
||||
@@ -431,7 +432,7 @@ LocatorMatcherTasks JavaScriptFilter::matchers()
|
||||
JavaScriptRequestTask(onJavaScriptSetup, onJavaScriptDone)
|
||||
};
|
||||
|
||||
return {{root, storage}};
|
||||
return {root};
|
||||
}
|
||||
|
||||
} // namespace Core::Internal
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Core::Internal {
|
||||
@@ -26,12 +27,9 @@ LocatorFiltersFilter::LocatorFiltersFilter():
|
||||
|
||||
LocatorMatcherTasks LocatorFiltersFilter::matchers()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage, icon = m_icon] {
|
||||
if (!storage->input().isEmpty())
|
||||
const auto onSetup = [icon = m_icon] {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
if (!storage.input().isEmpty())
|
||||
return;
|
||||
|
||||
QMap<QString, ILocatorFilter *> uniqueFilters;
|
||||
@@ -60,9 +58,9 @@ LocatorMatcherTasks LocatorFiltersFilter::matchers()
|
||||
entries.append(entry);
|
||||
}
|
||||
}
|
||||
storage->reportOutput(entries);
|
||||
storage.reportOutput(entries);
|
||||
};
|
||||
return {{Sync(onSetup), storage}};
|
||||
return {Sync(onSetup)};
|
||||
}
|
||||
|
||||
} // Core::Internal
|
||||
|
@@ -70,15 +70,13 @@ static void matchEditors(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
|
||||
LocatorMatcherTasks OpenDocumentsFilter::matchers()
|
||||
{
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage](Async<void> &async) {
|
||||
const auto onSetup = [](Async<void> &async) {
|
||||
const QList<Entry> editorsData = Utils::transform(DocumentModel::entries(),
|
||||
[](const DocumentModel::Entry *e) { return Entry{e->filePath(), e->displayName()}; });
|
||||
async.setConcurrentCallData(matchEditors, *storage, editorsData);
|
||||
async.setConcurrentCallData(matchEditors, *LocatorStorage::storage(), editorsData);
|
||||
};
|
||||
|
||||
return {{AsyncTask<void>(onSetup), storage}};
|
||||
return {AsyncTask<void>(onSetup)};
|
||||
}
|
||||
|
||||
} // namespace Core::Internal
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include <QJsonObject>
|
||||
#include <QRegularExpression>
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Core::Internal {
|
||||
@@ -176,16 +177,12 @@ static void matches(QPromise<void> &promise,
|
||||
|
||||
LocatorMatcherTasks SpotlightLocatorFilter::matchers()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage,
|
||||
command = m_command,
|
||||
const auto onSetup = [command = m_command,
|
||||
insensArgs = m_arguments,
|
||||
sensArgs = m_caseSensitiveArguments,
|
||||
sortResults = m_sortResults](Async<void> &async) {
|
||||
const Link link = Link::fromString(storage->input(), true);
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
const Link link = Link::fromString(storage.input(), true);
|
||||
const FilePath input = link.targetFilePath;
|
||||
if (input.isEmpty())
|
||||
return SetupResult::StopWithSuccess;
|
||||
@@ -196,11 +193,11 @@ LocatorMatcherTasks SpotlightLocatorFilter::matchers()
|
||||
? insensArgs : sensArgs;
|
||||
const CommandLine cmd(FilePath::fromString(command), expander->expand(args),
|
||||
CommandLine::Raw);
|
||||
async.setConcurrentCallData(matches, *storage, cmd, sortResults);
|
||||
async.setConcurrentCallData(matches, storage, cmd, sortResults);
|
||||
return SetupResult::Continue;
|
||||
};
|
||||
|
||||
return {{AsyncTask<void>(onSetup), storage}};
|
||||
return {AsyncTask<void>(onSetup)};
|
||||
}
|
||||
|
||||
bool SpotlightLocatorFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Core {
|
||||
@@ -163,12 +164,9 @@ UrlLocatorFilter::UrlLocatorFilter(const QString &displayName, Id id)
|
||||
|
||||
LocatorMatcherTasks UrlLocatorFilter::matchers()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [storage, urls = remoteUrls()] {
|
||||
const QString input = storage->input();
|
||||
const auto onSetup = [urls = remoteUrls()] {
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
const QString input = storage.input();
|
||||
LocatorFilterEntries entries;
|
||||
for (const QString &url : urls) {
|
||||
const QString name = url.arg(input);
|
||||
@@ -182,9 +180,9 @@ LocatorMatcherTasks UrlLocatorFilter::matchers()
|
||||
entry.highlightInfo = {int(name.lastIndexOf(input)), int(input.length())};
|
||||
entries.append(entry);
|
||||
}
|
||||
storage->reportOutput(entries);
|
||||
storage.reportOutput(entries);
|
||||
};
|
||||
return {{Sync(onSetup), storage}};
|
||||
return {Sync(onSetup)};
|
||||
}
|
||||
|
||||
const char kDisplayNameKey[] = "displayName";
|
||||
|
@@ -351,9 +351,9 @@ bool SessionManager::deleteSession(const QString &session)
|
||||
FilePath sessionFile = sessionNameToFileName(session);
|
||||
if (!sessionFile.exists())
|
||||
return false;
|
||||
expected_str<void> result = sessionFile.removeFile();
|
||||
Result result = sessionFile.removeFile();
|
||||
QTC_CHECK_EXPECTED(result);
|
||||
return result.has_value();
|
||||
return bool(result);
|
||||
}
|
||||
|
||||
void SessionManager::deleteSessions(const QStringList &sessions)
|
||||
|
@@ -19,13 +19,14 @@
|
||||
|
||||
using namespace Core;
|
||||
using namespace CPlusPlus;
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace CppEditor {
|
||||
|
||||
using EntryFromIndex = std::function<LocatorFilterEntry(const IndexItem::Ptr &)>;
|
||||
|
||||
void matchesFor(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
static void matchesFor(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
IndexItem::ItemType wantedType, const EntryFromIndex &converter)
|
||||
{
|
||||
const QString input = storage.input();
|
||||
@@ -99,19 +100,15 @@ void matchesFor(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
LocatorFilterEntries()));
|
||||
}
|
||||
|
||||
LocatorMatcherTask locatorMatcher(IndexItem::ItemType type, const EntryFromIndex &converter)
|
||||
static ExecutableItem locatorMatcher(IndexItem::ItemType type, const EntryFromIndex &converter)
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [=](Async<void> &async) {
|
||||
async.setConcurrentCallData(matchesFor, *storage, type, converter);
|
||||
const auto onSetup = [type, converter](Async<void> &async) {
|
||||
async.setConcurrentCallData(matchesFor, *LocatorStorage::storage(), type, converter);
|
||||
};
|
||||
return {AsyncTask<void>(onSetup), storage};
|
||||
return AsyncTask<void>(onSetup);
|
||||
}
|
||||
|
||||
LocatorMatcherTask allSymbolsMatcher()
|
||||
static ExecutableItem allSymbolsMatcher()
|
||||
{
|
||||
const auto converter = [](const IndexItem::Ptr &info) {
|
||||
LocatorFilterEntry filterEntry;
|
||||
@@ -129,7 +126,7 @@ LocatorMatcherTask allSymbolsMatcher()
|
||||
return locatorMatcher(IndexItem::All, converter);
|
||||
}
|
||||
|
||||
LocatorMatcherTask classMatcher()
|
||||
static ExecutableItem classMatcher()
|
||||
{
|
||||
const auto converter = [](const IndexItem::Ptr &info) {
|
||||
LocatorFilterEntry filterEntry;
|
||||
@@ -145,7 +142,7 @@ LocatorMatcherTask classMatcher()
|
||||
return locatorMatcher(IndexItem::Class, converter);
|
||||
}
|
||||
|
||||
LocatorMatcherTask functionMatcher()
|
||||
static ExecutableItem functionMatcher()
|
||||
{
|
||||
const auto converter = [](const IndexItem::Ptr &info) {
|
||||
QString name = info->symbolName();
|
||||
@@ -166,7 +163,7 @@ LocatorMatcherTask functionMatcher()
|
||||
return locatorMatcher(IndexItem::Function, converter);
|
||||
}
|
||||
|
||||
QList<IndexItem::Ptr> itemsOfCurrentDocument(const FilePath ¤tFileName)
|
||||
static QList<IndexItem::Ptr> itemsOfCurrentDocument(const FilePath ¤tFileName)
|
||||
{
|
||||
if (currentFileName.isEmpty())
|
||||
return {};
|
||||
@@ -188,7 +185,7 @@ QList<IndexItem::Ptr> itemsOfCurrentDocument(const FilePath ¤tFileName)
|
||||
return results;
|
||||
}
|
||||
|
||||
LocatorFilterEntry::HighlightInfo highlightInfo(const QRegularExpressionMatch &match,
|
||||
static LocatorFilterEntry::HighlightInfo highlightInfo(const QRegularExpressionMatch &match,
|
||||
LocatorFilterEntry::HighlightInfo::DataType dataType)
|
||||
{
|
||||
const FuzzyMatcher::HighlightingPositions positions =
|
||||
@@ -197,7 +194,7 @@ LocatorFilterEntry::HighlightInfo highlightInfo(const QRegularExpressionMatch &m
|
||||
return LocatorFilterEntry::HighlightInfo(positions.starts, positions.lengths, dataType);
|
||||
}
|
||||
|
||||
void matchesForCurrentDocument(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
static void matchesForCurrentDocument(QPromise<void> &promise, const LocatorStorage &storage,
|
||||
const FilePath ¤tFileName)
|
||||
{
|
||||
const QString input = storage.input();
|
||||
@@ -290,25 +287,21 @@ void matchesForCurrentDocument(QPromise<void> &promise, const LocatorStorage &st
|
||||
[](const Entry &entry) { return entry.entry; }));
|
||||
}
|
||||
|
||||
FilePath currentFileName()
|
||||
static FilePath currentFileName()
|
||||
{
|
||||
IEditor *currentEditor = EditorManager::currentEditor();
|
||||
return currentEditor ? currentEditor->document()->filePath() : FilePath();
|
||||
}
|
||||
|
||||
LocatorMatcherTask currentDocumentMatcher()
|
||||
static ExecutableItem currentDocumentMatcher()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [=](Async<void> &async) {
|
||||
async.setConcurrentCallData(matchesForCurrentDocument, *storage, currentFileName());
|
||||
const auto onSetup = [](Async<void> &async) {
|
||||
async.setConcurrentCallData(matchesForCurrentDocument, *LocatorStorage::storage(), currentFileName());
|
||||
};
|
||||
return {AsyncTask<void>(onSetup), storage};
|
||||
return AsyncTask<void>(onSetup);
|
||||
}
|
||||
|
||||
using MatcherCreator = std::function<Core::LocatorMatcherTask()>;
|
||||
using MatcherCreator = std::function<ExecutableItem()>;
|
||||
|
||||
static MatcherCreator creatorForType(MatcherType type)
|
||||
{
|
||||
|
@@ -28,7 +28,7 @@ QTC_DECLARE_MYTESTDATADIR("../../../tests/cpplocators/")
|
||||
class CppLocatorFilterTestCase : public CppEditor::Tests::TestCase
|
||||
{
|
||||
public:
|
||||
CppLocatorFilterTestCase(const QList<LocatorMatcherTask> &matchers,
|
||||
CppLocatorFilterTestCase(const LocatorMatcherTasks &matchers,
|
||||
const QString &fileName,
|
||||
const QString &searchText,
|
||||
const ResultDataList &expectedResults)
|
||||
@@ -54,7 +54,7 @@ class CppCurrentDocumentFilterTestCase : public CppEditor::Tests::TestCase
|
||||
{
|
||||
public:
|
||||
CppCurrentDocumentFilterTestCase(const FilePath &filePath,
|
||||
const QList<LocatorMatcherTask> &matchers,
|
||||
const LocatorMatcherTasks &matchers,
|
||||
const ResultDataList &expectedResults,
|
||||
const QString &searchText = QString())
|
||||
{
|
||||
|
@@ -510,7 +510,7 @@ public:
|
||||
QAction m_abortAction{Tr::tr("Abort Debugging")};
|
||||
QAction m_stepIntoAction{Tr::tr("Step Into")};
|
||||
QAction m_stepOutAction{Tr::tr("Step Out")};
|
||||
QAction m_toggleEnableBreakpointsAction{Tr::tr("Disable all Breakpoints")};
|
||||
QAction m_toggleEnableBreakpointsAction{Tr::tr("Disable All Breakpoints")};
|
||||
QAction m_runToLineAction{Tr::tr("Run to Line")}; // In the debug menu
|
||||
QAction m_runToSelectedFunctionAction{Tr::tr("Run to Selected Function")};
|
||||
QAction m_jumpToLineAction{Tr::tr("Jump to Line")};
|
||||
|
@@ -20,8 +20,6 @@
|
||||
#include <utils/processinterface.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
@@ -43,18 +41,6 @@ public:
|
||||
, m_kit(kit)
|
||||
{}
|
||||
|
||||
QModelIndex indexForId(const QVariant &id) const
|
||||
{
|
||||
// The "None" item always comes last
|
||||
const auto noneIndex = [this] { return index(rowCount() - 1, 0); };
|
||||
|
||||
if (id.isNull())
|
||||
return noneIndex();
|
||||
const TreeItem *const item = findItemAtLevel<1>(
|
||||
[id](TreeItem *item) { return item->data(0, DebuggerTreeItem::IdRole) == id; });
|
||||
return item ? indexForItem(item) : noneIndex();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
clear();
|
||||
@@ -83,12 +69,6 @@ class DebuggerItemSortModel : public SortModel
|
||||
public:
|
||||
DebuggerItemSortModel(QObject *parent) : SortModel(parent) {}
|
||||
|
||||
QModelIndex indexForId(const QVariant &id) const
|
||||
{
|
||||
return mapFromSource(
|
||||
static_cast<DebuggerItemListModel *>(sourceModel())->indexForId(id));
|
||||
}
|
||||
|
||||
void reset() { static_cast<DebuggerItemListModel *>(sourceModel())->reset(); }
|
||||
|
||||
private:
|
||||
@@ -135,58 +115,24 @@ public:
|
||||
{
|
||||
setManagingPage(ProjectExplorer::Constants::DEBUGGER_SETTINGS_PAGE_ID);
|
||||
|
||||
m_comboBox = createSubWidget<QComboBox>();
|
||||
m_comboBox->setSizePolicy(QSizePolicy::Ignored, m_comboBox->sizePolicy().verticalPolicy());
|
||||
m_comboBox->setEnabled(true);
|
||||
const auto sortModel = new DebuggerItemSortModel(this);
|
||||
sortModel->setSourceModel(new DebuggerItemListModel(*workingCopy, this));
|
||||
m_comboBox->setModel(sortModel);
|
||||
|
||||
refresh();
|
||||
m_comboBox->setToolTip(factory->description());
|
||||
connect(m_comboBox, &QComboBox::currentIndexChanged, this, [this] {
|
||||
if (m_ignoreChanges.isLocked())
|
||||
return;
|
||||
m_kit->setValue(DebuggerKitAspect::id(), currentId());
|
||||
});
|
||||
|
||||
auto getter = [](const Kit &k) {
|
||||
if (const DebuggerItem * const item = DebuggerKitAspect::debugger(&k))
|
||||
return item->id();
|
||||
return QVariant();
|
||||
};
|
||||
auto setter = [](Kit &k, const QVariant &id) { k.setValue(DebuggerKitAspect::id(), id); };
|
||||
auto resetModel = [](QAbstractItemModel &model) {
|
||||
static_cast<DebuggerItemSortModel &>(model).reset();
|
||||
};
|
||||
setListAspectSpec(
|
||||
{sortModel,
|
||||
std::move(getter),
|
||||
std::move(setter),
|
||||
std::move(resetModel),
|
||||
DebuggerTreeItem::IdRole});
|
||||
}
|
||||
|
||||
~DebuggerKitAspectImpl() override
|
||||
{
|
||||
delete m_comboBox;
|
||||
}
|
||||
|
||||
private:
|
||||
void addToInnerLayout(Layouting::Layout &parent) override
|
||||
{
|
||||
addMutableAction(m_comboBox);
|
||||
parent.addItem(m_comboBox);
|
||||
}
|
||||
|
||||
void makeReadOnly() override
|
||||
{
|
||||
KitAspect::makeReadOnly();
|
||||
m_comboBox->setEnabled(false);
|
||||
}
|
||||
|
||||
void refresh() override
|
||||
{
|
||||
const GuardLocker locker(m_ignoreChanges);
|
||||
const auto sortModel = static_cast<DebuggerItemSortModel *>(m_comboBox->model());
|
||||
sortModel->reset();
|
||||
sortModel->sort(0);
|
||||
const DebuggerItem * const item = DebuggerKitAspect::debugger(m_kit);
|
||||
m_comboBox->setCurrentIndex(sortModel->indexForId(item ? item->id() : QVariant()).row());
|
||||
}
|
||||
|
||||
QVariant currentId() const
|
||||
{
|
||||
return m_comboBox->itemData(m_comboBox->currentIndex(), DebuggerTreeItem::IdRole);
|
||||
}
|
||||
|
||||
Guard m_ignoreChanges;
|
||||
QComboBox *m_comboBox;
|
||||
};
|
||||
} // namespace Internal
|
||||
|
||||
|
@@ -83,92 +83,27 @@ static QString noDebuggerInKitMessage()
|
||||
return Tr::tr("The kit does not have a debugger set.");
|
||||
}
|
||||
|
||||
class CoreUnpacker final : public RunWorker
|
||||
{
|
||||
public:
|
||||
CoreUnpacker(RunControl *runControl, const FilePath &coreFilePath)
|
||||
: RunWorker(runControl), m_coreFilePath(coreFilePath)
|
||||
{}
|
||||
|
||||
FilePath coreFileName() const { return m_tempCoreFilePath; }
|
||||
|
||||
private:
|
||||
~CoreUnpacker() final
|
||||
{
|
||||
if (m_tempCoreFile.isOpen())
|
||||
m_tempCoreFile.close();
|
||||
|
||||
m_tempCoreFilePath.removeFile();
|
||||
}
|
||||
|
||||
void start() final
|
||||
{
|
||||
{
|
||||
Utils::TemporaryFile tmp("tmpcore-XXXXXX");
|
||||
tmp.open();
|
||||
m_tempCoreFilePath = FilePath::fromString(tmp.fileName());
|
||||
}
|
||||
|
||||
m_coreUnpackProcess.setWorkingDirectory(TemporaryDirectory::masterDirectoryFilePath());
|
||||
connect(&m_coreUnpackProcess, &Process::done, this, [this] {
|
||||
if (m_coreUnpackProcess.error() == QProcess::UnknownError) {
|
||||
reportStopped();
|
||||
return;
|
||||
}
|
||||
reportFailure("Error unpacking " + m_coreFilePath.toUserOutput());
|
||||
});
|
||||
|
||||
const QString msg = Tr::tr("Unpacking core file to %1");
|
||||
appendMessage(msg.arg(m_tempCoreFilePath.toUserOutput()), LogMessageFormat);
|
||||
|
||||
if (m_coreFilePath.endsWith(".lzo")) {
|
||||
m_coreUnpackProcess.setCommand({"lzop", {"-o", m_tempCoreFilePath.path(),
|
||||
"-x", m_coreFilePath.path()}});
|
||||
reportStarted();
|
||||
m_coreUnpackProcess.start();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_coreFilePath.endsWith(".gz")) {
|
||||
appendMessage(msg.arg(m_tempCoreFilePath.toUserOutput()), LogMessageFormat);
|
||||
m_tempCoreFile.setFileName(m_tempCoreFilePath.path());
|
||||
m_tempCoreFile.open(QFile::WriteOnly);
|
||||
connect(&m_coreUnpackProcess, &Process::readyReadStandardOutput, this, [this] {
|
||||
m_tempCoreFile.write(m_coreUnpackProcess.readAllRawStandardOutput());
|
||||
});
|
||||
m_coreUnpackProcess.setCommand({"gzip", {"-c", "-d", m_coreFilePath.path()}});
|
||||
reportStarted();
|
||||
m_coreUnpackProcess.start();
|
||||
return;
|
||||
}
|
||||
|
||||
QTC_CHECK(false);
|
||||
reportFailure("Unknown file extension in " + m_coreFilePath.toUserOutput());
|
||||
}
|
||||
|
||||
QFile m_tempCoreFile;
|
||||
FilePath m_coreFilePath;
|
||||
FilePath m_tempCoreFilePath;
|
||||
Process m_coreUnpackProcess;
|
||||
};
|
||||
|
||||
class DebuggerRunToolPrivate
|
||||
{
|
||||
public:
|
||||
QPointer<CoreUnpacker> coreUnpacker;
|
||||
bool addQmlServerInferiorCommandLineArgumentIfNeeded = false;
|
||||
int snapshotCounter = 0;
|
||||
int engineStartsNeeded = 0;
|
||||
int engineStopsNeeded = 0;
|
||||
QString runId;
|
||||
|
||||
// Core unpacker
|
||||
QFile m_tempCoreFile;
|
||||
FilePath m_tempCoreFilePath;
|
||||
Process m_coreUnpackProcess;
|
||||
|
||||
// Terminal
|
||||
Process terminalProc;
|
||||
DebuggerRunTool::AllowTerminal allowTerminal = DebuggerRunTool::DoAllowTerminal;
|
||||
|
||||
// DebugServer
|
||||
Process debuggerServerProc;
|
||||
Utils::ProcessHandle serverAttachPid;
|
||||
ProcessHandle serverAttachPid;
|
||||
bool serverUseMulti = true;
|
||||
bool serverEssential = true;
|
||||
};
|
||||
@@ -369,11 +304,6 @@ void DebuggerRunTool::setStartMessage(const QString &msg)
|
||||
|
||||
void DebuggerRunTool::setCoreFilePath(const FilePath &coreFile, bool isSnapshot)
|
||||
{
|
||||
if (coreFile.endsWith(".gz") || coreFile.endsWith(".lzo")) {
|
||||
d->coreUnpacker = new CoreUnpacker(runControl(), coreFile);
|
||||
addStartDependency(d->coreUnpacker);
|
||||
}
|
||||
|
||||
m_runParameters.coreFile = coreFile;
|
||||
m_runParameters.isSnapshot = isSnapshot;
|
||||
}
|
||||
@@ -405,6 +335,63 @@ void DebuggerRunTool::addSearchDirectory(const Utils::FilePath &dir)
|
||||
|
||||
void DebuggerRunTool::start()
|
||||
{
|
||||
startCoreFileSetupIfNeededAndContinueStartup();
|
||||
}
|
||||
|
||||
void DebuggerRunTool::startCoreFileSetupIfNeededAndContinueStartup()
|
||||
{
|
||||
const FilePath coreFile = m_runParameters.coreFile;
|
||||
if (!coreFile.endsWith(".gz") && !coreFile.endsWith(".lzo")) {
|
||||
continueAfterCoreFileSetup();
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
TemporaryFile tmp("tmpcore-XXXXXX");
|
||||
tmp.open();
|
||||
d->m_tempCoreFilePath = FilePath::fromString(tmp.fileName());
|
||||
}
|
||||
|
||||
d->m_coreUnpackProcess.setWorkingDirectory(TemporaryDirectory::masterDirectoryFilePath());
|
||||
connect(&d->m_coreUnpackProcess, &Process::done, this, [this] {
|
||||
if (d->m_coreUnpackProcess.error() == QProcess::UnknownError) {
|
||||
m_runParameters.coreFile = d->m_tempCoreFilePath;
|
||||
continueAfterCoreFileSetup();
|
||||
return;
|
||||
}
|
||||
reportFailure("Error unpacking " + m_runParameters.coreFile.toUserOutput());
|
||||
});
|
||||
|
||||
const QString msg = Tr::tr("Unpacking core file to %1");
|
||||
appendMessage(msg.arg(d->m_tempCoreFilePath.toUserOutput()), LogMessageFormat);
|
||||
|
||||
if (coreFile.endsWith(".lzo")) {
|
||||
d->m_coreUnpackProcess.setCommand({"lzop", {"-o", d->m_tempCoreFilePath.path(),
|
||||
"-x", coreFile.path()}});
|
||||
d->m_coreUnpackProcess.start();
|
||||
return;
|
||||
}
|
||||
|
||||
if (coreFile.endsWith(".gz")) {
|
||||
d->m_tempCoreFile.setFileName(d->m_tempCoreFilePath.path());
|
||||
d->m_tempCoreFile.open(QFile::WriteOnly);
|
||||
connect(&d->m_coreUnpackProcess, &Process::readyReadStandardOutput, this, [this] {
|
||||
d->m_tempCoreFile.write(d->m_coreUnpackProcess.readAllRawStandardOutput());
|
||||
});
|
||||
d->m_coreUnpackProcess.setCommand({"gzip", {"-c", "-d", coreFile.path()}});
|
||||
d->m_coreUnpackProcess.start();
|
||||
return;
|
||||
}
|
||||
|
||||
QTC_CHECK(false);
|
||||
reportFailure("Unknown file extension in " + coreFile.toUserOutput());
|
||||
}
|
||||
|
||||
void DebuggerRunTool::continueAfterCoreFileSetup()
|
||||
{
|
||||
if (d->m_tempCoreFile.isOpen())
|
||||
d->m_tempCoreFile.close();
|
||||
|
||||
startTerminalIfNeededAndContinueStartup();
|
||||
}
|
||||
|
||||
@@ -497,9 +484,6 @@ void DebuggerRunTool::continueAfterTerminalStart()
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (d->coreUnpacker)
|
||||
m_runParameters.coreFile = d->coreUnpacker->coreFileName();
|
||||
|
||||
if (!fixupParameters())
|
||||
return;
|
||||
|
||||
@@ -978,6 +962,9 @@ void DebuggerRunTool::addSolibSearchDir(const QString &str)
|
||||
|
||||
DebuggerRunTool::~DebuggerRunTool()
|
||||
{
|
||||
if (d->m_tempCoreFilePath.exists())
|
||||
d->m_tempCoreFilePath.removeFile();
|
||||
|
||||
if (m_runParameters.isSnapshot && !m_runParameters.coreFile.isEmpty())
|
||||
m_runParameters.coreFile.removeFile();
|
||||
|
||||
|
@@ -111,6 +111,9 @@ private:
|
||||
void handleEngineStarted(Internal::DebuggerEngine *engine);
|
||||
void handleEngineFinished(Internal::DebuggerEngine *engine);
|
||||
|
||||
void startCoreFileSetupIfNeededAndContinueStartup();
|
||||
void continueAfterCoreFileSetup();
|
||||
|
||||
void startTerminalIfNeededAndContinueStartup();
|
||||
void continueAfterTerminalStart();
|
||||
|
||||
|
@@ -232,7 +232,7 @@ void AttachCoreDialog::accepted()
|
||||
const expected_str<FilePath> resultPath = pattern.createTempFile();
|
||||
if (!resultPath)
|
||||
return make_unexpected(resultPath.error());
|
||||
const expected_str<void> result = srcPath.copyFile(resultPath.value());
|
||||
const Result result = srcPath.copyFile(resultPath.value());
|
||||
if (!result)
|
||||
return make_unexpected(result.error());
|
||||
|
||||
|
@@ -582,7 +582,7 @@ DockerDevice::DockerDevice()
|
||||
return make_unexpected(cmdBridgePath.error());
|
||||
|
||||
auto fAccess = std::make_unique<DockerDeviceFileAccess>(d);
|
||||
expected_str<void> initResult;
|
||||
Result initResult = Result::Ok;
|
||||
if (!cmdBridgePath->isSameDevice(Docker::Internal::settings().dockerBinaryPath())) {
|
||||
initResult = fAccess->deployAndInit(Core::ICore::libexecPath(), rootPath());
|
||||
} else {
|
||||
|
@@ -171,6 +171,8 @@ public:
|
||||
constexpr static QSize dividerS{1, 16};
|
||||
constexpr static TextFormat itemNameTF
|
||||
{Theme::Token_Text_Default, UiElement::UiElementH6};
|
||||
constexpr static TextFormat releaseStatusTF
|
||||
{Theme::Token_Notification_Alert, UiElement::UiElementLabelSmall};
|
||||
constexpr static TextFormat countTF
|
||||
{Theme::Token_Text_Default, UiElement::UiElementLabelSmall,
|
||||
Qt::AlignCenter | Qt::TextDontClip};
|
||||
@@ -190,23 +192,23 @@ public:
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)
|
||||
const override
|
||||
{
|
||||
// +---------------+-------+---------------+----------------------------------------------------------------------+---------------+---------+
|
||||
// | | | | (ExPaddingGapL) | | |
|
||||
// | | | +-----------------------------+---------+--------+---------+-----------+ | |
|
||||
// | | | | <itemName> |(HGapXxs)|<status>|(HGapXxs)|<checkmark>| | |
|
||||
// | | | +-----------------------------+---------+--------+---------+-----------+ | |
|
||||
// | | | | (VGapXxs) | | |
|
||||
// | | | +--------+--------+--------------+--------+--------+---------+---------+ | |
|
||||
// |(ExPaddingGapL)|<icon> |(ExPaddingGapL)|<vendor>|(HGapXs)|<divider>(h16)|(HGapXs)|<dlIcon>|(HGapXxs)|<dlCount>|(ExPaddingGapL)|(gapSize)|
|
||||
// | |(50x50)| +--------+--------+--------------+--------+--------+---------+---------+ | |
|
||||
// | | | | (VGapXxs) | | |
|
||||
// | | | +----------------------------------------------------------------------+ | |
|
||||
// | | | | <tags> | | |
|
||||
// | | | +----------------------------------------------------------------------+ | |
|
||||
// | | | | (ExPaddingGapL) | | |
|
||||
// +---------------+-------+---------------+----------------------------------------------------------------------+---------------+---------+
|
||||
// | (gapSize) |
|
||||
// +----------------------------------------------------------------------------------------------------------------------------------------+
|
||||
// +---------------+-------+---------------+-----------------------------------------------------------------------------------+---------------+---------+
|
||||
// | | | | (ExPaddingGapL) | | |
|
||||
// | | | +----------+---------+---------------+---------+--------------+---------+-----------+ | |
|
||||
// | | | |<itemName>|(HGapXxs)|<releaseStatus>|(HGapXxs)|<installState>|(HGapXxs)|<checkmark>| | |
|
||||
// | | | +----------+---------+---------------+---------+--------------+---------+-----------+ | |
|
||||
// | | | | (VGapXxs) | | |
|
||||
// | | | +---------------------+--------+--------------+--------+--------+---------+---------+ | |
|
||||
// |(ExPaddingGapL)|<icon> |(ExPaddingGapL)| <vendor> |(HGapXs)|<divider>(h16)|(HGapXs)|<dlIcon>|(HGapXxs)|<dlCount>|(ExPaddingGapL)|(gapSize)|
|
||||
// | |(50x50)| +---------------------+--------+--------------+--------+--------+---------+---------+ | |
|
||||
// | | | | (VGapXxs) | | |
|
||||
// | | | +-----------------------------------------------------------------------------------+ | |
|
||||
// | | | | <tags> | | |
|
||||
// | | | +-----------------------------------------------------------------------------------+ | |
|
||||
// | | | | (ExPaddingGapL) | | |
|
||||
// +---------------+-------+---------------+-----------------------------------------------------------------------------------+---------------+---------+
|
||||
// | (gapSize) |
|
||||
// +-----------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
const QRect bgRGlobal = option.rect.adjusted(0, 0, -gapSize, -gapSize);
|
||||
const QRect bgR = bgRGlobal.translated(-option.rect.topLeft());
|
||||
@@ -267,6 +269,10 @@ public:
|
||||
const QPixmap icon = itemIcon(index, SizeSmall);
|
||||
painter->drawPixmap(iconBgR.topLeft(), icon);
|
||||
}
|
||||
{
|
||||
const QPixmap badge = itemBadge(index, SizeSmall);
|
||||
painter->drawPixmap(bgR.topLeft(), badge);
|
||||
}
|
||||
if (isPack) {
|
||||
constexpr int circleSize = 18;
|
||||
constexpr int circleOverlap = 3; // Protrusion from lower right corner of iconRect
|
||||
@@ -286,16 +292,40 @@ public:
|
||||
QRect effectiveR = itemNameR;
|
||||
if (showState)
|
||||
effectiveR.setRight(stateR.left() - HGapXxs - 1);
|
||||
const QString releaseStatus = statusDisplayString(index);
|
||||
const bool showReleaseStatus = !releaseStatus.isEmpty();
|
||||
|
||||
if (showReleaseStatus) {
|
||||
const QFont releaseStatusF = releaseStatusTF.font();
|
||||
const int releaseStatusAdv =
|
||||
QFontMetrics(releaseStatusF).horizontalAdvance(releaseStatus)
|
||||
+ (showState ? ExVPaddingGapXl - HGapXxs
|
||||
: HGapXxs);
|
||||
effectiveR.setWidth(effectiveR.width() - releaseStatusAdv);
|
||||
}
|
||||
|
||||
painter->setPen(itemNameTF.color());
|
||||
painter->setFont(itemNameTF.font());
|
||||
const QString titleElided
|
||||
= painter->fontMetrics().elidedText(itemName, Qt::ElideRight, effectiveR.width());
|
||||
painter->drawText(effectiveR, itemNameTF.drawTextFlags, titleElided);
|
||||
|
||||
if (showReleaseStatus) {
|
||||
const int titleElidedAdv = painter->fontMetrics().horizontalAdvance(titleElided);
|
||||
const QRect releaseStatusR(effectiveR.x() + titleElidedAdv + HGapXxs,
|
||||
effectiveR.y(), 1, effectiveR.height() - 1);
|
||||
painter->setPen(releaseStatusTF.color());
|
||||
painter->setFont(releaseStatusTF.font());
|
||||
painter->drawText(releaseStatusR, releaseStatusTF.drawTextFlags, releaseStatus);
|
||||
}
|
||||
}
|
||||
if (showState) {
|
||||
static const QIcon checkmark = Icon({{":/extensionmanager/images/checkmark.png",
|
||||
stateTF.themeColor}}, Icon::Tint).icon();
|
||||
checkmark.paint(painter, checkmarkR);
|
||||
const FilePath checkmarkMask = ":/extensionmanager/images/checkmark.png";
|
||||
static const QIcon enabled = Icon({{checkmarkMask, Theme::Token_Accent_Muted}},
|
||||
Icon::Tint).icon();
|
||||
static const QIcon disabled = Icon({{checkmarkMask, stateTF.themeColor}},
|
||||
Icon::Tint).icon();
|
||||
(state == InstalledEnabled ? enabled : disabled).paint(painter, checkmarkR);
|
||||
painter->setPen(stateTF.color());
|
||||
painter->setFont(stateTF.font());
|
||||
painter->drawText(stateR, stateTF.drawTextFlags, stateString);
|
||||
@@ -518,6 +548,7 @@ ExtensionsBrowser::ExtensionsBrowser(ExtensionsModel *model, QWidget *parent)
|
||||
Tr::tr("Filter by: %1"));
|
||||
d->filterChooser->addItems(Utils::transform(SortFilterProxyModel::filterOptions(),
|
||||
&SortFilterProxyModel::FilterOption::displayName));
|
||||
d->filterChooser->hide(); // TODO: Unhide when ready. See QTCREATORBUG-31751
|
||||
|
||||
d->sortChooser = new OptionChooser(":/extensionmanager/images/sort.png", Tr::tr("Sort by: %1"));
|
||||
d->sortChooser->addItems(Utils::transform(SortFilterProxyModel::sortOptions(),
|
||||
@@ -549,11 +580,11 @@ ExtensionsBrowser::ExtensionsBrowser(ExtensionsModel *model, QWidget *parent)
|
||||
customMargins(0, VPaddingM, extraListViewWidth() + gapSize, VPaddingM),
|
||||
},
|
||||
Row {
|
||||
d->filterChooser,
|
||||
Space(HGapS),
|
||||
d->sortChooser,
|
||||
d->filterChooser,
|
||||
st,
|
||||
settingsToolButton,
|
||||
spacing(HGapS),
|
||||
customMargins(0, 0, extraListViewWidth() + gapSize, 0),
|
||||
},
|
||||
d->extensionsView,
|
||||
@@ -587,7 +618,7 @@ ExtensionsBrowser::ExtensionsBrowser(ExtensionsModel *model, QWidget *parent)
|
||||
d->sortFilterProxyModel, &SortFilterProxyModel::setSortOption);
|
||||
connect(d->filterChooser, &OptionChooser::currentIndexChanged,
|
||||
d->sortFilterProxyModel, &SortFilterProxyModel::setFilterOption);
|
||||
connect(settingsToolButton, &QAbstractButton::pressed, this, []() {
|
||||
connect(settingsToolButton, &QAbstractButton::clicked, this, []() {
|
||||
ICore::showOptionsDialog(Constants::EXTENSIONMANAGER_SETTINGSPAGE_ID);
|
||||
});
|
||||
connect(&settings(), &AspectContainer::changed, this, [this]() {
|
||||
@@ -697,6 +728,8 @@ QLabel *tfLabel(const TextFormat &tf, bool singleLine)
|
||||
return label;
|
||||
}
|
||||
|
||||
const int iconRectRounding = 4;
|
||||
|
||||
QPixmap itemIcon(const QModelIndex &index, Size size)
|
||||
{
|
||||
const QSize iconBgS = size == SizeSmall ? iconBgSizeSmall : iconBgSizeBig;
|
||||
@@ -727,7 +760,6 @@ QPixmap itemIcon(const QModelIndex &index, Size size)
|
||||
const ItemType itemType = index.data(RoleItemType).value<ItemType>();
|
||||
const QIcon &icon = (itemType == ItemTypePack) ? (size == SizeSmall ? packS : packB)
|
||||
: (size == SizeSmall ? extensionS : extensionB);
|
||||
const int iconRectRounding = 4;
|
||||
const qreal iconOpacityDisabled = 0.6;
|
||||
|
||||
QPainter p(&pixmap);
|
||||
@@ -741,4 +773,33 @@ QPixmap itemIcon(const QModelIndex &index, Size size)
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QPixmap itemBadge(const QModelIndex &index, [[maybe_unused]] Size size)
|
||||
{
|
||||
const QString badgeText = index.data(RoleBadge).toString();
|
||||
if (badgeText.isNull())
|
||||
return {};
|
||||
|
||||
constexpr TextFormat badgeTF
|
||||
{Theme::Token_Basic_White, UiElement::UiElementLabelSmall};
|
||||
|
||||
const QFont font = badgeTF.font();
|
||||
const int textWidth = QFontMetrics(font).horizontalAdvance(badgeText);
|
||||
const QSize badgeS(ExPaddingGapM + textWidth + ExPaddingGapM,
|
||||
ExPaddingGapS + badgeTF.lineHeight() + ExPaddingGapS);
|
||||
const QRect badgeR(QPoint(), badgeS);
|
||||
const qreal dpr = qApp->devicePixelRatio();
|
||||
QPixmap pixmap(badgeS * dpr);
|
||||
pixmap.fill(Qt::transparent);
|
||||
pixmap.setDevicePixelRatio(dpr);
|
||||
|
||||
QPainter p(&pixmap);
|
||||
WelcomePageHelpers::drawCardBackground(&p, badgeR,
|
||||
creatorColor(Theme::Token_Notification_Neutral),
|
||||
Qt::NoPen, iconRectRounding);
|
||||
p.setFont(font);
|
||||
p.setPen(badgeTF.color());
|
||||
p.drawText(badgeR, Qt::AlignCenter, badgeText);
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
} // ExtensionManager::Internal
|
||||
|
@@ -50,5 +50,6 @@ enum Size {
|
||||
SizeBig,
|
||||
};
|
||||
QPixmap itemIcon(const QModelIndex &index, Size size);
|
||||
QPixmap itemBadge(const QModelIndex &index, Size size);
|
||||
|
||||
} // ExtensionManager::Internal
|
||||
|
@@ -49,7 +49,7 @@ public:
|
||||
void ExtensionsModelPrivate::addUnlistedLocalPlugins()
|
||||
{
|
||||
QStringList responseExtensions;
|
||||
for (const QJsonValueConstRef &responseItem : responseItems)
|
||||
for (const QJsonValueConstRef &responseItem : qAsConst(responseItems))
|
||||
responseExtensions << responseItem.toObject().value("id").toString();
|
||||
|
||||
localPlugins.clear();
|
||||
@@ -114,7 +114,7 @@ QVariant ExtensionsModelPrivate::dataFromRemotePlugin(const QJsonObject &json, i
|
||||
const QJsonArray sources = json.value("sources").toArray();
|
||||
const QString thisPlatform = customOsTypeToString(HostOsInfo::hostOs());
|
||||
const QString thisArch = QSysInfo::currentCpuArchitecture();
|
||||
for (const QJsonValue source : sources) {
|
||||
for (const QJsonValue &source : sources) {
|
||||
const QJsonObject sourceObject = source.toObject();
|
||||
const QJsonObject platform = sourceObject.value("platform").toObject();
|
||||
if (platform.isEmpty() // Might be a Lua plugin
|
||||
@@ -150,11 +150,14 @@ QVariant ExtensionsModelPrivate::dataFromRemoteExtension(int index, int role) co
|
||||
case RoleName:
|
||||
return json.value("display_name");
|
||||
case RoleDownloadCount:
|
||||
return json.value("downloads");
|
||||
break; // TODO: Reinstate download numbers when they have more substance
|
||||
// return json.value("downloads");
|
||||
case RoleId:
|
||||
return json.value(EXTENSION_KEY_ID);
|
||||
case RoleDateUpdated:
|
||||
return QDate::fromString(json.value("updated_at").toString(), Qt::ISODate);
|
||||
case RoleStatus:
|
||||
return json.value("status");
|
||||
case RoleTags:
|
||||
return json.value("tags").toVariant().toStringList();
|
||||
case RoleVendor:
|
||||
@@ -239,6 +242,13 @@ int ExtensionsModel::rowCount([[maybe_unused]] const QModelIndex &parent) const
|
||||
return d->responseItems.count() + d->localPlugins.count();
|
||||
}
|
||||
|
||||
static QString badgeText(const QModelIndex &index)
|
||||
{
|
||||
if (index.data(RoleDownloadUrl).isNull())
|
||||
return {};
|
||||
return Tr::tr("New");
|
||||
}
|
||||
|
||||
ExtensionState extensionState(const QModelIndex &index)
|
||||
{
|
||||
if (index.data(RoleItemType) != ItemTypeExtension)
|
||||
@@ -264,10 +274,16 @@ static QString searchText(const QModelIndex &index)
|
||||
|
||||
QVariant ExtensionsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == RoleExtensionState)
|
||||
switch (role) {
|
||||
case RoleBadge:
|
||||
return badgeText(index);
|
||||
case RoleExtensionState:
|
||||
return extensionState(index);
|
||||
if (role == RoleSearchText)
|
||||
case RoleSearchText:
|
||||
return searchText(index);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const bool isRemoteExtension = index.row() < d->responseItems.count();
|
||||
const int itemIndex = index.row() - (isRemoteExtension ? 0 : d->responseItems.count());
|
||||
@@ -282,8 +298,8 @@ QModelIndex ExtensionsModel::indexOfId(const QString &extensionId) const
|
||||
if (localIndex >= 0)
|
||||
return index(d->responseItems.count() + localIndex);
|
||||
|
||||
for (int remoteIndex = 0; const QJsonValueConstRef vlaue : d->responseItems) {
|
||||
if (vlaue.toObject().value(EXTENSION_KEY_ID) == extensionId)
|
||||
for (int remoteIndex = 0; const QJsonValueConstRef &value : std::as_const(d->responseItems)) {
|
||||
if (value.toObject().value(EXTENSION_KEY_ID) == extensionId)
|
||||
return index(remoteIndex);
|
||||
++remoteIndex;
|
||||
}
|
||||
@@ -324,4 +340,10 @@ PluginSpec *pluginSpecForId(const QString &pluginId)
|
||||
return findOrDefault(PluginManager::plugins(), equal(&PluginSpec::id, pluginId));
|
||||
}
|
||||
|
||||
QString statusDisplayString(const QModelIndex &index)
|
||||
{
|
||||
const QString statusString = index.data(RoleStatus).toString();
|
||||
return statusString != "published" ? statusString : QString();
|
||||
}
|
||||
|
||||
} // ExtensionManager::Internal
|
||||
|
@@ -27,7 +27,9 @@ enum ExtensionState {
|
||||
|
||||
enum Role {
|
||||
RoleName = Qt::UserRole,
|
||||
RoleBadge,
|
||||
RoleCopyright,
|
||||
RoleDateUpdated,
|
||||
RoleDependencies,
|
||||
RoleDescriptionLong,
|
||||
RoleDescriptionShort,
|
||||
@@ -39,8 +41,8 @@ enum Role {
|
||||
RoleLicense,
|
||||
RolePlatforms,
|
||||
RolePlugins,
|
||||
RoleDateUpdated,
|
||||
RoleSearchText,
|
||||
RoleStatus,
|
||||
RoleTags,
|
||||
RoleVendor,
|
||||
RoleVendorId,
|
||||
@@ -65,6 +67,7 @@ private:
|
||||
|
||||
QString customOsTypeToString(Utils::OsType osType);
|
||||
ExtensionSystem::PluginSpec *pluginSpecForId(const QString &pluginId);
|
||||
QString statusDisplayString(const QModelIndex &index);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
QObject *createExtensionsModelTest();
|
||||
|
@@ -647,6 +647,11 @@ public:
|
||||
GitLogConfig(bool fileRelated, GitEditorWidget *editor)
|
||||
: GitBaseConfig(editor)
|
||||
{
|
||||
QAction *allBranchesButton =
|
||||
addToggleButton(QStringList{"--all"},
|
||||
Tr::tr("All"),
|
||||
Tr::tr("Show log for all local branches."));
|
||||
mapSetting(allBranchesButton, &settings().allBranches);
|
||||
QAction *firstParentButton =
|
||||
addToggleButton({"-m", "--first-parent"},
|
||||
Tr::tr("First Parent"),
|
||||
@@ -944,7 +949,7 @@ void GitClient::updateModificationInfos()
|
||||
{'?', IVCF::UnmanagedState},
|
||||
};
|
||||
|
||||
const IVCF &modification = std::max(gitStates.value(line.at(0), IVCF::NoModification),
|
||||
const IVCF modification = std::max(gitStates.value(line.at(0), IVCF::NoModification),
|
||||
gitStates.value(line.at(1), IVCF::NoModification));
|
||||
|
||||
if (modification != IVCF::NoModification)
|
||||
|
@@ -113,6 +113,7 @@ GitSettings::GitSettings()
|
||||
colorLog.setSettingsKey("ColorLog");
|
||||
colorLog.setDefaultValue(true);
|
||||
|
||||
allBranches.setSettingsKey("AllBranches");
|
||||
firstParent.setSettingsKey("FirstParent");
|
||||
|
||||
followRenames.setSettingsKey("FollowRenames");
|
||||
|
@@ -33,6 +33,7 @@ public:
|
||||
Utils::FilePathAspect repositoryBrowserCmd{this};
|
||||
Utils::BoolAspect graphLog{this};
|
||||
Utils::BoolAspect colorLog{this};
|
||||
Utils::BoolAspect allBranches{this};
|
||||
Utils::BoolAspect firstParent{this};
|
||||
Utils::BoolAspect followRenames{this};
|
||||
Utils::IntegerAspect lastResetIndex{this};
|
||||
|
@@ -407,6 +407,10 @@ void InstantBlame::perform()
|
||||
const CommitInfo info = parseBlameOutput(output.split('\n'), filePath, line, m_author);
|
||||
m_blameMark.reset(new BlameMark(filePath, line, info));
|
||||
|
||||
static const QString uncommittedHash(40, '0');
|
||||
if (info.hash == uncommittedHash)
|
||||
return;
|
||||
|
||||
// Get line diff: `git log -n 1 -p -L47,47:README.md a5c4c34c9ab4`
|
||||
const QString origLineString = QString("%1,%1").arg(info.originalLine);
|
||||
const QString fileLineRange = "-L" + origLineString + ":" + info.originalFileName;
|
||||
|
@@ -82,9 +82,7 @@ static void matches(QPromise<QStringList> &promise, const LocatorStorage &storag
|
||||
|
||||
LocatorMatcherTasks HelpIndexFilter::matchers()
|
||||
{
|
||||
Storage<LocatorStorage> storage;
|
||||
|
||||
const auto onSetup = [this, storage](Async<QStringList> &async) {
|
||||
const auto onSetup = [this](Async<QStringList> &async) {
|
||||
if (m_needsUpdate) {
|
||||
m_needsUpdate = false;
|
||||
LocalHelpManager::setupGuiHelpEngine();
|
||||
@@ -92,18 +90,19 @@ LocatorMatcherTasks HelpIndexFilter::matchers()
|
||||
m_lastIndicesCache.clear();
|
||||
m_lastEntry.clear();
|
||||
}
|
||||
const QStringList cache = m_lastEntry.isEmpty() || !storage->input().contains(m_lastEntry)
|
||||
const LocatorStorage &storage = *LocatorStorage::storage();
|
||||
const QStringList cache = m_lastEntry.isEmpty() || !storage.input().contains(m_lastEntry)
|
||||
? m_allIndicesCache : m_lastIndicesCache;
|
||||
async.setConcurrentCallData(matches, *storage, cache, m_icon);
|
||||
async.setConcurrentCallData(matches, storage, cache, m_icon);
|
||||
};
|
||||
const auto onDone = [this, storage](const Async<QStringList> &async) {
|
||||
const auto onDone = [this](const Async<QStringList> &async) {
|
||||
if (async.isResultAvailable()) {
|
||||
m_lastIndicesCache = async.result();
|
||||
m_lastEntry = storage->input();
|
||||
m_lastEntry = LocatorStorage::storage()->input();
|
||||
}
|
||||
};
|
||||
|
||||
return {{AsyncTask<QStringList>(onSetup, onDone, CallDoneIf::Success), storage}};
|
||||
return {AsyncTask<QStringList>(onSetup, onDone, CallDoneIf::Success)};
|
||||
}
|
||||
|
||||
void HelpIndexFilter::invalidateCache()
|
||||
|
@@ -104,7 +104,7 @@ void CommandBuilderAspectPrivate::tryToMigrate()
|
||||
for (Utils::Id stepId : migratableSteps) {
|
||||
if (BuildStep *bs = m_buildStep->stepList()->firstStepWithId(stepId)) {
|
||||
m_activeCommandBuilder = p;
|
||||
bs->setEnabled(false);
|
||||
bs->setStepEnabled(false);
|
||||
m_buildStep->project()->saveSettings();
|
||||
return;
|
||||
}
|
||||
|
@@ -381,7 +381,7 @@ bool applyDocumentChange(const Client *client, const DocumentChange &change)
|
||||
}
|
||||
}
|
||||
}
|
||||
return oldPath.renameFile(newPath).has_value();
|
||||
return bool(oldPath.renameFile(newPath));
|
||||
} else if (const auto deleteOperation = std::get_if<DeleteFileOperation>(&change)) {
|
||||
const FilePath filePath = deleteOperation->uri().toFilePath(client->hostPathMapper());
|
||||
if (const std::optional<DeleteFileOptions> options = deleteOperation->options()) {
|
||||
@@ -390,7 +390,7 @@ bool applyDocumentChange(const Client *client, const DocumentChange &change)
|
||||
if (filePath.isDir() && options->recursive().value_or(false))
|
||||
return filePath.removeRecursively();
|
||||
}
|
||||
return filePath.removeFile().has_value();
|
||||
return bool(filePath.removeFile());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -15,11 +15,12 @@
|
||||
|
||||
using namespace Core;
|
||||
using namespace LanguageServerProtocol;
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace LanguageClient {
|
||||
|
||||
void filterResults(QPromise<void> &promise, const LocatorStorage &storage, Client *client,
|
||||
static void filterResults(QPromise<void> &promise, const LocatorStorage &storage, Client *client,
|
||||
const QList<SymbolInformation> &results, const QList<SymbolKind> &filter)
|
||||
{
|
||||
const auto doFilter = [&](const SymbolInformation &info) {
|
||||
@@ -41,18 +42,15 @@ void filterResults(QPromise<void> &promise, const LocatorStorage &storage, Clien
|
||||
storage.reportOutput(Utils::transform(filteredResults, generateEntry));
|
||||
}
|
||||
|
||||
LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount,
|
||||
static ExecutableItem locatorMatcher(Client *client, int maxResultCount,
|
||||
const QList<SymbolKind> &filter)
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
Storage<QList<SymbolInformation>> resultStorage;
|
||||
|
||||
const auto onQuerySetup = [storage, client, maxResultCount](ClientWorkspaceSymbolRequest &request) {
|
||||
const auto onQuerySetup = [client, maxResultCount](ClientWorkspaceSymbolRequest &request) {
|
||||
request.setClient(client);
|
||||
WorkspaceSymbolParams params;
|
||||
params.setQuery(storage->input());
|
||||
params.setQuery(LocatorStorage::storage()->input());
|
||||
if (maxResultCount > 0)
|
||||
params.setLimit(maxResultCount);
|
||||
request.setParams(params);
|
||||
@@ -64,11 +62,12 @@ LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount,
|
||||
*resultStorage = result->toList();
|
||||
};
|
||||
|
||||
const auto onFilterSetup = [storage, resultStorage, client, filter](Async<void> &async) {
|
||||
const auto onFilterSetup = [resultStorage, client, filter](Async<void> &async) {
|
||||
const QList<SymbolInformation> results = *resultStorage;
|
||||
if (results.isEmpty())
|
||||
return SetupResult::StopWithSuccess;
|
||||
async.setConcurrentCallData(filterResults, *storage, client, results, filter);
|
||||
async.setConcurrentCallData(filterResults, *LocatorStorage::storage(), client, results,
|
||||
filter);
|
||||
return SetupResult::Continue;
|
||||
};
|
||||
|
||||
@@ -77,20 +76,20 @@ LocatorMatcherTask locatorMatcher(Client *client, int maxResultCount,
|
||||
ClientWorkspaceSymbolRequestTask(onQuerySetup, onQueryDone, CallDoneIf::Success),
|
||||
AsyncTask<void>(onFilterSetup)
|
||||
};
|
||||
return {root, storage};
|
||||
return root;
|
||||
}
|
||||
|
||||
LocatorMatcherTask allSymbolsMatcher(Client *client, int maxResultCount)
|
||||
static ExecutableItem allSymbolsMatcher(Client *client, int maxResultCount)
|
||||
{
|
||||
return locatorMatcher(client, maxResultCount, {});
|
||||
}
|
||||
|
||||
LocatorMatcherTask classMatcher(Client *client, int maxResultCount)
|
||||
static ExecutableItem classMatcher(Client *client, int maxResultCount)
|
||||
{
|
||||
return locatorMatcher(client, maxResultCount, {SymbolKind::Class, SymbolKind::Struct});
|
||||
}
|
||||
|
||||
LocatorMatcherTask functionMatcher(Client *client, int maxResultCount)
|
||||
static ExecutableItem functionMatcher(Client *client, int maxResultCount)
|
||||
{
|
||||
return locatorMatcher(client, maxResultCount,
|
||||
{SymbolKind::Method, SymbolKind::Function, SymbolKind::Constructor});
|
||||
@@ -112,33 +111,28 @@ static void filterCurrentResults(QPromise<void> &promise, const LocatorStorage &
|
||||
docSymbolModifier));
|
||||
}
|
||||
|
||||
LocatorMatcherTask currentDocumentMatcher()
|
||||
static ExecutableItem currentDocumentMatcher()
|
||||
{
|
||||
using namespace Tasking;
|
||||
|
||||
Storage<LocatorStorage> storage;
|
||||
Storage<CurrentDocumentSymbolsData> resultStorage;
|
||||
|
||||
const auto onQuerySetup = [](CurrentDocumentSymbolsRequest &request) {
|
||||
Q_UNUSED(request)
|
||||
};
|
||||
const auto onQueryDone = [resultStorage](const CurrentDocumentSymbolsRequest &request) {
|
||||
*resultStorage = request.currentDocumentSymbolsData();
|
||||
};
|
||||
|
||||
const auto onFilterSetup = [storage, resultStorage](Async<void> &async) {
|
||||
async.setConcurrentCallData(filterCurrentResults, *storage, *resultStorage);
|
||||
const auto onFilterSetup = [resultStorage](Async<void> &async) {
|
||||
async.setConcurrentCallData(filterCurrentResults, *LocatorStorage::storage(),
|
||||
*resultStorage);
|
||||
};
|
||||
|
||||
const Group root {
|
||||
resultStorage,
|
||||
CurrentDocumentSymbolsRequestTask(onQuerySetup, onQueryDone, CallDoneIf::Success),
|
||||
CurrentDocumentSymbolsRequestTask({}, onQueryDone, CallDoneIf::Success),
|
||||
AsyncTask<void>(onFilterSetup)
|
||||
};
|
||||
return {root, storage};
|
||||
return root;
|
||||
}
|
||||
|
||||
using MatcherCreator = std::function<Core::LocatorMatcherTask(Client *, int)>;
|
||||
using MatcherCreator = std::function<ExecutableItem(Client *, int)>;
|
||||
|
||||
static MatcherCreator creatorForType(MatcherType type)
|
||||
{
|
||||
|
@@ -11,6 +11,8 @@
|
||||
#include <lua/bindings/inheritance.h>
|
||||
#include <lua/luaengine.h>
|
||||
|
||||
#include <lua/bindings/async.h>
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
|
||||
@@ -18,6 +20,7 @@
|
||||
#include <projectexplorer/projectmanager.h>
|
||||
|
||||
#include <utils/commandline.h>
|
||||
#include <utils/guardedcallback.h>
|
||||
#include <utils/layoutbuilder.h>
|
||||
|
||||
#include <QJsonDocument>
|
||||
@@ -207,6 +210,8 @@ public:
|
||||
TransportType m_transportType{TransportType::StdIO};
|
||||
std::function<expected_str<void>(CommandLine &)> m_cmdLineCallback;
|
||||
std::function<expected_str<void>(QString &)> m_initOptionsCallback;
|
||||
sol::function m_asyncInitOptions;
|
||||
bool m_isUpdatingAsyncOptions{false};
|
||||
AspectContainer *m_aspects{nullptr};
|
||||
QString m_name;
|
||||
Utils::Id m_settingsTypeId;
|
||||
@@ -324,6 +329,13 @@ public:
|
||||
&LanguageClientManager::clientRemoved,
|
||||
this,
|
||||
&LuaClientWrapper::onClientRemoved);
|
||||
|
||||
if (auto asyncInit = options.get<sol::optional<sol::function>>(
|
||||
"initializationOptionsAsync")) {
|
||||
m_asyncInitOptions = *asyncInit;
|
||||
QMetaObject::invokeMethod(
|
||||
this, &LuaClientWrapper::updateAsyncOptions, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void onClientRemoved(Client *c, bool unexpected)
|
||||
@@ -462,6 +474,25 @@ public:
|
||||
clients.front()->sendMessage(request);
|
||||
}
|
||||
|
||||
void updateAsyncOptions()
|
||||
{
|
||||
if (m_isUpdatingAsyncOptions)
|
||||
return;
|
||||
QTC_ASSERT(m_asyncInitOptions, return);
|
||||
m_isUpdatingAsyncOptions = true;
|
||||
std::function<void(sol::object)> cb = guardedCallback(this, [this](sol::object options) {
|
||||
if (options.is<sol::table>())
|
||||
m_initializationOptions = ::Lua::toJsonString(options.as<sol::table>());
|
||||
else if (options.is<QString>())
|
||||
m_initializationOptions = options.as<QString>();
|
||||
|
||||
emit optionsChanged();
|
||||
m_isUpdatingAsyncOptions = false;
|
||||
});
|
||||
|
||||
::Lua::Async::start<sol::object>(m_asyncInitOptions, cb);
|
||||
}
|
||||
|
||||
void updateOptions()
|
||||
{
|
||||
if (m_cmdLineCallback) {
|
||||
@@ -479,6 +510,8 @@ public:
|
||||
// optionsChanged() needs to be called for it as well, but only once per updateOptions()
|
||||
emit optionsChanged();
|
||||
}
|
||||
if (m_asyncInitOptions)
|
||||
updateAsyncOptions();
|
||||
}
|
||||
|
||||
static CommandLine cmdFromTable(const sol::table &tbl)
|
||||
|
@@ -4,7 +4,6 @@ add_qtc_plugin(Lua
|
||||
PUBLIC_DEFINES LUA_AVAILABLE
|
||||
SOURCES
|
||||
bindings/action.cpp
|
||||
bindings/async.cpp
|
||||
bindings/async.h
|
||||
bindings/core.cpp
|
||||
bindings/fetch.cpp
|
||||
@@ -49,7 +48,9 @@ if(TARGET Lua)
|
||||
qt_add_resources(Lua lua_script_rcc
|
||||
PREFIX "/lua"
|
||||
FILES
|
||||
scripts/async.lua
|
||||
scripts/ilua.lua
|
||||
scripts/inspect.lua
|
||||
)
|
||||
|
||||
set_source_files_properties(luauibindings.cpp PROPERTY SKIP_AUTOMOC ON PROPERTY SKIP_AUTOGEN ON)
|
||||
|
@@ -430,6 +430,10 @@ void setupGuiModule()
|
||||
&Widget::activateWindow,
|
||||
"close",
|
||||
&Widget::close,
|
||||
"visible",
|
||||
sol::property(&Widget::isVisible, &Widget::setVisible),
|
||||
"enabled",
|
||||
sol::property(&Widget::isEnabled, &Widget::setEnabled),
|
||||
sol::base_classes,
|
||||
sol::bases<Object, Thing>());
|
||||
|
||||
|
@@ -28,15 +28,28 @@ void setupProjectModule()
|
||||
|
||||
sol::table result = lua.create_table();
|
||||
|
||||
result.new_usertype<Kit>(
|
||||
"Kit",
|
||||
sol::no_constructor,
|
||||
"supportedPlatforms",
|
||||
[](Kit *kit) {
|
||||
const auto set = kit->supportedPlatforms();
|
||||
return QList<Utils::Id>(set.constBegin(), set.constEnd());
|
||||
});
|
||||
|
||||
result.new_usertype<RunConfiguration>(
|
||||
"RunConfiguration",
|
||||
sol::no_constructor,
|
||||
"runnable",
|
||||
sol::property(&RunConfiguration::runnable));
|
||||
sol::property(&RunConfiguration::runnable),
|
||||
"kit",
|
||||
sol::property(&RunConfiguration::kit));
|
||||
|
||||
result.new_usertype<Project>(
|
||||
"Project",
|
||||
sol::no_constructor,
|
||||
"displayName",
|
||||
sol::property(&Project::displayName),
|
||||
"directory",
|
||||
sol::property(&Project::projectDirectory),
|
||||
"activeRunConfiguration",
|
||||
@@ -53,7 +66,8 @@ void setupProjectModule()
|
||||
};
|
||||
|
||||
result["runStartupProject"] =
|
||||
[guard](const sol::optional<ProcessRunData> &runnable) {
|
||||
[guard](const sol::optional<ProcessRunData> &runnable,
|
||||
const sol::optional<QString> &displayName) {
|
||||
auto project = ProjectManager::instance()->startupProject();
|
||||
if (!project)
|
||||
throw sol::error("No startup project");
|
||||
@@ -72,6 +86,9 @@ void setupProjectModule()
|
||||
rc->setEnvironment(runnable->environment);
|
||||
}
|
||||
|
||||
if (displayName)
|
||||
rc->setDisplayName(displayName.value());
|
||||
|
||||
BuildForRunConfigStatus status = BuildManager::potentiallyBuildForRunConfig(
|
||||
runConfiguration);
|
||||
|
||||
@@ -96,9 +113,32 @@ void setupProjectModule()
|
||||
}
|
||||
};
|
||||
|
||||
result["stopRunConfigurationsByName"] =
|
||||
[](const QString &displayName, const std::optional<bool> &force) -> int {
|
||||
const auto runControls = ProjectExplorerPlugin::instance()->allRunControls();
|
||||
|
||||
int stoppedCount = 0;
|
||||
for (const auto rc : runControls) {
|
||||
if (rc && rc->displayName() == displayName) {
|
||||
stoppedCount++;
|
||||
|
||||
if (force.has_value() && force.value()) {
|
||||
rc->forceStop();
|
||||
} else {
|
||||
rc->initiateStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return stoppedCount;
|
||||
};
|
||||
|
||||
result["RunMode"] = lua.create_table_with(
|
||||
"Normal", Constants::NORMAL_RUN_MODE, "Debug", Constants::DEBUG_RUN_MODE);
|
||||
|
||||
result["Platforms"] = lua.create_table_with(
|
||||
"Desktop", Utils::Id(Constants::DESKTOP_DEVICE_TYPE));
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
|
@@ -5,10 +5,14 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <utils/stringutils.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QCompleter>
|
||||
#include <QDir>
|
||||
#include <QFileDevice>
|
||||
#include <QStandardPaths>
|
||||
|
||||
namespace Lua::Internal {
|
||||
|
||||
@@ -27,29 +31,27 @@ void setupQtModule()
|
||||
"currentCompletion",
|
||||
&QCompleter::currentCompletion,
|
||||
"completionMode",
|
||||
sol::property(&QCompleter::completionMode,
|
||||
[](QCompleter *c, QCompleter::CompletionMode mode) {
|
||||
c->setCompletionMode(mode);
|
||||
}),
|
||||
sol::property(
|
||||
&QCompleter::completionMode,
|
||||
[](QCompleter *c, QCompleter::CompletionMode mode) { c->setCompletionMode(mode); }),
|
||||
"onActivated",
|
||||
sol::property([guard = pluginSpec](QCompleter &obj, sol::function callback) {
|
||||
QObject::connect(&obj,
|
||||
QOverload<const QString &>::of(&QCompleter::activated),
|
||||
guard->connectionGuard.get(),
|
||||
[callback](const QString &arg) {
|
||||
void_safe_call(callback, arg);
|
||||
});})
|
||||
);
|
||||
QObject::connect(
|
||||
&obj,
|
||||
QOverload<const QString &>::of(&QCompleter::activated),
|
||||
guard->connectionGuard.get(),
|
||||
[callback](const QString &arg) { void_safe_call(callback, arg); });
|
||||
}));
|
||||
|
||||
qt.new_usertype<QClipboard>(
|
||||
"QClipboard",
|
||||
sol::call_constructor,
|
||||
&QApplication::clipboard,
|
||||
sol::no_constructor,
|
||||
"text",
|
||||
sol::property([](QClipboard &self) { return self.text(); },
|
||||
[](QClipboard &self, const QString &value) { self.setText(value); })
|
||||
);
|
||||
sol::property(
|
||||
[](QClipboard &self) { return self.text(); },
|
||||
[](QClipboard &, const QString &text) { Utils::setClipboardAndSelection(text); }));
|
||||
|
||||
qt["clipboard"] = &QApplication::clipboard;
|
||||
|
||||
mirrorEnum(qt, QMetaEnum::fromType<QCompleter::CompletionMode>(), "QCompleterCompletionMode");
|
||||
|
||||
@@ -110,6 +112,48 @@ void setupQtModule()
|
||||
"NoSort", QDir::NoSort
|
||||
)
|
||||
);
|
||||
|
||||
qt["QFileDevice"] = lua.create_table_with(
|
||||
"Permission", lua.create_table_with(
|
||||
"ReadOwner", QFileDevice::ReadOwner,
|
||||
"ReadUser", QFileDevice::ReadUser,
|
||||
"ReadGroup", QFileDevice::ReadGroup,
|
||||
"ReadOther", QFileDevice::ReadOther,
|
||||
"WriteOwner", QFileDevice::WriteOwner,
|
||||
"WriteUser", QFileDevice::WriteUser,
|
||||
"WriteGroup", QFileDevice::WriteGroup,
|
||||
"WriteOther", QFileDevice::WriteOther,
|
||||
"ExeOwner", QFileDevice::ExeOwner,
|
||||
"ExeUser", QFileDevice::ExeUser,
|
||||
"ExeGroup", QFileDevice::ExeGroup,
|
||||
"ExeOther", QFileDevice::ExeOther
|
||||
)
|
||||
);
|
||||
|
||||
qt["QStandardPaths"] = lua.create_table_with(
|
||||
"StandardLocation", lua.create_table_with(
|
||||
"DesktopLocation", QStandardPaths::DesktopLocation,
|
||||
"DocumentsLocation", QStandardPaths::DocumentsLocation,
|
||||
"FontsLocation", QStandardPaths::FontsLocation,
|
||||
"ApplicationsLocation", QStandardPaths::ApplicationsLocation,
|
||||
"MusicLocation", QStandardPaths::MusicLocation,
|
||||
"MoviesLocation", QStandardPaths::MoviesLocation,
|
||||
"PicturesLocation", QStandardPaths::PicturesLocation,
|
||||
"TempLocation", QStandardPaths::TempLocation,
|
||||
"HomeLocation", QStandardPaths::HomeLocation,
|
||||
"AppLocalDataLocation", QStandardPaths::AppLocalDataLocation,
|
||||
"CacheLocation", QStandardPaths::CacheLocation,
|
||||
"GenericDataLocation", QStandardPaths::GenericDataLocation,
|
||||
"RuntimeLocation", QStandardPaths::RuntimeLocation,
|
||||
"ConfigLocation", QStandardPaths::ConfigLocation,
|
||||
"DownloadLocation", QStandardPaths::DownloadLocation,
|
||||
"GenericCacheLocation", QStandardPaths::GenericCacheLocation,
|
||||
"GenericConfigLocation", QStandardPaths::GenericConfigLocation,
|
||||
"AppDataLocation", QStandardPaths::AppDataLocation,
|
||||
"AppConfigLocation", QStandardPaths::AppConfigLocation,
|
||||
"PublicShareLocation", QStandardPaths::PublicShareLocation,
|
||||
"TemplatesLocation", QStandardPaths::TemplatesLocation
|
||||
));
|
||||
// clang-format on
|
||||
|
||||
return qt;
|
||||
|
@@ -60,6 +60,7 @@ void setupProcessModule()
|
||||
const auto stdOut = parameter.get<std::optional<sol::function>>("stdout");
|
||||
const auto stdErr = parameter.get<std::optional<sol::function>>("stderr");
|
||||
const auto stdIn = parameter.get<sol::optional<QString>>("stdin");
|
||||
const auto onFinished = parameter.get<std::optional<sol::function>>("onFinished");
|
||||
|
||||
auto p = std::make_unique<Process>();
|
||||
|
||||
@@ -86,6 +87,16 @@ void setupProcessModule()
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
if (onFinished) {
|
||||
// clang-format off
|
||||
QObject::connect(p.get(), &Process::done,
|
||||
p.get(),
|
||||
[p = p.get(), cb = *onFinished]() {
|
||||
void_safe_call(cb);
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
return p;
|
||||
};
|
||||
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <utils/futuresynchronizer.h>
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/icon.h>
|
||||
#include <utils/id.h>
|
||||
#include <utils/processinterface.h>
|
||||
|
||||
#include <QDesktopServices>
|
||||
@@ -93,6 +94,10 @@ void setupUtilsModule()
|
||||
|
||||
utils["pid"] = QCoreApplication::applicationPid();
|
||||
|
||||
utils.new_usertype<Utils::Id>(
|
||||
"Id",
|
||||
sol::no_constructor);
|
||||
|
||||
auto hostOsInfoType = utils.new_usertype<HostOsInfo>("HostOsInfo");
|
||||
hostOsInfoType["isWindowsHost"] = &HostOsInfo::isWindowsHost;
|
||||
hostOsInfoType["isMacHost"] = &HostOsInfo::isMacHost;
|
||||
@@ -161,7 +166,15 @@ void setupUtilsModule()
|
||||
"resolvePath",
|
||||
sol::overload(
|
||||
[](const FilePath &p, const QString &path) { return p.resolvePath(path); },
|
||||
[](const FilePath &p, const FilePath &path) { return p.resolvePath(path); }));
|
||||
[](const FilePath &p, const FilePath &path) { return p.resolvePath(path); }),
|
||||
"permissions",
|
||||
[](FilePath& p) {
|
||||
return static_cast<QFileDevice::Permission>(p.permissions().toInt());
|
||||
},
|
||||
"setPermissions",
|
||||
[](FilePath& p, QFileDevice::Permission permissions) {
|
||||
p.setPermissions(static_cast<QFile::Permissions>(permissions));
|
||||
});
|
||||
|
||||
utils["FilePath"]["dirEntries_cb"] = utils["__dirEntries_cb__"];
|
||||
utils["FilePath"]["dirEntries"] = wrap(utils["__dirEntries_cb__"]);
|
||||
@@ -169,6 +182,34 @@ void setupUtilsModule()
|
||||
utils["FilePath"]["searchInPath_cb"] = utils["__searchInPath_cb__"];
|
||||
utils["FilePath"]["searchInPath"] = wrap(utils["__searchInPath_cb__"]);
|
||||
|
||||
utils["standardLocations"] = [](QStandardPaths::StandardLocation location) {
|
||||
const auto locationsStrings = QStandardPaths::standardLocations(
|
||||
static_cast<QStandardPaths::StandardLocation>(location));
|
||||
|
||||
QList<FilePath> locationsPaths;
|
||||
std::transform(locationsStrings.constBegin(), locationsStrings.constEnd(),
|
||||
std::back_inserter(locationsPaths), &FilePath::fromString);
|
||||
return locationsPaths;
|
||||
};
|
||||
utils["standardLocation"] =
|
||||
[](QStandardPaths::StandardLocation location) -> sol::optional<FilePath> {
|
||||
const auto paths = QStandardPaths::standardLocations(
|
||||
static_cast<QStandardPaths::StandardLocation>(location));
|
||||
if (paths.isEmpty())
|
||||
return sol::nullopt;
|
||||
|
||||
return FilePath::fromString(paths.first());
|
||||
};
|
||||
utils["writableLocation"] =
|
||||
[](QStandardPaths::StandardLocation location) -> sol::optional<FilePath> {
|
||||
const auto path = QStandardPaths::writableLocation(
|
||||
static_cast<QStandardPaths::StandardLocation>(location));
|
||||
if (path.isEmpty())
|
||||
return sol::nullopt;
|
||||
|
||||
return FilePath::fromString(path);
|
||||
};
|
||||
|
||||
utils.new_usertype<CommandLine>(
|
||||
"CommandLine",
|
||||
sol::call_constructor,
|
||||
|
@@ -39,7 +39,6 @@ QtcPlugin {
|
||||
|
||||
files: [
|
||||
"action.cpp",
|
||||
"async.cpp",
|
||||
"core.cpp",
|
||||
"fetch.cpp",
|
||||
"gui.cpp",
|
||||
|
@@ -72,7 +72,9 @@ QObject *ScriptPluginSpec::setup(
|
||||
"name",
|
||||
sol::property([](ScriptPluginSpec &self) { return self.name; }),
|
||||
"pluginDirectory",
|
||||
sol::property([pluginLocation]() { return pluginLocation; }));
|
||||
sol::property([pluginLocation]() { return pluginLocation; }),
|
||||
"appDataPath",
|
||||
sol::property([appDataPath]() { return appDataPath; }));
|
||||
|
||||
auto guardObject = std::make_unique<QObject>();
|
||||
auto guardObjectPtr = guardObject.get();
|
||||
@@ -169,6 +171,23 @@ void registerProvider(const QString &packageName, const PackageProvider &provide
|
||||
d->m_providers[packageName] = provider;
|
||||
}
|
||||
|
||||
void registerProvider(const QString &packageName, const FilePath &path)
|
||||
{
|
||||
registerProvider(packageName, [path](sol::state_view lua) -> sol::object {
|
||||
auto content = path.fileContents();
|
||||
if (!content)
|
||||
throw sol::error(content.error().toStdString());
|
||||
|
||||
sol::protected_function_result res
|
||||
= lua.script(content->data(), path.fileName().toStdString());
|
||||
if (!res.valid()) {
|
||||
sol::error err = res;
|
||||
throw err;
|
||||
}
|
||||
return res.get<sol::table>(0);
|
||||
});
|
||||
}
|
||||
|
||||
void autoRegister(const std::function<void(sol::state_view)> ®isterFunction)
|
||||
{
|
||||
d->m_autoProviders.append(registerFunction);
|
||||
|
@@ -51,6 +51,7 @@ LUA_EXPORT Utils::expected_str<sol::protected_function> prepareSetup(
|
||||
sol::state_view lua, const LuaPluginSpec &pluginSpec);
|
||||
|
||||
LUA_EXPORT void registerProvider(const QString &packageName, const PackageProvider &provider);
|
||||
LUA_EXPORT void registerProvider(const QString &packageName, const Utils::FilePath &path);
|
||||
LUA_EXPORT void autoRegister(const std::function<void(sol::state_view)> ®isterFunction);
|
||||
LUA_EXPORT void registerHook(
|
||||
QString name, const std::function<void(sol::function, QObject *guard)> &hookProvider);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user