Merge remote-tracking branch 'origin/master' into 4.15

Change-Id: Ia313b9a8bf82940e496b7456801faf552fe4b022
This commit is contained in:
Eike Ziller
2021-02-24 19:42:30 +01:00
37 changed files with 343 additions and 102 deletions

View File

@@ -403,7 +403,7 @@ AndroidDeviceInfoList AvdManagerOutputParser::listVirtualDevices(const AndroidCo
avdList = parseAvdList(output);
} while (output.contains(avdManufacturerError));
for (const QString &avdPathStr : avdErrorPaths)
for (const QString &avdPathStr : qAsConst(avdErrorPaths))
AvdConfigEditManufacturerTag(avdPathStr, true);
return avdList;

View File

@@ -1494,7 +1494,7 @@ FilePath AndroidConfig::getJdkPath()
#endif // Q_OS_WIN
}
for (const QString &version : allVersions) {
for (const QString &version : qAsConst(allVersions)) {
settings->beginGroup(version);
jdkHome = FilePath::fromUserInput(settings->value("JavaHome").toString());
settings->endGroup();

View File

@@ -538,7 +538,7 @@ void AndroidRunnerWorker::asyncStartHelper()
forceStop();
asyncStartLogcat();
for (const QString &entry : m_beforeStartAdbCommands)
for (const QString &entry : qAsConst(m_beforeStartAdbCommands))
runAdb(entry.split(' ', Qt::SkipEmptyParts));
QStringList args({"shell", "am", "start"});
@@ -825,7 +825,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
m_debugServerProcess.reset();
// Run adb commands after application quit.
for (const QString &entry: m_afterFinishAdbCommands)
for (const QString &entry: qAsConst(m_afterFinishAdbCommands))
runAdb(entry.split(' ', Qt::SkipEmptyParts));
} else {
// In debugging cases this will be funneled to the engine to actually start

View File

@@ -566,7 +566,7 @@ void SdkManagerOutputParser::compilePackageAssociations()
deleteAlreadyInstalled(images);
// Associate the system images with sdk platforms.
for (AndroidSdkPackage *image : images) {
for (AndroidSdkPackage *image : qAsConst(images)) {
int imageApi = m_systemImages[image];
auto itr = std::find_if(m_packages.begin(), m_packages.end(),
[imageApi](const AndroidSdkPackage *p) {
@@ -1151,7 +1151,7 @@ void AndroidSdkManagerPrivate::parseCommonArguments(QFutureInterface<QString> &f
void AndroidSdkManagerPrivate::clearPackages()
{
for (AndroidSdkPackage *p : m_allPackages)
for (AndroidSdkPackage *p : qAsConst(m_allPackages))
delete p;
m_allPackages.clear();
}

View File

@@ -298,7 +298,7 @@ void AndroidSdkModel::selectMissingEssentials()
}
// Select SDK platform
for (const SdkPlatform *platform : m_sdkPlatforms) {
for (const SdkPlatform *platform : qAsConst(m_sdkPlatforms)) {
if (!platform->installedLocation().isEmpty()) {
pendingPkgs.removeOne(platform->sdkStylePath());
} else if (pendingPkgs.contains(platform->sdkStylePath()) &&

View File

@@ -154,7 +154,7 @@ SdkPlatform::SdkPlatform(QVersionNumber version, QString sdkStylePathStr, int ap
SdkPlatform::~SdkPlatform()
{
for (SystemImage *image : m_systemImages)
for (SystemImage *image : qAsConst(m_systemImages))
delete image;
m_systemImages.clear();
}

View File

@@ -177,7 +177,7 @@ void AvdDialog::updateDeviceDefinitionComboBox()
m_avdDialog.deviceDefinitionTypeComboBox->currentText());
m_avdDialog.deviceDefinitionComboBox->clear();
for (const DeviceDefinitionStruct &item : m_deviceDefinitionsList) {
for (const DeviceDefinitionStruct &item : qAsConst(m_deviceDefinitionsList)) {
if (item.deviceType == curDeviceType)
m_avdDialog.deviceDefinitionComboBox->addItem(item.name_id);
}
@@ -231,7 +231,7 @@ void AvdDialog::updateApiLevelComboBox()
});
m_avdDialog.targetApiComboBox->clear();
for (SystemImage *image : filteredList) {
for (SystemImage *image : qAsConst(filteredList)) {
QString imageString = "android-" % QString::number(image->apiLevel());
const QStringList imageSplits = image->sdkStylePath().split(';');
if (imageSplits.size() == 4)

View File

@@ -25,12 +25,21 @@
#include "javalanguageserver.h"
#include "androidconfigurations.h"
#include "androidconstants.h"
#include "androidmanager.h"
#include <languageclient/client.h>
#include <languageclient/languageclientinterface.h>
#include <languageclient/languageclientutils.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/environment.h>
#include <utils/pathchooser.h>
#include <utils/temporarydirectory.h>
#include <utils/variablechooser.h>
#include <QGridLayout>
@@ -39,7 +48,6 @@
using namespace Utils;
constexpr char languageServerKey[] = "languageServer";
constexpr char workspaceKey[] = "workspace";
namespace Android {
namespace Internal {
@@ -67,7 +75,6 @@ JLSSettingsWidget::JLSSettingsWidget(const JLSSettings *settings, QWidget *paren
, m_name(new QLineEdit(settings->m_name, this))
, m_java(new PathChooser(this))
, m_ls(new PathChooser(this))
, m_workspace(new PathChooser(this))
{
int row = 0;
auto *mainLayout = new QGridLayout;
@@ -88,11 +95,6 @@ JLSSettingsWidget::JLSSettingsWidget(const JLSSettings *settings, QWidget *paren
m_ls->setPath(QDir::toNativeSeparators(settings->m_languageServer));
mainLayout->addWidget(m_ls, row, 1);
mainLayout->addWidget(new QLabel(tr("Workspace:")), ++row, 0);
m_workspace->setExpectedKind(Utils::PathChooser::Directory);
m_workspace->setPath(QDir::toNativeSeparators(settings->m_workspace));
mainLayout->addWidget(m_workspace, row, 1);
setLayout(mainLayout);
}
@@ -117,9 +119,6 @@ bool JLSSettings::applyFromSettingsWidget(QWidget *widget)
changed |= m_languageServer != jlswidget->languageServer();
m_languageServer = jlswidget->languageServer();
changed |= m_workspace != jlswidget->workspace();
m_workspace = jlswidget->workspace();
changed |= m_executable != jlswidget->java();
m_executable = jlswidget->java();
@@ -130,8 +129,7 @@ bool JLSSettings::applyFromSettingsWidget(QWidget *widget)
"-noverify "
"-Xmx1G "
"-jar \"%1\" "
"-configuration \"%2\" "
"-data \"%3\"";
"-configuration \"%2\"";
QFileInfo languageServerFileInfo(m_languageServer);
QDir configDir = languageServerFileInfo.absoluteDir();
@@ -145,7 +143,7 @@ bool JLSSettings::applyFromSettingsWidget(QWidget *widget)
configDir.cd("config_mac");
}
if (configDir.exists()) {
arguments = arguments.arg(m_languageServer, configDir.absolutePath(), m_workspace);
arguments = arguments.arg(m_languageServer, configDir.absolutePath());
changed |= m_arguments != arguments;
m_arguments = arguments;
}
@@ -159,14 +157,13 @@ QWidget *JLSSettings::createSettingsWidget(QWidget *parent) const
bool JLSSettings::isValid() const
{
return StdIOSettings::isValid() && !m_languageServer.isEmpty() && !m_workspace.isEmpty();
return StdIOSettings::isValid() && !m_languageServer.isEmpty();
}
QVariantMap JLSSettings::toMap() const
{
QVariantMap map = StdIOSettings::toMap();
map.insert(languageServerKey, m_languageServer);
map.insert(workspaceKey, m_workspace);
return map;
}
@@ -174,7 +171,6 @@ void JLSSettings::fromMap(const QVariantMap &map)
{
StdIOSettings::fromMap(map);
m_languageServer = map[languageServerKey].toString();
m_workspace = map[workspaceKey].toString();
}
LanguageClient::BaseSettings *JLSSettings::copy() const
@@ -182,12 +178,39 @@ LanguageClient::BaseSettings *JLSSettings::copy() const
return new JLSSettings(*this);
}
class JLSInterface : public LanguageClient::StdIOClientInterface
{
public:
JLSInterface() = default;
QString workspaceDir() const { return m_workspaceDir.path(); }
private:
TemporaryDirectory m_workspaceDir = TemporaryDirectory("QtCreator-jls-XXXXXX");
};
LanguageClient::BaseClientInterface *JLSSettings::createInterface() const
{
auto interface = new JLSInterface();
interface->setExecutable(m_executable);
QString arguments = this->arguments();
arguments += QString(" -data \"%1\"").arg(interface->workspaceDir());
interface->setArguments(arguments);
return interface;
}
class JLSClient : public LanguageClient::Client
{
public:
using Client::Client;
void executeCommand(const LanguageServerProtocol::Command &command) override;
void setCurrentProject(ProjectExplorer::Project *project) override;
void updateProjectFiles();
void updateTarget(ProjectExplorer::Target *target);
private:
ProjectExplorer::Target *m_currentTarget = nullptr;
};
void JLSClient::executeCommand(const LanguageServerProtocol::Command &command)
@@ -206,6 +229,127 @@ void JLSClient::executeCommand(const LanguageServerProtocol::Command &command)
}
}
void JLSClient::setCurrentProject(ProjectExplorer::Project *project)
{
Client::setCurrentProject(project);
QTC_ASSERT(project, return);
updateTarget(project->activeTarget());
updateProjectFiles();
connect(project, &ProjectExplorer::Project::activeTargetChanged,
this, &JLSClient::updateTarget);
}
static void generateProjectFile(const FilePath &projectDir,
const QString &qtSrc,
const QString &projectName)
{
const FilePath projectFilePath = projectDir.pathAppended(".project");
QFile projectFile(projectFilePath.toString());
if (projectFile.open(QFile::Truncate | QFile::WriteOnly)) {
QXmlStreamWriter writer(&projectFile);
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeComment("Autogenerated by Qt Creator. "
"Changes to this file will not be taken into account.");
writer.writeStartElement("projectDescription");
writer.writeTextElement("name", projectName);
writer.writeStartElement("natures");
writer.writeTextElement("nature", "org.eclipse.jdt.core.javanature");
writer.writeEndElement(); // natures
writer.writeStartElement("linkedResources");
writer.writeStartElement("link");
writer.writeTextElement("name", "qtSrc");
writer.writeTextElement("type", "2");
writer.writeTextElement("location", qtSrc);
writer.writeEndElement(); // link
writer.writeEndElement(); // linkedResources
writer.writeEndElement(); // projectDescription
writer.writeEndDocument();
projectFile.close();
}
}
static void generateClassPathFile(const FilePath &projectDir,
const QString &sourceDir,
const QStringList &libs)
{
const FilePath classPathFilePath = projectDir.pathAppended(".classpath");
QFile classPathFile(classPathFilePath.toString());
if (classPathFile.open(QFile::Truncate | QFile::WriteOnly)) {
QXmlStreamWriter writer(&classPathFile);
writer.setAutoFormatting(true);
writer.writeStartDocument();
writer.writeComment("Autogenerated by Qt Creator. "
"Changes to this file will not be taken into account.");
writer.writeStartElement("classpath");
writer.writeEmptyElement("classpathentry");
writer.writeAttribute("kind", "src");
writer.writeAttribute("path", sourceDir);
writer.writeEmptyElement("classpathentry");
writer.writeAttribute("kind", "src");
writer.writeAttribute("path", "qtSrc");
for (const QString &lib : libs) {
writer.writeEmptyElement("classpathentry");
writer.writeAttribute("kind", "lib");
writer.writeAttribute("path", lib);
}
writer.writeEndElement(); // classpath
writer.writeEndDocument();
classPathFile.close();
}
}
void JLSClient::updateProjectFiles()
{
using namespace ProjectExplorer;
if (!m_currentTarget)
return;
if (Target *target = m_currentTarget) {
Kit *kit = m_currentTarget->kit();
if (DeviceTypeKitAspect::deviceTypeId(kit) != Android::Constants::ANDROID_DEVICE_TYPE)
return;
if (ProjectNode *node = project()->findNodeForBuildKey(target->activeBuildKey())) {
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(kit);
if (!version)
return;
const QString qtSrc = version->prefix().toString() + "/src/android/java/src";
const FilePath &projectDir = project()->rootProjectDirectory();
if (!projectDir.exists())
return;
const FilePath packageSourceDir = FilePath::fromVariant(
node->data(Constants::AndroidPackageSourceDir));
FilePath sourceDir = packageSourceDir.pathAppended("src");
if (!sourceDir.exists())
return;
sourceDir = sourceDir.relativeChildPath(projectDir);
const FilePath &sdkLocation = AndroidConfigurations::currentConfig().sdkLocation();
const QString &targetSDK = AndroidManager::buildTargetSDK(m_currentTarget);
const QString androidJar = QString("%1/platforms/%2/android.jar")
.arg(sdkLocation.toString(), targetSDK);
QStringList libs(androidJar);
QDir libDir(packageSourceDir.pathAppended("libs").toString());
libs << Utils::transform(libDir.entryInfoList({"*.jar"}, QDir::Files),
&QFileInfo::absoluteFilePath);
generateProjectFile(projectDir, qtSrc, project()->displayName());
generateClassPathFile(projectDir, sourceDir.toString(), libs);
}
}
}
void JLSClient::updateTarget(ProjectExplorer::Target *target)
{
if (m_currentTarget) {
disconnect(m_currentTarget, &ProjectExplorer::Target::parsingFinished,
this, &JLSClient::updateProjectFiles);
}
m_currentTarget = target;
if (m_currentTarget) {
connect(m_currentTarget, &ProjectExplorer::Target::parsingFinished,
this, &JLSClient::updateProjectFiles);
}
updateProjectFiles();
}
LanguageClient::Client *JLSSettings::createClient(LanguageClient::BaseClientInterface *interface) const
{
return new JLSClient(interface);

View File

@@ -42,9 +42,9 @@ public:
void fromMap(const QVariantMap &map) final;
LanguageClient::BaseSettings *copy() const final;
LanguageClient::Client *createClient(LanguageClient::BaseClientInterface *interface) const final;
LanguageClient::BaseClientInterface *createInterface() const override;
QString m_languageServer;
QString m_workspace;
private:
JLSSettings(const JLSSettings &other) = default;

View File

@@ -128,7 +128,7 @@ void ClangToolsUnitTests::testProject()
QVERIFY(waitForFinishedTool.wait(m_timeout));
// Check for errors
const QString errorText = waitForFinishedTool.takeFirst().first().toString();
const QString errorText = waitForFinishedTool.takeFirst().constFirst().toString();
const bool finishedSuccessfully = errorText.isEmpty();
if (!finishedSuccessfully)
qWarning("Error: %s", qPrintable(errorText));

View File

@@ -245,7 +245,7 @@ static FilePath qmakeFromCMakeCache(const CMakeConfig &config)
if (!qmakeLocationTxt.open(QIODevice::ReadOnly)) {
return FilePath();
}
FilePath qmakeLocation = FilePath::fromUtf8(qmakeLocationTxt.readLine().data());
FilePath qmakeLocation = FilePath::fromUtf8(qmakeLocationTxt.readLine().constData());
qCDebug(cmInputLog) << "qmake location: " << qmakeLocation.toUserOutput();
return qmakeLocation;

View File

@@ -100,6 +100,13 @@ Client::Client(BaseClientInterface *clientInterface)
&Client::rehighlight);
}
QString Client::name() const
{
if (m_project && !m_project->displayName().isEmpty())
return tr("%1 for %2").arg(m_displayName, m_project->displayName());
return m_displayName;
}
static void updateEditorToolBar(QList<TextEditor::TextDocument *> documents)
{
for (TextEditor::TextDocument *document : documents) {
@@ -790,6 +797,15 @@ void Client::projectOpened(ProjectExplorer::Project *project)
void Client::projectClosed(ProjectExplorer::Project *project)
{
if (sendWorkspceFolderChanges()) {
WorkspaceFoldersChangeEvent event;
event.setRemoved({WorkSpaceFolder(DocumentUri::fromFilePath(project->projectDirectory()),
project->displayName())});
DidChangeWorkspaceFoldersParams params;
params.setEvent(event);
DidChangeWorkspaceFoldersNotification change(params);
sendContent(change);
}
if (project == m_project) {
if (m_state == Initialized) {
shutdown();
@@ -797,16 +813,8 @@ void Client::projectClosed(ProjectExplorer::Project *project)
m_state = Shutdown; // otherwise the manager would try to restart this server
emit finished();
}
m_project = nullptr;
}
if (!sendWorkspceFolderChanges())
return;
WorkspaceFoldersChangeEvent event;
event.setRemoved({WorkSpaceFolder(DocumentUri::fromFilePath(project->projectDirectory()),
project->displayName())});
DidChangeWorkspaceFoldersParams params;
params.setEvent(event);
DidChangeWorkspaceFoldersNotification change(params);
sendContent(change);
}
void Client::setSupportedLanguage(const LanguageFilter &filter)
@@ -1260,6 +1268,8 @@ void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
bool Client::sendWorkspceFolderChanges() const
{
if (!reachable())
return false;
if (m_dynamicCapabilities.isRegistered(
DidChangeWorkspaceFoldersNotification::methodName).value_or(false)) {
return true;

View File

@@ -87,7 +87,7 @@ public:
// basic properties
Utils::Id id() const { return m_id; }
void setName(const QString &name) { m_displayName = name; }
QString name() const { return m_displayName; }
QString name() const;
void sendContent(const LanguageServerProtocol::IContent &content);
void cancelRequest(const LanguageServerProtocol::MessageId &id);
@@ -134,10 +134,10 @@ public:
bool documentUpdatePostponed(const Utils::FilePath &fileName) const;
// workspace control
void setCurrentProject(ProjectExplorer::Project *project);
virtual void setCurrentProject(ProjectExplorer::Project *project);
const ProjectExplorer::Project *project() const;
void projectOpened(ProjectExplorer::Project *project);
void projectClosed(ProjectExplorer::Project *project);
virtual void projectOpened(ProjectExplorer::Project *project);
virtual void projectClosed(ProjectExplorer::Project *project);
// commands
void requestCodeActions(const LanguageServerProtocol::DocumentUri &uri,

View File

@@ -89,9 +89,7 @@ void BaseClientInterface::parseData(const QByteArray &data)
}
}
StdIOClientInterface::StdIOClientInterface(const QString &executable, const QString &arguments)
: m_executable(executable)
, m_arguments(arguments)
StdIOClientInterface::StdIOClientInterface()
{
connect(&m_process, &QProcess::readyReadStandardError,
this, &StdIOClientInterface::readError);
@@ -99,9 +97,6 @@ StdIOClientInterface::StdIOClientInterface(const QString &executable, const QStr
this, &StdIOClientInterface::readOutput);
connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &StdIOClientInterface::onProcessFinished);
m_process.setArguments(Utils::QtcProcess::splitArgs(m_arguments));
m_process.setProgram(m_executable);
}
StdIOClientInterface::~StdIOClientInterface()
@@ -109,11 +104,6 @@ StdIOClientInterface::~StdIOClientInterface()
Utils::SynchronousProcess::stopProcess(m_process);
}
bool StdIOClientInterface::needsRestart(const StdIOSettings *settings) const
{
return m_executable != settings->m_executable || m_arguments != settings->arguments();
}
bool StdIOClientInterface::start()
{
m_process.start();
@@ -124,6 +114,16 @@ bool StdIOClientInterface::start()
return true;
}
void StdIOClientInterface::setExecutable(const QString &executable)
{
m_process.setProgram(executable);
}
void StdIOClientInterface::setArguments(const QString &arguments)
{
m_process.setArguments(Utils::QtcProcess::splitArgs(arguments));
}
void StdIOClientInterface::setWorkingDirectory(const QString &workingDirectory)
{
m_process.setWorkingDirectory(workingDirectory);

View File

@@ -25,6 +25,8 @@
#pragma once
#include "languageclient_global.h"
#include <languageserverprotocol/basemessage.h>
#include <QBuffer>
@@ -34,13 +36,13 @@ namespace LanguageClient {
class StdIOSettings;
class BaseClientInterface : public QObject
class LANGUAGECLIENT_EXPORT BaseClientInterface : public QObject
{
Q_OBJECT
public:
BaseClientInterface();
virtual ~BaseClientInterface();
~BaseClientInterface() override;
void sendMessage(const LanguageServerProtocol::BaseMessage &message);
virtual bool start() { return true; }
@@ -61,23 +63,23 @@ private:
LanguageServerProtocol::BaseMessage m_currentMessage;
};
class StdIOClientInterface : public BaseClientInterface
class LANGUAGECLIENT_EXPORT StdIOClientInterface : public BaseClientInterface
{
Q_OBJECT
public:
StdIOClientInterface(const QString &executable, const QString &arguments);
StdIOClientInterface();
~StdIOClientInterface() override;
StdIOClientInterface() = delete;
StdIOClientInterface(const StdIOClientInterface &) = delete;
StdIOClientInterface(StdIOClientInterface &&) = delete;
StdIOClientInterface &operator=(const StdIOClientInterface &) = delete;
StdIOClientInterface &operator=(StdIOClientInterface &&) = delete;
bool needsRestart(const StdIOSettings *settings) const;
bool start() override;
// These functions only have an effect if they are called before start
void setExecutable(const QString &executable);
void setArguments(const QString &arguments);
void setWorkingDirectory(const QString &workingDirectory);
protected:
@@ -88,9 +90,6 @@ private:
void readError();
void readOutput();
void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
const QString m_executable;
const QString m_arguments;
};
} // namespace LanguageClient

View File

@@ -472,13 +472,17 @@ void LanguageClientManager::documentOpened(Core::IDocument *document)
continue;
// check whether we already have a client running for this project
if (Utils::findOrDefault(clients,
[project](const QPointer<Client> &client) {
return client->project() == project;
})) {
continue;
Client *clientForProject = Utils::findOrDefault(clients,
[project](Client *client) {
return client->project()
== project;
});
if (!clientForProject) {
clientForProject = startClient(setting, project);
clients << clientForProject;
}
clients << startClient(setting, project);
QTC_ASSERT(clientForProject, continue);
openDocumentWithClient(textDocument, clientForProject);
}
} else if (setting->m_startBehavior == BaseSettings::RequiresFile && clients.isEmpty()) {
clients << startClient(setting);

View File

@@ -722,7 +722,10 @@ Utils::CommandLine StdIOSettings::command() const
BaseClientInterface *StdIOSettings::createInterface() const
{
return new StdIOClientInterface(m_executable, arguments());
auto interface = new StdIOClientInterface;
interface->setExecutable(m_executable);
interface->setArguments(arguments());
return interface;
}
class JsonTreeItemDelegate : public QStyledItemDelegate

View File

@@ -62,7 +62,7 @@ void OutputParserTester::testParsing(const QString &lines,
{
const auto terminator = new TestTerminator(this);
if (!lineParsers().isEmpty())
terminator->setRedirectionDetector(lineParsers().last());
terminator->setRedirectionDetector(lineParsers().constLast());
addLineParser(terminator);
reset();
@@ -113,7 +113,7 @@ TestTerminator::TestTerminator(OutputParserTester *t) :
m_tester(t)
{
if (!t->lineParsers().isEmpty()) {
for (const Utils::FilePath &searchDir : t->lineParsers().first()->searchDirectories())
for (const Utils::FilePath &searchDir : t->lineParsers().constFirst()->searchDirectories())
addSearchDir(searchDir);
}
}

View File

@@ -96,6 +96,18 @@ QHash<int, QByteArray> ItemLibraryCategoriesModel::roleNames() const
return m_roleNames;
}
void ItemLibraryCategoriesModel::expandCategories(bool expand)
{
int i = 0;
for (const auto &category : std::as_const(m_categoryList)) {
if (category->categoryExpanded() != expand) {
category->setExpanded(expand);
emit dataChanged(index(i), index(i), {m_roleNames.key("categoryExpanded")});
}
++i;
}
}
void ItemLibraryCategoriesModel::addCategory(ItemLibraryCategory *category)
{
m_categoryList.append(category);

View File

@@ -48,6 +48,7 @@ public:
QHash<int, QByteArray> roleNames() const override;
void addCategory(ItemLibraryCategory *category);
void expandCategories(bool expand = true);
const QList<QPointer<ItemLibraryCategory>> &categorySections() const;

View File

@@ -78,6 +78,10 @@ bool ItemLibraryCategory::updateItemVisibility(const QString &searchText, bool *
hasVisibleItems = true;
}
// expand category if it has an item matching search criteria
if (hasVisibleItems && !categoryExpanded())
setExpanded(true);
return hasVisibleItems;
}

View File

@@ -80,25 +80,28 @@ QObject *ItemLibraryImport::categoryModel()
return &m_categoryModel;
}
void ItemLibraryImport::expandCategories(bool expand)
{
m_categoryModel.expandCategories(expand);
}
bool ItemLibraryImport::updateCategoryVisibility(const QString &searchText, bool *changed)
{
bool hasVisibleItems = false;
bool hasVisibleCategories = false;
*changed = false;
for (const auto &category : m_categoryModel.categorySections()) {
bool categoryChanged = false;
hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged);
bool hasVisibleItems = category->updateItemVisibility(searchText, &categoryChanged);
categoryChanged |= category->setVisible(hasVisibleItems);
*changed |= categoryChanged;
*changed |= hasVisibleItems;
if (hasVisibleItems)
hasVisibleCategories = true;
}
if (*changed)
m_categoryModel.resetModel();
return hasVisibleItems;
return hasVisibleCategories;
}
Import ItemLibraryImport::importEntry() const

View File

@@ -63,6 +63,7 @@ public:
void setImportUsed(bool importUsed);
void sortCategorySections();
void setImportExpanded(bool expanded = true);
void expandCategories(bool expand = true);
static QString userComponentsTitle();

View File

@@ -61,34 +61,28 @@ bool ItemLibraryModel::loadExpandedState(const QString &sectionName)
void ItemLibraryModel::expandAll()
{
bool changed = false;
int i = 0;
for (const QPointer<ItemLibraryImport> &import : std::as_const(m_importList)) {
if (import->hasCategories() && !import->importExpanded()) {
changed = true;
if (!import->importExpanded()) {
import->setImportExpanded();
emit dataChanged(index(i), index(i), {m_roleNames.key("importExpanded")});
saveExpandedState(true, import->importUrl());
}
}
if (changed) {
beginResetModel();
endResetModel();
import->expandCategories(true);
++i;
}
}
void ItemLibraryModel::collapseAll()
{
bool changed = false;
int i = 0;
for (const QPointer<ItemLibraryImport> &import : std::as_const(m_importList)) {
if (import->hasCategories() && import->importExpanded()) {
changed = true;
import->setImportExpanded(false);
emit dataChanged(index(i), index(i), {m_roleNames.key("importExpanded")});
saveExpandedState(false, import->importUrl());
}
}
if (changed) {
beginResetModel();
endResetModel();
++i;
}
}
@@ -329,9 +323,18 @@ void ItemLibraryModel::updateVisibility(bool *changed)
{
for (ItemLibraryImport *import : std::as_const(m_importList)) {
bool categoryChanged = false;
import->updateCategoryVisibility(m_searchText, &categoryChanged);
bool hasVisibleItems = import->updateCategoryVisibility(m_searchText, &categoryChanged);
*changed |= categoryChanged;
// expand import if it has an item matching search criteria
if (hasVisibleItems && !import->importExpanded())
import->setImportExpanded();
}
if (changed) {
beginResetModel();
endResetModel();
}
}

View File

@@ -275,6 +275,7 @@ void ItemLibraryWidget::handleAddImport(int index)
m_model->changeImports({import}, {});
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
m_stackedWidget->setCurrentIndex(0); // switch to the Components view after import is added
updateSearch();
}
void ItemLibraryWidget::delayedUpdateModel()

View File

@@ -134,7 +134,7 @@ public:
}
}
void storeIcon(Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QIcon &icon)
void storeIcon(Utils::SmallStringView name, Sqlite::TimeStamp newTimeStamp, const QIcon &icon) override
{
try {
Sqlite::ImmediateTransaction transaction{database};

View File

@@ -337,7 +337,9 @@ void SubComponentManager::registerQmlFile(const QFileInfo &fileInfo, const QStri
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setType(componentName.toUtf8());
itemLibraryEntry.setName(baseComponentName);
#ifndef QMLDESIGNER_TEST
itemLibraryEntry.setCategory(ItemLibraryImport::userComponentsTitle());
#endif
itemLibraryEntry.setCustomComponentSource(fileInfo.absoluteFilePath());
if (!qualifier.isEmpty()) {
itemLibraryEntry.setRequiredImport(fixedQualifier);