Merge remote-tracking branch 'origin/15.0'

Change-Id: I1894a1f935fa8bfdc4126db35e3f94849527866a
This commit is contained in:
Eike Ziller
2024-10-08 14:00:39 +02:00
185 changed files with 1709 additions and 1863 deletions

View File

@@ -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
*/

View File

@@ -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"
}
]

View File

@@ -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}

View File

@@ -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}"
},

View File

@@ -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",

View File

@@ -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}

View File

@@ -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}"
},

View File

@@ -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>

View File

@@ -15352,12 +15352,12 @@ Par exemple, «&#xa0;Revision&#xa0;: 15&#xa0;» 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>

View File

@@ -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);

View File

@@ -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")

View File

@@ -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.

View File

@@ -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())));
};
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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() ,

View File

@@ -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

View File

@@ -55,8 +55,6 @@ QtcPlugin {
"androidqtversion.h",
"androidrunconfiguration.cpp",
"androidrunconfiguration.h",
"androidruncontrol.cpp",
"androidruncontrol.h",
"androidrunner.cpp",
"androidrunner.h",
"androidrunnerworker.cpp",

View File

@@ -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;
}

View File

@@ -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"

View File

@@ -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);
}
};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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",

View File

@@ -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>

View File

@@ -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

View File

@@ -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(); });

View File

@@ -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; });
}

View File

@@ -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()

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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";

View File

@@ -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)

View File

@@ -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 &currentFileName)
static QList<IndexItem::Ptr> itemsOfCurrentDocument(const FilePath &currentFileName)
{
if (currentFileName.isEmpty())
return {};
@@ -188,7 +185,7 @@ QList<IndexItem::Ptr> itemsOfCurrentDocument(const FilePath &currentFileName)
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 &currentFileName)
{
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)
{

View File

@@ -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())
{

View File

@@ -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")};

View File

@@ -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

View File

@@ -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();

View File

@@ -111,6 +111,9 @@ private:
void handleEngineStarted(Internal::DebuggerEngine *engine);
void handleEngineFinished(Internal::DebuggerEngine *engine);
void startCoreFileSetupIfNeededAndContinueStartup();
void continueAfterCoreFileSetup();
void startTerminalIfNeededAndContinueStartup();
void continueAfterTerminalStart();

View File

@@ -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());

View File

@@ -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 {

View File

@@ -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

View File

@@ -50,5 +50,6 @@ enum Size {
SizeBig,
};
QPixmap itemIcon(const QModelIndex &index, Size size);
QPixmap itemBadge(const QModelIndex &index, Size size);
} // ExtensionManager::Internal

View File

@@ -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

View File

@@ -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();

View File

@@ -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)

View File

@@ -113,6 +113,7 @@ GitSettings::GitSettings()
colorLog.setSettingsKey("ColorLog");
colorLog.setDefaultValue(true);
allBranches.setSettingsKey("AllBranches");
firstParent.setSettingsKey("FirstParent");
followRenames.setSettingsKey("FollowRenames");

View File

@@ -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};

View File

@@ -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;

View File

@@ -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()

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)
{

View File

@@ -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)

View File

@@ -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)

View File

@@ -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>());

View File

@@ -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;
});

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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,

View File

@@ -39,7 +39,6 @@ QtcPlugin {
files: [
"action.cpp",
"async.cpp",
"core.cpp",
"fetch.cpp",
"gui.cpp",

View File

@@ -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)> &registerFunction)
{
d->m_autoProviders.append(registerFunction);

View File

@@ -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)> &registerFunction);
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