forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/6.0'
Conflicts: cmake/QtCreatorIDEBranding.cmake qbs/modules/qtc/qtc.qbs qtcreator_ide_branding.pri Change-Id: I32991a77e52831dd2e24cf4a51ec252998c2d743
This commit is contained in:
@@ -256,8 +256,22 @@
|
||||
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
||||
<key>NSAppleEventsUsageDescription</key>
|
||||
<string>This application wants to run AppleScript.</string>
|
||||
<key>NSDesktopFolderUsageDescription</key>
|
||||
<string>This application wants to access the Desktop folder.</string>
|
||||
<key>NSDocumentsFolderUsageDescription</key>
|
||||
<string>This application wants to access the Documents folder.</string>
|
||||
<key>NSDownloadsFolderUsageDescription</key>
|
||||
<string>This application wants to access the Downloads folder.</string>
|
||||
<key>NSNetworkVolumesUsageDescription</key>
|
||||
<string>This application wants to access network volumes.</string>
|
||||
<key>NSRemovableVolumesUsageDescription</key>
|
||||
<string>This application wants to access removable volumes.</string>
|
||||
<key>NSFileProviderDomainUsageDescription</key>
|
||||
<string>This application wants to access files from a provider.</string>
|
||||
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||
<string>A user application wants to access bluetooth.</string>
|
||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||
<string>A user application wants to access bluetooth.</string>
|
||||
<key>NSCalendarsUsageDescription</key>
|
||||
<string>A user application wants to access calendars.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
|
||||
@@ -31,7 +31,7 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/qlitehtml/src/CMakeLists.txt)
|
||||
set(QLITEHTML_DEVEL_EXCLUDE_FROM_ALL ON)
|
||||
set(QLITEHTML_HEADER_PATH "${IDE_HEADER_INSTALL_PATH}/src/lib/qlitehtml")
|
||||
set(QT_VERSION_MAJOR ${Qt5_VERSION_MAJOR})
|
||||
set(BUILD_TESTING OFF) # otherwise litehtml downloads googletest
|
||||
option(BUILD_TESTING "Build litehtml tests" OFF) # otherwise litehtml downloads googletest
|
||||
add_subdirectory(qlitehtml/src)
|
||||
endif()
|
||||
if(TARGET qlitehtml)
|
||||
|
||||
@@ -1236,7 +1236,11 @@ bool Check::visit(FunctionExpression *ast)
|
||||
}
|
||||
}
|
||||
|
||||
addMessage(ErrFunctionsNotSupportedInQmlUi, locationFromRange(locfunc, loclparen));
|
||||
const bool isDirectInConnectionsScope =
|
||||
(!m_typeStack.isEmpty() && m_typeStack.last() == "Connections");
|
||||
|
||||
if (!isDirectInConnectionsScope)
|
||||
addMessage(ErrFunctionsNotSupportedInQmlUi, locationFromRange(locfunc, loclparen));
|
||||
|
||||
DeclarationsCheck bodyCheck;
|
||||
addMessages(bodyCheck(ast));
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
add_qtc_library(Sqlite
|
||||
PROPERTIES AUTOMOC OFF AUTOUIC OFF
|
||||
PUBLIC_DEFINES
|
||||
BUILD_SQLITE_LIBRARY
|
||||
SQLITE_CORE
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#include <utils/smallstringview.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
constexpr int compare(Utils::SmallStringView first, Utils::SmallStringView second) noexcept
|
||||
@@ -41,6 +43,8 @@ constexpr int compare(Utils::SmallStringView first, Utils::SmallStringView secon
|
||||
return difference;
|
||||
}
|
||||
|
||||
enum class UpdateChange { No, Update };
|
||||
|
||||
template<typename SqliteRange,
|
||||
typename Range,
|
||||
typename CompareKey,
|
||||
@@ -58,6 +62,7 @@ void insertUpdateDelete(SqliteRange &&sqliteRange,
|
||||
auto endSqliteIterator = sqliteRange.end();
|
||||
auto currentValueIterator = values.begin();
|
||||
auto endValueIterator = values.end();
|
||||
std::optional<std::decay_t<decltype(*currentValueIterator)>> lastValue;
|
||||
|
||||
while (true) {
|
||||
bool hasMoreValues = currentValueIterator != endValueIterator;
|
||||
@@ -67,21 +72,42 @@ void insertUpdateDelete(SqliteRange &&sqliteRange,
|
||||
auto &&value = *currentValueIterator;
|
||||
auto compare = compareKey(sqliteValue, value);
|
||||
if (compare == 0) {
|
||||
updateCallback(sqliteValue, value);
|
||||
++currentValueIterator;
|
||||
UpdateChange updateChange = updateCallback(sqliteValue, value);
|
||||
switch (updateChange) {
|
||||
case UpdateChange::Update:
|
||||
lastValue = value;
|
||||
break;
|
||||
case UpdateChange::No:
|
||||
lastValue.reset();
|
||||
break;
|
||||
}
|
||||
++currentSqliteIterator;
|
||||
++currentValueIterator;
|
||||
} else if (compare > 0) {
|
||||
insertCallback(value);
|
||||
++currentValueIterator;
|
||||
} else if (compare < 0) {
|
||||
deleteCallback(sqliteValue);
|
||||
if (lastValue) {
|
||||
if (compareKey(sqliteValue, *lastValue) != 0)
|
||||
deleteCallback(sqliteValue);
|
||||
lastValue.reset();
|
||||
} else {
|
||||
deleteCallback(sqliteValue);
|
||||
}
|
||||
++currentSqliteIterator;
|
||||
}
|
||||
} else if (hasMoreValues) {
|
||||
insertCallback(*currentValueIterator);
|
||||
++currentValueIterator;
|
||||
} else if (hasMoreSqliteValues) {
|
||||
deleteCallback(*currentSqliteIterator);
|
||||
auto &&sqliteValue = *currentSqliteIterator;
|
||||
if (lastValue) {
|
||||
if (compareKey(sqliteValue, *lastValue) != 0)
|
||||
deleteCallback(sqliteValue);
|
||||
lastValue.reset();
|
||||
} else {
|
||||
deleteCallback(sqliteValue);
|
||||
}
|
||||
++currentSqliteIterator;
|
||||
} else {
|
||||
break;
|
||||
|
||||
@@ -639,11 +639,12 @@ public:
|
||||
std::function<QString(const QString &)> m_displayFilter;
|
||||
std::unique_ptr<BoolAspect> m_checker;
|
||||
|
||||
Qt::TextElideMode m_elideMode = Qt::ElideNone;
|
||||
QString m_placeHolderText;
|
||||
QString m_historyCompleterKey;
|
||||
PathChooser::Kind m_expectedKind = PathChooser::File;
|
||||
EnvironmentChange m_environmentChange;
|
||||
QPointer<QLabel> m_labelDisplay;
|
||||
QPointer<ElidingLabel> m_labelDisplay;
|
||||
QPointer<FancyLineEdit> m_lineEditDisplay;
|
||||
QPointer<PathChooser> m_pathChooserDisplay;
|
||||
QPointer<QTextEdit> m_textEditDisplay;
|
||||
@@ -935,6 +936,16 @@ void StringAspect::setPlaceHolderText(const QString &placeHolderText)
|
||||
d->m_textEditDisplay->setPlaceholderText(placeHolderText);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets \a elideMode as label elide mode.
|
||||
*/
|
||||
void StringAspect::setElideMode(Qt::TextElideMode elideMode)
|
||||
{
|
||||
d->m_elideMode = elideMode;
|
||||
if (d->m_labelDisplay)
|
||||
d->m_labelDisplay->setElideMode(elideMode);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets \a historyCompleterKey as key for the history completer settings for
|
||||
line edits and path chooser displays.
|
||||
@@ -1144,7 +1155,8 @@ void StringAspect::addToLayout(LayoutBuilder &builder)
|
||||
}
|
||||
break;
|
||||
case LabelDisplay:
|
||||
d->m_labelDisplay = createSubWidget<QLabel>();
|
||||
d->m_labelDisplay = createSubWidget<ElidingLabel>();
|
||||
d->m_labelDisplay->setElideMode(d->m_elideMode);
|
||||
d->m_labelDisplay->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
d->m_labelDisplay->setText(displayedString);
|
||||
d->m_labelDisplay->setToolTip(d->m_showToolTipOnLabel ? displayedString : toolTip());
|
||||
|
||||
@@ -308,6 +308,7 @@ public:
|
||||
void setValidationFunction(const Utils::FancyLineEdit::ValidationFunction &validator);
|
||||
void setOpenTerminalHandler(const std::function<void()> &openTerminal);
|
||||
void setAutoApplyOnEditingFinished(bool applyOnEditingFinished);
|
||||
void setElideMode(Qt::TextElideMode elideMode);
|
||||
|
||||
void validateInput();
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ static QLayout *createLayoutFromType(LayoutBuilder::LayoutType layoutType)
|
||||
switch (layoutType) {
|
||||
case LayoutBuilder::FormLayout: {
|
||||
auto formLayout = new QFormLayout;
|
||||
formLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||
return formLayout;
|
||||
}
|
||||
case LayoutBuilder::GridLayout: {
|
||||
|
||||
@@ -325,6 +325,13 @@ int main(int argc, char *argv[])
|
||||
kill(chldPid, SIGKILL);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (chldPid > 0) {
|
||||
int res = kill(chldPid, SIGINT);
|
||||
if (res)
|
||||
perror("Stub could not interrupt inferior");
|
||||
}
|
||||
break;
|
||||
case 'c': {
|
||||
int res = write(blockingPipe[1], &c, 1);
|
||||
if (res < 0)
|
||||
|
||||
@@ -589,7 +589,7 @@ FilePath AndroidConfig::openJDKBinPath() const
|
||||
|
||||
FilePath AndroidConfig::keytoolPath() const
|
||||
{
|
||||
return openJDKBinPath().pathAppended(keytoolName);
|
||||
return openJDKBinPath().pathAppended(keytoolName).withExecutableSuffix();
|
||||
}
|
||||
|
||||
QVector<AndroidDeviceInfo> AndroidConfig::connectedDevices(QString *error) const
|
||||
|
||||
@@ -84,7 +84,8 @@ AndroidPackageInstallationStep::AndroidPackageInstallationStep(BuildStepList *bs
|
||||
setWidgetExpandedByDefault(false);
|
||||
setImmutable(true);
|
||||
setSummaryUpdater([this] {
|
||||
return tr("<b>Make install:</b> Copy App Files to %1").arg(nativeAndroidBuildPath());
|
||||
return tr("<b>Make install:</b> Copy App Files to %1")
|
||||
.arg(QDir::toNativeSeparators(nativeAndroidBuildPath()));
|
||||
});
|
||||
setUseEnglishOutput();
|
||||
}
|
||||
|
||||
@@ -59,18 +59,18 @@ QStringList filterInterfering(const QStringList &provided, QStringList *omitted)
|
||||
"--gtest_print_time="
|
||||
};
|
||||
|
||||
QSet<QString> allowed = Utils::filtered(Utils::toSet(provided), [] (const QString &arg) {
|
||||
QStringList allowed = Utils::filtered(provided, [] (const QString &arg) {
|
||||
return Utils::allOf(knownInterferingOptions, [&arg] (const QString &interfering) {
|
||||
return !arg.startsWith(interfering);
|
||||
});
|
||||
});
|
||||
|
||||
if (omitted) {
|
||||
if (omitted && allowed.size() < provided.size()) {
|
||||
QSet<QString> providedSet = Utils::toSet(provided);
|
||||
providedSet.subtract(allowed);
|
||||
providedSet.subtract(Utils::toSet(allowed));
|
||||
omitted->append(Utils::toList(providedSet));
|
||||
}
|
||||
return Utils::toList(allowed);
|
||||
return allowed;
|
||||
}
|
||||
|
||||
QStringList GTestConfiguration::argumentsForTestRunner(QStringList *omitted) const
|
||||
|
||||
@@ -395,10 +395,14 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
|
||||
bool ClangdTextMark::addToolTipContent(QLayout *target) const
|
||||
{
|
||||
const auto canApplyFixIt = [c = m_client, diag = m_lspDiagnostic, fp = fileName()] {
|
||||
return c && c->reachable() && c->hasDiagnostic(DocumentUri::fromFilePath(fp), diag);
|
||||
return QTC_GUARD(c) && c->reachable()
|
||||
&& c->hasDiagnostic(DocumentUri::fromFilePath(fp), diag);
|
||||
};
|
||||
const QString clientName = QTC_GUARD(m_client) ? m_client->name() : "clangd [unknown]";
|
||||
target->addWidget(ClangDiagnosticWidget::createWidget({m_diagnostic},
|
||||
ClangDiagnosticWidget::ToolTip, canApplyFixIt, m_client ? m_client->name() : "clangd"));
|
||||
ClangDiagnosticWidget::ToolTip,
|
||||
canApplyFixIt,
|
||||
clientName));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -581,7 +581,15 @@ QStringList createClangOptions(const ProjectPart &projectPart, const QString &fi
|
||||
LibClangOptionsBuilder optionsBuilder(projectPart, fileOptions.useBuildSystemWarnings());
|
||||
const QStringList projectPartOptions = optionsBuilder.build(CppEditor::ProjectFile::Unsupported,
|
||||
UsePrecompiledHeaders::No);
|
||||
return projectPartOptions + fileOptions.options();
|
||||
|
||||
// FIXME: Sanitize FileOptionsBuilder instead.
|
||||
QStringList fileArgs = fileOptions.options();
|
||||
if (projectPartOptions.contains("-TP"))
|
||||
fileArgs.removeAll("/TP");
|
||||
if (projectPartOptions.contains("-TC"))
|
||||
fileArgs.removeAll("/TC");
|
||||
|
||||
return projectPartOptions + fileArgs;
|
||||
}
|
||||
|
||||
ClangDiagnosticConfig warningsConfigForProject(Project *project)
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
|
||||
#include <qnx/qnxconstants.h>
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/cpplanguage_details.h>
|
||||
#include <utils/fileutils.h>
|
||||
@@ -152,6 +154,7 @@ QStringList CompilerOptionsBuilder::build(ProjectFile::Kind fileKind,
|
||||
undefineClangVersionMacrosForMsvc();
|
||||
undefineCppLanguageFeatureMacrosForMsvc2015();
|
||||
addDefineFunctionMacrosMsvc();
|
||||
addDefineFunctionMacrosQnx();
|
||||
|
||||
addHeaderPathOptions();
|
||||
|
||||
@@ -404,8 +407,8 @@ void CompilerOptionsBuilder::addProjectMacros()
|
||||
static const int useMacros = qEnvironmentVariableIntValue("QTC_CLANG_USE_TOOLCHAIN_MACROS");
|
||||
|
||||
if (m_projectPart.toolchainType == ProjectExplorer::Constants::CUSTOM_TOOLCHAIN_TYPEID
|
||||
|| m_projectPart.toolchainType.name().contains("BareMetal")
|
||||
|| useMacros) {
|
||||
|| m_projectPart.toolchainType == Qnx::Constants::QNX_TOOLCHAIN_ID
|
||||
|| m_projectPart.toolchainType.name().contains("BareMetal") || useMacros) {
|
||||
addMacros(m_projectPart.toolChainMacros);
|
||||
}
|
||||
|
||||
@@ -771,6 +774,17 @@ void CompilerOptionsBuilder::undefineClangVersionMacrosForMsvc()
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addDefineFunctionMacrosQnx()
|
||||
{
|
||||
// QNX 7.0+ uses GCC with LIBCPP from Clang, and in that context GCC is giving
|
||||
// the builtin operator new and delete.
|
||||
//
|
||||
// In our case we have only Clang and need to instruct LIBCPP that it doesn't
|
||||
// have these operators. This makes the code model happy and doesn't produce errors.
|
||||
if (m_projectPart.toolchainType == Qnx::Constants::QNX_TOOLCHAIN_ID)
|
||||
addMacros({{"_LIBCPP_HAS_NO_BUILTIN_OPERATOR_NEW_DELETE"}});
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::reset()
|
||||
{
|
||||
m_options.clear();
|
||||
|
||||
@@ -84,6 +84,8 @@ public:
|
||||
void addProjectConfigFileInclude();
|
||||
void undefineClangVersionMacrosForMsvc();
|
||||
|
||||
void addDefineFunctionMacrosQnx();
|
||||
|
||||
// Add custom options
|
||||
void add(const QString &arg, bool gccOnlyOption = false);
|
||||
void prepend(const QString &arg);
|
||||
|
||||
@@ -74,8 +74,7 @@ CppUseSelectionsUpdater::RunnerInfo CppUseSelectionsUpdater::update(CallType cal
|
||||
auto *cppEditorDocument = qobject_cast<CppEditorDocument *>(cppEditorWidget->textDocument());
|
||||
QTC_ASSERT(cppEditorDocument, return RunnerInfo::FailedToStart);
|
||||
|
||||
if (!CppModelManager::instance()->supportsLocalUses(cppEditorDocument))
|
||||
return RunnerInfo::AlreadyUpToDate;
|
||||
m_updateSelections = CppModelManager::instance()->supportsLocalUses(cppEditorDocument);
|
||||
|
||||
CursorInfoParams params;
|
||||
params.semanticInfo = cppEditorWidget->semanticInfo();
|
||||
@@ -130,16 +129,16 @@ bool CppUseSelectionsUpdater::isSameIdentifierAsBefore(const QTextCursor &cursor
|
||||
|
||||
void CppUseSelectionsUpdater::processResults(const CursorInfo &result)
|
||||
{
|
||||
ExtraSelections localVariableSelections;
|
||||
if (!result.useRanges.isEmpty() || !currentUseSelections().isEmpty()) {
|
||||
ExtraSelections selections = updateUseSelections(result.useRanges);
|
||||
if (result.areUseRangesForLocalVariable)
|
||||
localVariableSelections = selections;
|
||||
if (m_updateSelections) {
|
||||
ExtraSelections localVariableSelections;
|
||||
if (!result.useRanges.isEmpty() || !currentUseSelections().isEmpty()) {
|
||||
ExtraSelections selections = updateUseSelections(result.useRanges);
|
||||
if (result.areUseRangesForLocalVariable)
|
||||
localVariableSelections = selections;
|
||||
}
|
||||
updateUnusedSelections(result.unusedVariablesRanges);
|
||||
emit selectionsForVariableUnderCursorUpdated(localVariableSelections);
|
||||
}
|
||||
|
||||
updateUnusedSelections(result.unusedVariablesRanges);
|
||||
|
||||
emit selectionsForVariableUnderCursorUpdated(localVariableSelections);
|
||||
emit finished(result.localUses, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@ private:
|
||||
QScopedPointer<QFutureWatcher<CursorInfo>> m_runnerWatcher;
|
||||
int m_runnerRevision = -1;
|
||||
int m_runnerWordStartPosition = -1;
|
||||
bool m_updateSelections = true;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -254,6 +254,7 @@ QList<ReloadInput> DiffOpenFilesController::reloadInputList() const
|
||||
const QList<IDocument *> openedDocuments = DocumentModel::openedDocuments();
|
||||
|
||||
for (IDocument *doc : openedDocuments) {
|
||||
QTC_ASSERT(doc, continue);
|
||||
auto textDocument = qobject_cast<TextEditor::TextDocument *>(doc);
|
||||
|
||||
if (textDocument && textDocument->isModified()) {
|
||||
@@ -518,6 +519,7 @@ void DiffEditorPluginPrivate::updateDiffCurrentFileAction()
|
||||
void DiffEditorPluginPrivate::updateDiffOpenFilesAction()
|
||||
{
|
||||
const bool enabled = Utils::anyOf(DocumentModel::openedDocuments(), [](IDocument *doc) {
|
||||
QTC_ASSERT(doc, return false);
|
||||
return doc->isModified() && qobject_cast<TextEditor::TextDocument *>(doc);
|
||||
});
|
||||
m_diffOpenFilesAction->setEnabled(enabled);
|
||||
|
||||
@@ -692,7 +692,7 @@ void Client::documentContentsChanged(TextEditor::TextDocument *document,
|
||||
const QString method(DidChangeTextDocumentNotification::methodName);
|
||||
TextDocumentSyncKind syncKind = m_serverCapabilities.textDocumentSyncKindHelper();
|
||||
if (Utils::optional<bool> registered = m_dynamicCapabilities.isRegistered(method)) {
|
||||
syncKind = registered.value() ? TextDocumentSyncKind::None : TextDocumentSyncKind::Full;
|
||||
syncKind = registered.value() ? TextDocumentSyncKind::Full : TextDocumentSyncKind::None;
|
||||
if (syncKind != TextDocumentSyncKind::None) {
|
||||
const TextDocumentChangeRegistrationOptions option(
|
||||
m_dynamicCapabilities.option(method).toObject());
|
||||
|
||||
@@ -392,8 +392,10 @@ bool LanguageClientCompletionAssistProcessor::running()
|
||||
void LanguageClientCompletionAssistProcessor::cancel()
|
||||
{
|
||||
if (m_currentRequest.has_value()) {
|
||||
m_client->cancelRequest(m_currentRequest.value());
|
||||
m_client->removeAssistProcessor(this);
|
||||
if (m_client) {
|
||||
m_client->cancelRequest(m_currentRequest.value());
|
||||
m_client->removeAssistProcessor(this);
|
||||
}
|
||||
m_currentRequest.reset();
|
||||
} else if (m_postponedUpdateConnection) {
|
||||
QObject::disconnect(m_postponedUpdateConnection);
|
||||
|
||||
@@ -75,6 +75,10 @@ void SemanticTokenSupport::reloadSemanticTokens(TextDocument *textDocument)
|
||||
const TextDocumentIdentifier docId(DocumentUri::fromFilePath(filePath));
|
||||
auto responseCallback = [this, filePath, documentVersion = m_client->documentVersion(filePath)](
|
||||
const SemanticTokensFullRequest::Response &response) {
|
||||
if (const auto error = response.error()) {
|
||||
qCDebug(LOGLSPHIGHLIGHT)
|
||||
<< "received error" << error->code() << error->message() << "for" << filePath;
|
||||
}
|
||||
handleSemanticTokens(filePath, response.result().value_or(nullptr), documentVersion);
|
||||
};
|
||||
/*if (supportedRequests.testFlag(SemanticRequestType::Range)) {
|
||||
@@ -120,6 +124,10 @@ void SemanticTokenSupport::updateSemanticTokens(TextDocument *textDocument)
|
||||
request.setResponseCallback(
|
||||
[this, filePath, documentVersion](
|
||||
const SemanticTokensFullDeltaRequest::Response &response) {
|
||||
if (const auto error = response.error()) {
|
||||
qCDebug(LOGLSPHIGHLIGHT) << "received error" << error->code()
|
||||
<< error->message() << "for" << filePath;
|
||||
}
|
||||
handleSemanticTokensDelta(filePath,
|
||||
response.result().value_or(nullptr),
|
||||
documentVersion);
|
||||
@@ -285,6 +293,9 @@ void SemanticTokenSupport::handleSemanticTokens(const Utils::FilePath &filePath,
|
||||
m_tokens[filePath] = {*tokens, documentVersion};
|
||||
highlight(filePath);
|
||||
} else {
|
||||
qCDebug(LOGLSPHIGHLIGHT)
|
||||
<< "no data in reply to full semantic tokens request, clearing tokens"
|
||||
<< m_client->name() << filePath;
|
||||
m_tokens.remove(filePath);
|
||||
}
|
||||
}
|
||||
@@ -353,8 +364,10 @@ void SemanticTokenSupport::handleSemanticTokensDelta(
|
||||
tokens.setData(newData);
|
||||
tokens.setResultId(tokensDelta->resultId());
|
||||
} else {
|
||||
qCDebug(LOGLSPHIGHLIGHT)
|
||||
<< "no data in reply to semantic tokens delta request, clearing tokens"
|
||||
<< m_client->name() << filePath;
|
||||
m_tokens.remove(filePath);
|
||||
qCDebug(LOGLSPHIGHLIGHT) << "Data cleared";
|
||||
return;
|
||||
}
|
||||
highlight(filePath);
|
||||
|
||||
@@ -56,7 +56,7 @@ static const QHash<QString, QString> &envVarToCMakeVarMapping()
|
||||
{"RenesasFlashProgrammer_PATH", "RENESAS_FLASH_PROGRAMMER_PATH"},
|
||||
{"MCUXpressoIDE_PATH", "MCUXPRESSO_IDE_PATH"},
|
||||
{"JLINK_PATH", "JLINK_PATH"},
|
||||
{"CYPRESS_AUTO_FLASH_UTILITY_DIR", "CYPRESS_AUTO_FLASH_UTILITY_DIR"},
|
||||
{"CYPRESS_AUTO_FLASH_UTILITY_DIR", "INFINEON_AUTO_FLASH_UTILITY_DIR"},
|
||||
{"EK_RA6M3G_E2_PROJECT_PATH", "EK_RA6M3G_E2_PROJECT_PATH"},
|
||||
};
|
||||
return mapping;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
cmake_minimum_required (VERSION 3.15)
|
||||
|
||||
project(%{ProjectName} VERSION 0.0.1 LANGUAGES C CXX ASM)
|
||||
project(%{ProjectName} VERSION 0.0.1 LANGUAGES C CXX ASM ASM_MASM)
|
||||
|
||||
find_package(Qul)
|
||||
|
||||
|
||||
@@ -2110,7 +2110,7 @@ Utils::optional<QString> MsvcToolChain::generateEnvironmentSettings(const Utils:
|
||||
Utils::Environment runEnv = env;
|
||||
runEnv.unset(QLatin1String("ORIGINALPATH"));
|
||||
run.setEnvironment(runEnv);
|
||||
run.setTimeoutS(30);
|
||||
run.setTimeoutS(60);
|
||||
Utils::FilePath cmdPath = Utils::FilePath::fromUserInput(
|
||||
QString::fromLocal8Bit(qgetenv("COMSPEC")));
|
||||
if (cmdPath.isEmpty())
|
||||
|
||||
@@ -794,7 +794,9 @@ static void getExpandedCompilerFlags(QStringList &cFlags, QStringList &cxxFlags,
|
||||
cFlags = cxxFlags = commonFlags;
|
||||
|
||||
const auto cxxLanguageVersion = arrayToStringList(getCppProp("cxxLanguageVersion"));
|
||||
if (cxxLanguageVersion.contains("c++20"))
|
||||
if (cxxLanguageVersion.contains("c++23"))
|
||||
cxxFlags << "-std=c++2b";
|
||||
else if (cxxLanguageVersion.contains("c++20"))
|
||||
cxxFlags << "-std=c++20";
|
||||
else if (cxxLanguageVersion.contains("c++17"))
|
||||
cxxFlags << "-std=c++17";
|
||||
@@ -850,9 +852,12 @@ static void getExpandedCompilerFlags(QStringList &cFlags, QStringList &cxxFlags,
|
||||
cxxFlags << "/TP";
|
||||
if (!enableRtti.isUndefined())
|
||||
cxxFlags << QLatin1String(enableRtti.toBool() ? "/GR" : "/GR-");
|
||||
if (getCppProp("cxxLanguageVersion").toArray().contains("c++20"))
|
||||
const QJsonArray cxxLanguageVersion = getCppProp("cxxLanguageVersion").toArray();
|
||||
if (cxxLanguageVersion.contains("c++23"))
|
||||
cxxFlags << "/std:c++latest";
|
||||
else if (cxxLanguageVersion.contains("c++20"))
|
||||
cxxFlags << "/std:c++20";
|
||||
else if (getCppProp("cxxLanguageVersion").toArray().contains("c++17"))
|
||||
else if (cxxLanguageVersion.contains("c++17"))
|
||||
cxxFlags << "/std:c++17";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,33 +202,36 @@ void ActionEditor::prepareConnections()
|
||||
continue;
|
||||
|
||||
const QString name = QString::fromUtf8(propertyName);
|
||||
const bool writeable = modelNode.metaInfo().propertyIsWritable(propertyName);
|
||||
TypeName type = modelNode.metaInfo().propertyTypeName(propertyName);
|
||||
if (type.contains("<cpp>."))
|
||||
type.remove(0, 6);
|
||||
|
||||
connection.properties.append(ActionEditorDialog::PropertyOption(name, type));
|
||||
connection.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable));
|
||||
}
|
||||
|
||||
for (const VariantProperty &variantProperty : modelNode.variantProperties()) {
|
||||
if (variantProperty.isValid()) {
|
||||
if (variantProperty.isDynamic()) {
|
||||
if (!typeWhiteList.contains(variantProperty.dynamicTypeName()))
|
||||
continue;
|
||||
if (variantProperty.isValid() && variantProperty.isDynamic()) {
|
||||
if (!typeWhiteList.contains(variantProperty.dynamicTypeName()))
|
||||
continue;
|
||||
|
||||
const QString name = QString::fromUtf8(variantProperty.name());
|
||||
TypeName type = variantProperty.dynamicTypeName();
|
||||
if (type.contains("<cpp>."))
|
||||
type.remove(0, 6);
|
||||
const QString name = QString::fromUtf8(variantProperty.name());
|
||||
const bool writeable = modelNode.metaInfo().propertyIsWritable(variantProperty.name());
|
||||
TypeName type = variantProperty.dynamicTypeName();
|
||||
if (type.contains("<cpp>."))
|
||||
type.remove(0, 6);
|
||||
|
||||
connection.properties.append(ActionEditorDialog::PropertyOption(name, type));
|
||||
}
|
||||
connection.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable));
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &slotName : modelNode.metaInfo().slotNames()) {
|
||||
if (slotName.startsWith("q_") || slotName.startsWith("_q_"))
|
||||
continue;
|
||||
|
||||
QmlJS::Document::MutablePtr newDoc = QmlJS::Document::create(
|
||||
QLatin1String("<expression>"), QmlJS::Dialect::JavaScript);
|
||||
newDoc->setSource(QLatin1String(slotName));
|
||||
newDoc->setSource(modelNode.id() + "." + QLatin1String(slotName));
|
||||
newDoc->parseExpression();
|
||||
|
||||
QmlJS::AST::ExpressionNode *expression = newDoc->expression();
|
||||
@@ -263,10 +266,11 @@ void ActionEditor::prepareConnections()
|
||||
continue;
|
||||
|
||||
const QString name = QString::fromUtf8(propertyName);
|
||||
const bool writeable = metaInfo.propertyIsWritable(propertyName);
|
||||
if (type.contains("<cpp>."))
|
||||
type.remove(0, 6);
|
||||
|
||||
singelton.properties.append(ActionEditorDialog::PropertyOption(name, type));
|
||||
singelton.properties.append(ActionEditorDialog::PropertyOption(name, type, writeable));
|
||||
}
|
||||
|
||||
if (!singelton.properties.isEmpty()) {
|
||||
|
||||
@@ -472,7 +472,7 @@ void ActionEditorDialog::fillAndSetTargetItem(const QString &value, bool useDefa
|
||||
} else { // ConnectionType::Assignment
|
||||
m_assignmentTargetItem->clear();
|
||||
for (const auto &connection : qAsConst(m_connections)) {
|
||||
if (!connection.properties.isEmpty())
|
||||
if (!connection.properties.isEmpty() && connection.hasWriteableProperties())
|
||||
m_assignmentTargetItem->addItem(connection.item);
|
||||
}
|
||||
|
||||
@@ -516,8 +516,10 @@ void ActionEditorDialog::fillAndSetTargetProperty(const QString &value, bool use
|
||||
if (idx == -1) {
|
||||
insertAndSetUndefined(m_assignmentTargetProperty);
|
||||
} else {
|
||||
for (const auto &property : qAsConst(m_connections[idx].properties))
|
||||
m_assignmentTargetProperty->addItem(property.name, property.type);
|
||||
for (const auto &property : qAsConst(m_connections[idx].properties)) {
|
||||
if (property.isWriteable)
|
||||
m_assignmentTargetProperty->addItem(property.name, property.type);
|
||||
}
|
||||
|
||||
if (m_assignmentTargetProperty->findText(value) != -1) {
|
||||
m_assignmentTargetProperty->setCurrentText(value);
|
||||
|
||||
@@ -51,10 +51,10 @@ public:
|
||||
class PropertyOption
|
||||
{
|
||||
public:
|
||||
PropertyOption() {}
|
||||
PropertyOption(const QString &n, const TypeName &t)
|
||||
PropertyOption(const QString &n, const TypeName &t, bool writeable = true)
|
||||
: name(n)
|
||||
, type(t)
|
||||
, isWriteable(writeable)
|
||||
{}
|
||||
|
||||
bool operator==(const QString &value) const { return value == name; }
|
||||
@@ -62,6 +62,7 @@ public:
|
||||
|
||||
QString name;
|
||||
TypeName type;
|
||||
bool isWriteable;
|
||||
};
|
||||
|
||||
class SingletonOption
|
||||
@@ -80,6 +81,16 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasWriteableProperties() const
|
||||
{
|
||||
for (const auto &p : properties) {
|
||||
if (p.isWriteable)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator==(const QString &value) const { return value == item; }
|
||||
bool operator==(const SingletonOption &value) const { return value.item == item; }
|
||||
|
||||
@@ -90,7 +101,6 @@ public:
|
||||
class ConnectionOption : public SingletonOption
|
||||
{
|
||||
public:
|
||||
ConnectionOption() {}
|
||||
ConnectionOption(const QString &value) : SingletonOption(value) {}
|
||||
|
||||
QStringList methods;
|
||||
|
||||
@@ -221,6 +221,7 @@ const int priorityLast = 60;
|
||||
const char addImagesDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Image Files");
|
||||
const char addFontsDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Font Files");
|
||||
const char addSoundsDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Sound Files");
|
||||
const char addVideosDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Video Files");
|
||||
const char addShadersDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "Shader Files");
|
||||
const char add3DAssetsDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources", "3D Assets");
|
||||
const char addQt3DSPresentationsDisplayString[] = QT_TRANSLATE_NOOP("QmlDesignerAddResources",
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
|
||||
#include <QGraphicsLinearLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QImageReader>
|
||||
#include <QMessageBox>
|
||||
#include <QMimeData>
|
||||
|
||||
@@ -1549,20 +1550,27 @@ void DesignerActionManager::createDefaultAddResourceHandler()
|
||||
registerAddResourceHandler(AddResourceHandler(category, ext, op));
|
||||
};
|
||||
|
||||
auto transformer = [](const QByteArray& format) -> QString { return QString("*.") + format; };
|
||||
auto imageFormats = Utils::transform(QImageReader::supportedImageFormats(), transformer);
|
||||
imageFormats.push_back("*.hdr");
|
||||
|
||||
// The filters will be displayed in reverse order to these lists in file dialog,
|
||||
// so declare most common types last
|
||||
registerHandlers({"*.webp", "*.hdr", "*.svg", "*.bmp", "*.jpg", "*.png"},
|
||||
registerHandlers(imageFormats,
|
||||
ModelNodeOperations::addImageToProject,
|
||||
ComponentCoreConstants::addImagesDisplayString);
|
||||
registerHandlers({"*.otf", "*.ttf"},
|
||||
ModelNodeOperations::addFontToProject,
|
||||
ComponentCoreConstants::addFontsDisplayString);
|
||||
registerHandlers({"*.wav"},
|
||||
registerHandlers({"*.wav", "*.mp3"},
|
||||
ModelNodeOperations::addSoundToProject,
|
||||
ComponentCoreConstants::addSoundsDisplayString);
|
||||
registerHandlers({"*.glsl", "*.glslv", "*.glslf", "*.vsh", "*.fsh", "*.vert", "*.frag"},
|
||||
ModelNodeOperations::addShaderToProject,
|
||||
ComponentCoreConstants::addShadersDisplayString);
|
||||
registerHandlers({"*.mp4"},
|
||||
ModelNodeOperations::addVideoToProject,
|
||||
ComponentCoreConstants::addVideosDisplayString);
|
||||
}
|
||||
|
||||
void DesignerActionManager::createDefaultModelNodePreviewImageHandlers()
|
||||
|
||||
@@ -1083,6 +1083,11 @@ AddFilesResult addImageToProject(const QStringList &fileNames, const QString &de
|
||||
return addFilesToProject(fileNames, getAssetDefaultDirectory("images", defaultDirectory));
|
||||
}
|
||||
|
||||
AddFilesResult addVideoToProject(const QStringList &fileNames, const QString &defaultDirectory)
|
||||
{
|
||||
return addFilesToProject(fileNames, getAssetDefaultDirectory("videos", defaultDirectory));
|
||||
}
|
||||
|
||||
void createFlowActionArea(const SelectionContext &selectionContext)
|
||||
{
|
||||
AbstractView *view = selectionContext.view();
|
||||
|
||||
@@ -80,6 +80,7 @@ AddFilesResult addImageToProject(const QStringList &fileNames, const QString &di
|
||||
AddFilesResult addFontToProject(const QStringList &fileNames, const QString &directory);
|
||||
AddFilesResult addSoundToProject(const QStringList &fileNames, const QString &directory);
|
||||
AddFilesResult addShaderToProject(const QStringList &fileNames, const QString &directory);
|
||||
AddFilesResult addVideoToProject(const QStringList &fileNames, const QString &directory);
|
||||
void createFlowActionArea(const SelectionContext &selectionContext);
|
||||
void addTransition(const SelectionContext &selectionState);
|
||||
void addFlowEffect(const SelectionContext &selectionState, const TypeName &typeName);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 286 B |
Binary file not shown.
|
After Width: | Height: | Size: 399 B |
@@ -33,5 +33,7 @@
|
||||
<file>images/x@2x.png</file>
|
||||
<file>images/browse.png</file>
|
||||
<file>images/browse@2x.png</file>
|
||||
<file>images/item-video-icon.png</file>
|
||||
<file>images/item-video-icon@2x.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -54,6 +54,8 @@ QPixmap ItemLibraryAssetsIconProvider::requestPixmap(const QString &id, QSize *s
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/asset_shader_48.png");
|
||||
else if (ItemLibraryAssetsModel::supportedAudioSuffixes().contains(suffix))
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/asset_sound_48.png");
|
||||
else if (ItemLibraryAssetsModel::supportedVideoSuffixes().contains(suffix))
|
||||
pixmap = Utils::StyleHelper::dpiSpecificImageFile(":/ItemLibrary/images/item-video-icon.png");
|
||||
|
||||
if (size) {
|
||||
size->setWidth(pixmap.width());
|
||||
|
||||
@@ -167,7 +167,13 @@ const QStringList &ItemLibraryAssetsModel::supportedFontSuffixes()
|
||||
|
||||
const QStringList &ItemLibraryAssetsModel::supportedAudioSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.wav"};
|
||||
static const QStringList retList {"*.wav", "*.mp3"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
const QStringList &ItemLibraryAssetsModel::supportedVideoSuffixes()
|
||||
{
|
||||
static const QStringList retList {"*.mp4"};
|
||||
return retList;
|
||||
}
|
||||
|
||||
@@ -300,6 +306,7 @@ const QSet<QString> &ItemLibraryAssetsModel::supportedSuffixes() const
|
||||
insertSuffixes(supportedShaderSuffixes());
|
||||
insertSuffixes(supportedFontSuffixes());
|
||||
insertSuffixes(supportedAudioSuffixes());
|
||||
insertSuffixes(supportedVideoSuffixes());
|
||||
insertSuffixes(supportedTexture3DSuffixes());
|
||||
}
|
||||
return allSuffixes;
|
||||
|
||||
@@ -66,6 +66,7 @@ public:
|
||||
static const QStringList &supportedShaderSuffixes();
|
||||
static const QStringList &supportedFontSuffixes();
|
||||
static const QStringList &supportedAudioSuffixes();
|
||||
static const QStringList &supportedVideoSuffixes();
|
||||
static const QStringList &supportedTexture3DSuffixes();
|
||||
|
||||
const QSet<QString> &previewableSuffixes() const;
|
||||
|
||||
@@ -552,6 +552,9 @@ QPair<QString, QByteArray> ItemLibraryWidget::getAssetTypeAndData(const QString
|
||||
} else if (ItemLibraryAssetsModel::supportedAudioSuffixes().contains(suffix)) {
|
||||
// No extra data for sounds
|
||||
return {"application/vnd.bauhaus.libraryresource.sound", {}};
|
||||
} else if (ItemLibraryAssetsModel::supportedVideoSuffixes().contains(suffix)) {
|
||||
// No extra data for videos
|
||||
return {"application/vnd.bauhaus.libraryresource.video", {}};
|
||||
} else if (ItemLibraryAssetsModel::supportedTexture3DSuffixes().contains(suffix)) {
|
||||
// Data: Image format (suffix)
|
||||
return {"application/vnd.bauhaus.libraryresource.texture3d", suffix.toUtf8()};
|
||||
@@ -653,10 +656,12 @@ void ItemLibraryWidget::addResources(const QStringList &files)
|
||||
QStringList fileNames = categoryFileNames.values(category);
|
||||
AddResourceOperation operation = categoryToOperation.value(category);
|
||||
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_RESOURCE_IMPORTED + category);
|
||||
AddFilesResult result = operation(fileNames, document->fileName().parentDir().toString());
|
||||
if (result == AddFilesResult::Failed) {
|
||||
Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"),
|
||||
tr("Could not add %1 to project.").arg(fileNames.join(' ')));
|
||||
if (operation) {
|
||||
AddFilesResult result = operation(fileNames, document->fileName().parentDir().toString());
|
||||
if (result == AddFilesResult::Failed) {
|
||||
Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"),
|
||||
tr("Could not add %1 to project.").arg(fileNames.join(' ')));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,12 +168,9 @@ void StatesEditorWidget::reloadQmlSource()
|
||||
connect(rootObject(), SIGNAL(createNewState()), m_statesEditorView.data(), SLOT(createNewState()));
|
||||
connect(rootObject(), SIGNAL(deleteState(int)), m_statesEditorView.data(), SLOT(removeState(int)));
|
||||
m_statesEditorView.data()->synchonizeCurrentStateFromWidget();
|
||||
setFixedHeight(initialSize().height());
|
||||
|
||||
if (!DesignerSettings::getValue(DesignerSettingsKey::STATESEDITOR_EXPANDED).toBool()) {
|
||||
if (!DesignerSettings::getValue(DesignerSettingsKey::STATESEDITOR_EXPANDED).toBool())
|
||||
toggleStatesViewExpanded();
|
||||
setFixedHeight(rootObject()->height());
|
||||
}
|
||||
|
||||
connect(rootObject(), SIGNAL(expandedChanged()), this, SLOT(handleExpandedChanged()));
|
||||
}
|
||||
@@ -184,7 +181,5 @@ void StatesEditorWidget::handleExpandedChanged()
|
||||
|
||||
bool expanded = rootObject()->property("expanded").toBool();
|
||||
DesignerSettings::setValue(DesignerSettingsKey::STATESEDITOR_EXPANDED, expanded);
|
||||
|
||||
setFixedHeight(rootObject()->height());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utils/span.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace QmlDesigner {
|
||||
@@ -73,6 +75,15 @@ public:
|
||||
InternalIntergerType id = -1;
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
auto toIntegers(const Container &container)
|
||||
{
|
||||
using DataType = typename Container::value_type::DatabaseType;
|
||||
const DataType *data = reinterpret_cast<const DataType *>(container.data());
|
||||
|
||||
return Utils::span{data, container.size()};
|
||||
}
|
||||
|
||||
enum class BasicIdType {
|
||||
Type,
|
||||
PropertyType,
|
||||
|
||||
@@ -538,8 +538,13 @@ QProcessEnvironment PuppetCreator::processEnvironment() const
|
||||
environment.set("QMLDESIGNER_QUICK3D_PARTICLES3D_MODE", "true");
|
||||
|
||||
import = QmlDesigner::Import::createLibraryImport("QtCharts", "2.0");
|
||||
if (m_model->hasImport(import, true, true))
|
||||
if (m_model->hasImport(import, true, true)) {
|
||||
environment.set("QMLDESIGNER_FORCE_QAPPLICATION", "true");
|
||||
} else if (m_target) {
|
||||
auto bs = qobject_cast<QmlProjectManager::QmlBuildSystem *>(m_target->buildSystem());
|
||||
if (bs && bs->widgetApp())
|
||||
environment.set("QMLDESIGNER_FORCE_QAPPLICATION", "true");
|
||||
}
|
||||
|
||||
bool particlemode = QmlDesigner::DesignerSettings::getValue("particleMode").toBool();
|
||||
if (!particlemode)
|
||||
|
||||
@@ -957,7 +957,8 @@ static QList<QmlDesigner::Import> generatePossibleLibraryImports(const QHash<QSt
|
||||
if (majorVersion >= 0) {
|
||||
int minorVersion = (importKey.minorVersion == LanguageUtils::ComponentVersion::NoVersion) ? 0 : importKey.minorVersion;
|
||||
QString version = QStringLiteral("%1.%2").arg(majorVersion).arg(minorVersion);
|
||||
possibleImports.append(QmlDesigner::Import::createLibraryImport(libraryName, version));
|
||||
if (!libraryName.endsWith(".impl"))
|
||||
possibleImports.append(QmlDesigner::Import::createLibraryImport(libraryName, version));
|
||||
|
||||
// In Qt6, QtQuick.Controls itself doesn't have any version as it has no types,
|
||||
// so it never gets added normally to possible imports.
|
||||
|
||||
@@ -77,14 +77,10 @@ public:
|
||||
|
||||
TypeIds typeIdsToBeDeleted;
|
||||
|
||||
auto sourceIdValues = Utils::transform<std::vector>(package.sourceIds, [](SourceId sourceId) {
|
||||
return &sourceId;
|
||||
});
|
||||
std::sort(package.updatedSourceIds.begin(), package.updatedSourceIds.end());
|
||||
|
||||
std::sort(sourceIdValues.begin(), sourceIdValues.end());
|
||||
|
||||
synchronizeFileStatuses(package.fileStatuses, sourceIdValues);
|
||||
synchronizeImports(package.imports, sourceIdValues);
|
||||
synchronizeFileStatuses(package.fileStatuses, package.updatedFileStatusSourceIds);
|
||||
synchronizeImports(package.imports, package.updatedSourceIds);
|
||||
synchronizeTypes(package.types,
|
||||
updatedTypeIds,
|
||||
insertedAliasPropertyDeclarations,
|
||||
@@ -92,10 +88,10 @@ public:
|
||||
relinkableAliasPropertyDeclarations,
|
||||
relinkablePropertyDeclarations,
|
||||
relinkablePrototypes,
|
||||
sourceIdValues);
|
||||
package.updatedSourceIds);
|
||||
|
||||
deleteNotUpdatedTypes(updatedTypeIds,
|
||||
sourceIdValues,
|
||||
package.updatedSourceIds,
|
||||
typeIdsToBeDeleted,
|
||||
relinkableAliasPropertyDeclarations,
|
||||
relinkablePropertyDeclarations,
|
||||
@@ -109,6 +105,8 @@ public:
|
||||
|
||||
linkAliases(insertedAliasPropertyDeclarations, updatedAliasPropertyDeclarations);
|
||||
|
||||
synchronizeProjectDatas(package.projectDatas, package.updatedProjectSourceIds);
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
@@ -271,7 +269,7 @@ public:
|
||||
SourceContextId fetchSourceContextId(SourceId sourceId) const
|
||||
{
|
||||
auto sourceContextId = selectSourceContextIdFromSourcesBySourceIdStatement
|
||||
.template valueWithTransaction<SourceContextId>(sourceId.id);
|
||||
.template valueWithTransaction<SourceContextId>(&sourceId);
|
||||
|
||||
if (!sourceContextId)
|
||||
throw SourceIdDoesNotExists();
|
||||
@@ -305,9 +303,16 @@ public:
|
||||
&sourceId);
|
||||
}
|
||||
|
||||
Storage::ProjectDatas fetchProjectDatas(SourceId sourceId) const override
|
||||
Storage::ProjectDatas fetchProjectDatas(SourceId projectSourceId) const override
|
||||
{
|
||||
return Storage::ProjectDatas{};
|
||||
return selectProjectDatasForModuleIdStatement
|
||||
.template valuesWithTransaction<Storage::ProjectData>(64, &projectSourceId);
|
||||
}
|
||||
|
||||
Storage::ProjectDatas fetchProjectDatas(const SourceIds &projectSourceIds) const
|
||||
{
|
||||
return selectProjectDatasForModuleIdsStatement
|
||||
.template valuesWithTransaction<Storage::ProjectData>(64, toIntegers(projectSourceIds));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -332,7 +337,7 @@ private:
|
||||
|
||||
friend bool operator==(const Module &first, const Module &second)
|
||||
{
|
||||
return first.id == second.id && first.value == second.value;
|
||||
return &first == &second && first.value == second.value;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -503,7 +508,7 @@ private:
|
||||
AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
|
||||
PropertyDeclarations &relinkablePropertyDeclarations,
|
||||
Prototypes &relinkablePrototypes,
|
||||
const std::vector<int> &sourceIdValues)
|
||||
const SourceIds &updatedSourceIds)
|
||||
{
|
||||
Storage::ExportedTypes exportedTypes;
|
||||
exportedTypes.reserve(types.size() * 3);
|
||||
@@ -517,7 +522,7 @@ private:
|
||||
extractExportedTypes(typeId, type, exportedTypes);
|
||||
}
|
||||
|
||||
synchronizeExportedTypes(sourceIdValues,
|
||||
synchronizeExportedTypes(updatedSourceIds,
|
||||
updatedTypeIds,
|
||||
exportedTypes,
|
||||
relinkableAliasPropertyDeclarations,
|
||||
@@ -532,10 +537,72 @@ private:
|
||||
relinkablePropertyDeclarations);
|
||||
}
|
||||
|
||||
void synchronizeFileStatuses(FileStatuses &fileStatuses, const std::vector<int> &sourceIdValues)
|
||||
void synchronizeProjectDatas(Storage::ProjectDatas &projectDatas,
|
||||
const SourceIds &updatedProjectSourceIds)
|
||||
{
|
||||
auto compareKey = [](auto &&first, auto &&second) {
|
||||
return first.sourceId.id - second.sourceId.id;
|
||||
auto projectSourceIdDifference = &first.projectSourceId - &second.projectSourceId;
|
||||
if (projectSourceIdDifference != 0)
|
||||
return projectSourceIdDifference;
|
||||
|
||||
return &first.sourceId - &second.sourceId;
|
||||
};
|
||||
|
||||
std::sort(projectDatas.begin(), projectDatas.end(), [&](auto &&first, auto &&second) {
|
||||
return std::tie(first.projectSourceId, first.sourceId)
|
||||
< std::tie(second.projectSourceId, second.sourceId);
|
||||
});
|
||||
|
||||
auto range = selectProjectDatasForModuleIdsStatement.template range<Storage::ProjectData>(
|
||||
toIntegers(updatedProjectSourceIds));
|
||||
|
||||
auto insert = [&](const Storage::ProjectData &projectData) {
|
||||
if (!projectData.projectSourceId)
|
||||
throw ProjectDataHasInvalidProjectSourceId{};
|
||||
if (!projectData.sourceId)
|
||||
throw ProjectDataHasInvalidSourceId{};
|
||||
if (!projectData.moduleId)
|
||||
throw ProjectDataHasInvalidModuleId{};
|
||||
|
||||
insertProjectDataStatement.write(&projectData.projectSourceId,
|
||||
&projectData.sourceId,
|
||||
&projectData.moduleId,
|
||||
static_cast<int>(projectData.fileType));
|
||||
};
|
||||
|
||||
auto update = [&](const Storage::ProjectData &projectDataFromDatabase,
|
||||
const Storage::ProjectData &projectData) {
|
||||
if (!projectData.moduleId)
|
||||
throw ProjectDataHasInvalidModuleId{};
|
||||
|
||||
if (projectDataFromDatabase.fileType != projectData.fileType
|
||||
|| projectDataFromDatabase.moduleId != projectData.moduleId) {
|
||||
updateProjectDataStatement.write(&projectData.projectSourceId,
|
||||
&projectData.sourceId,
|
||||
&projectData.moduleId,
|
||||
static_cast<int>(projectData.fileType));
|
||||
return Sqlite::UpdateChange::Update;
|
||||
}
|
||||
|
||||
return Sqlite::UpdateChange::No;
|
||||
};
|
||||
|
||||
auto remove = [&](const Storage::ProjectData &projectData) {
|
||||
deleteProjectDataStatement.write(&projectData.projectSourceId, &projectData.sourceId);
|
||||
};
|
||||
|
||||
Sqlite::insertUpdateDelete(range, projectDatas, compareKey, insert, update, remove);
|
||||
}
|
||||
|
||||
void synchronizeFileStatuses(FileStatuses &fileStatuses, const SourceIds &updatedSourceIds)
|
||||
{
|
||||
auto updatedSourceIdValues = Utils::transform<std::vector>(updatedSourceIds,
|
||||
[](SourceId sourceId) {
|
||||
return &sourceId;
|
||||
});
|
||||
|
||||
auto compareKey = [](auto &&first, auto &&second) {
|
||||
return &first.sourceId - &second.sourceId;
|
||||
};
|
||||
|
||||
std::sort(fileStatuses.begin(), fileStatuses.end(), [&](auto &&first, auto &&second) {
|
||||
@@ -543,7 +610,7 @@ private:
|
||||
});
|
||||
|
||||
auto range = selectFileStatusesForSourceIdsStatement.template range<FileStatus>(
|
||||
Utils::span(sourceIdValues));
|
||||
toIntegers(updatedSourceIds));
|
||||
|
||||
auto insert = [&](const FileStatus &fileStatus) {
|
||||
insertFileStatusStatement.write(&fileStatus.sourceId,
|
||||
@@ -557,7 +624,10 @@ private:
|
||||
updateFileStatusStatement.write(&fileStatus.sourceId,
|
||||
fileStatus.size,
|
||||
fileStatus.lastModified);
|
||||
return Sqlite::UpdateChange::Update;
|
||||
}
|
||||
|
||||
return Sqlite::UpdateChange::No;
|
||||
};
|
||||
|
||||
auto remove = [&](const FileStatus &fileStatus) {
|
||||
@@ -567,30 +637,32 @@ private:
|
||||
Sqlite::insertUpdateDelete(range, fileStatuses, compareKey, insert, update, remove);
|
||||
}
|
||||
|
||||
void synchronizeImports(Storage::Imports &imports, std::vector<int> &sourceIdValues)
|
||||
void synchronizeImports(Storage::Imports &imports, const SourceIds &updatedSourceIds)
|
||||
{
|
||||
deleteDocumentImportsForDeletedDocuments(imports, sourceIdValues);
|
||||
deleteDocumentImportsForDeletedDocuments(imports, updatedSourceIds);
|
||||
|
||||
synchronizeDocumentImports(imports, sourceIdValues);
|
||||
synchronizeDocumentImports(imports, updatedSourceIds);
|
||||
}
|
||||
|
||||
void deleteDocumentImportsForDeletedDocuments(Storage::Imports &imports,
|
||||
const std::vector<int> &sourceIdValues)
|
||||
const SourceIds &updatedSourceIds)
|
||||
{
|
||||
std::vector<int> importSourceIds = Utils::transform<std::vector<int>>(
|
||||
imports, [](const Storage::Import &import) { return &import.sourceId; });
|
||||
SourceIds importSourceIds = Utils::transform<SourceIds>(imports,
|
||||
[](const Storage::Import &import) {
|
||||
return import.sourceId;
|
||||
});
|
||||
|
||||
std::sort(importSourceIds.begin(), importSourceIds.end());
|
||||
|
||||
std::vector<int> documentSourceIdsToBeDeleted;
|
||||
SourceIds documentSourceIdsToBeDeleted;
|
||||
|
||||
std::set_difference(sourceIdValues.begin(),
|
||||
sourceIdValues.end(),
|
||||
std::set_difference(updatedSourceIds.begin(),
|
||||
updatedSourceIds.end(),
|
||||
importSourceIds.begin(),
|
||||
importSourceIds.end(),
|
||||
std::back_inserter(documentSourceIdsToBeDeleted));
|
||||
|
||||
deleteDocumentImportsWithSourceIdsStatement.write(Utils::span{documentSourceIdsToBeDeleted});
|
||||
deleteDocumentImportsWithSourceIdsStatement.write(toIntegers(documentSourceIdsToBeDeleted));
|
||||
}
|
||||
|
||||
ModuleId fetchModuleIdUnguarded(Utils::SmallStringView name) const
|
||||
@@ -767,17 +839,13 @@ private:
|
||||
}
|
||||
|
||||
void deleteNotUpdatedTypes(const TypeIds &updatedTypeIds,
|
||||
const std::vector<int> &sourceIdValues,
|
||||
const SourceIds &updatedSourceIds,
|
||||
const TypeIds &typeIdsToBeDeleted,
|
||||
AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
|
||||
PropertyDeclarations &relinkablePropertyDeclarations,
|
||||
Prototypes &relinkablePrototypes,
|
||||
TypeIds &deletedTypeIds)
|
||||
{
|
||||
auto updatedTypeIdValues = Utils::transform<std::vector>(updatedTypeIds, [](TypeId typeId) {
|
||||
return &typeId;
|
||||
});
|
||||
|
||||
auto callback = [&](long long typeId) {
|
||||
deletedTypeIds.push_back(TypeId{typeId});
|
||||
deleteType(TypeId{typeId},
|
||||
@@ -788,8 +856,8 @@ private:
|
||||
};
|
||||
|
||||
selectNotUpdatedTypesInSourcesStatement.readCallback(callback,
|
||||
Utils::span(sourceIdValues),
|
||||
Utils::span(updatedTypeIdValues));
|
||||
toIntegers(updatedSourceIds),
|
||||
toIntegers(updatedTypeIds));
|
||||
for (TypeId typeIdToBeDeleted : typeIdsToBeDeleted)
|
||||
callback(&typeIdToBeDeleted);
|
||||
}
|
||||
@@ -853,7 +921,7 @@ private:
|
||||
updateAliasPropertyDeclarationValues(updatedAliasPropertyDeclarations);
|
||||
}
|
||||
|
||||
void synchronizeExportedTypes(const std::vector<int> &sourceIdValues,
|
||||
void synchronizeExportedTypes(const SourceIds &exportedSourceIds,
|
||||
const TypeIds &updatedTypeIds,
|
||||
Storage::ExportedTypes &exportedTypes,
|
||||
AliasPropertyDeclarations &relinkableAliasPropertyDeclarations,
|
||||
@@ -865,17 +933,13 @@ private:
|
||||
< std::tie(second.moduleId, second.name, second.version);
|
||||
});
|
||||
|
||||
Utils::span typeIdValues{static_cast<const TypeIds::value_type::DatabaseType *>(
|
||||
&updatedTypeIds.data()->id),
|
||||
updatedTypeIds.size()};
|
||||
|
||||
auto range = selectExportedTypesForSourceIdsStatement
|
||||
.template range<Storage::ExportedTypeView>(Utils::span{sourceIdValues},
|
||||
typeIdValues);
|
||||
.template range<Storage::ExportedTypeView>(toIntegers(exportedSourceIds),
|
||||
toIntegers(updatedTypeIds));
|
||||
|
||||
auto compareKey = [](const Storage::ExportedTypeView &view,
|
||||
const Storage::ExportedType &type) -> long long {
|
||||
auto moduleIdDifference = view.moduleId.id - type.moduleId.id;
|
||||
auto moduleIdDifference = &view.moduleId - &type.moduleId;
|
||||
if (moduleIdDifference != 0)
|
||||
return moduleIdDifference;
|
||||
|
||||
@@ -924,7 +988,9 @@ private:
|
||||
relinkableAliasPropertyDeclarations);
|
||||
handlePrototypes(view.typeId, relinkablePrototypes);
|
||||
updateExportedTypeNameTypeIdStatement.write(&view.exportedTypeNameId, &type.typeId);
|
||||
return Sqlite::UpdateChange::Update;
|
||||
}
|
||||
return Sqlite::UpdateChange::No;
|
||||
};
|
||||
|
||||
auto remove = [&](const Storage::ExportedTypeView &view) {
|
||||
@@ -998,7 +1064,7 @@ private:
|
||||
view.aliasId);
|
||||
}
|
||||
|
||||
void synchronizePropertyDeclarationsUpdateProperty(const Storage::PropertyDeclarationView &view,
|
||||
auto synchronizePropertyDeclarationsUpdateProperty(const Storage::PropertyDeclarationView &view,
|
||||
const Storage::PropertyDeclaration &value,
|
||||
SourceId sourceId,
|
||||
PropertyDeclarationIds &propertyDeclarationIds)
|
||||
@@ -1012,7 +1078,7 @@ private:
|
||||
|
||||
if (view.traits == value.traits && propertyTypeId == view.typeId
|
||||
&& propertyImportedTypeNameId == view.typeNameId)
|
||||
return;
|
||||
return Sqlite::UpdateChange::No;
|
||||
|
||||
updatePropertyDeclarationStatement.write(&view.id,
|
||||
&propertyTypeId,
|
||||
@@ -1021,6 +1087,7 @@ private:
|
||||
updatePropertyAliasDeclarationRecursivelyWithTypeAndTraitsStatement
|
||||
.write(&view.id, &propertyTypeId, static_cast<int>(value.traits));
|
||||
propertyDeclarationIds.push_back(view.id);
|
||||
return Sqlite::UpdateChange::Update;
|
||||
}
|
||||
|
||||
void synchronizePropertyDeclarations(TypeId typeId,
|
||||
@@ -1064,11 +1131,13 @@ private:
|
||||
sourceId);
|
||||
propertyDeclarationIds.push_back(view.id);
|
||||
} else {
|
||||
synchronizePropertyDeclarationsUpdateProperty(view,
|
||||
value,
|
||||
sourceId,
|
||||
propertyDeclarationIds);
|
||||
return synchronizePropertyDeclarationsUpdateProperty(view,
|
||||
value,
|
||||
sourceId,
|
||||
propertyDeclarationIds);
|
||||
}
|
||||
|
||||
return Sqlite::UpdateChange::No;
|
||||
};
|
||||
|
||||
auto remove = [&](const Storage::PropertyDeclarationView &view) {
|
||||
@@ -1127,7 +1196,7 @@ private:
|
||||
auto insert = [&](const Storage::PropertyDeclaration &) {};
|
||||
|
||||
auto update = [&](const AliasPropertyDeclarationView &,
|
||||
const Storage::PropertyDeclaration &) {};
|
||||
const Storage::PropertyDeclaration &) { return Sqlite::UpdateChange::No; };
|
||||
|
||||
auto remove = [&](const AliasPropertyDeclarationView &view) {
|
||||
updatePropertyDeclarationAliasIdToNullStatement.write(&view.id);
|
||||
@@ -1151,7 +1220,7 @@ private:
|
||||
PropertyCompare<AliasPropertyDeclaration>{});
|
||||
}
|
||||
|
||||
void synchronizeDocumentImports(Storage::Imports &imports, const std::vector<int> &sourceIdValues)
|
||||
void synchronizeDocumentImports(Storage::Imports &imports, const SourceIds &updatedSourceIds)
|
||||
{
|
||||
std::sort(imports.begin(), imports.end(), [](auto &&first, auto &&second) {
|
||||
return std::tie(first.sourceId, first.moduleId, first.version)
|
||||
@@ -1159,15 +1228,15 @@ private:
|
||||
});
|
||||
|
||||
auto range = selectDocumentImportForSourceIdStatement.template range<Storage::ImportView>(
|
||||
Utils::span{sourceIdValues});
|
||||
toIntegers(updatedSourceIds));
|
||||
|
||||
auto compareKey = [](const Storage::ImportView &view,
|
||||
const Storage::Import &import) -> long long {
|
||||
auto sourceIdDifference = view.sourceId.id - import.sourceId.id;
|
||||
auto sourceIdDifference = &view.sourceId - &import.sourceId;
|
||||
if (sourceIdDifference != 0)
|
||||
return sourceIdDifference;
|
||||
|
||||
auto moduleIdDifference = view.moduleId.id - import.moduleId.id;
|
||||
auto moduleIdDifference = &view.moduleId - &import.moduleId;
|
||||
if (moduleIdDifference != 0)
|
||||
return moduleIdDifference;
|
||||
|
||||
@@ -1193,7 +1262,9 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
auto update = [](const Storage::ImportView &, const Storage::Import &) {};
|
||||
auto update = [](const Storage::ImportView &, const Storage::Import &) {
|
||||
return Sqlite::UpdateChange::No;
|
||||
};
|
||||
|
||||
auto remove = [&](const Storage::ImportView &view) {
|
||||
deleteDocumentImportStatement.write(&view.importId);
|
||||
@@ -1258,9 +1329,11 @@ private:
|
||||
Utils::PathString signature{createJson(value.parameters)};
|
||||
|
||||
if (value.returnTypeName == view.returnTypeName && signature == view.signature)
|
||||
return;
|
||||
return Sqlite::UpdateChange::No;
|
||||
|
||||
updateFunctionDeclarationStatement.write(&view.id, value.returnTypeName, signature);
|
||||
|
||||
return Sqlite::UpdateChange::Update;
|
||||
};
|
||||
|
||||
auto remove = [&](const Storage::FunctionDeclarationView &view) {
|
||||
@@ -1295,9 +1368,11 @@ private:
|
||||
Utils::PathString signature{createJson(value.parameters)};
|
||||
|
||||
if (signature == view.signature)
|
||||
return;
|
||||
return Sqlite::UpdateChange::No;
|
||||
|
||||
updateSignalDeclarationStatement.write(&view.id, signature);
|
||||
|
||||
return Sqlite::UpdateChange::Update;
|
||||
};
|
||||
|
||||
auto remove = [&](const Storage::SignalDeclarationView &view) {
|
||||
@@ -1360,9 +1435,11 @@ private:
|
||||
Utils::PathString enumeratorDeclarations{createJson(value.enumeratorDeclarations)};
|
||||
|
||||
if (enumeratorDeclarations == view.enumeratorDeclarations)
|
||||
return;
|
||||
return Sqlite::UpdateChange::No;
|
||||
|
||||
updateEnumerationDeclarationStatement.write(&view.id, enumeratorDeclarations);
|
||||
|
||||
return Sqlite::UpdateChange::Update;
|
||||
};
|
||||
|
||||
auto remove = [&](const Storage::EnumerationDeclarationView &view) {
|
||||
@@ -1760,6 +1837,7 @@ private:
|
||||
createSignalsTable(database);
|
||||
createDocumentImportsTable(database, moduleIdColumn);
|
||||
createFileStatusesTable(database);
|
||||
createProjectDatasTable(database);
|
||||
|
||||
transaction.commit();
|
||||
|
||||
@@ -2002,6 +2080,22 @@ private:
|
||||
|
||||
table.initialize(database);
|
||||
}
|
||||
|
||||
void createProjectDatasTable(Database &database)
|
||||
{
|
||||
Sqlite::Table table;
|
||||
table.setUseIfNotExists(true);
|
||||
table.setUseWithoutRowId(true);
|
||||
table.setName("projectDatas");
|
||||
auto &projectSourceIdColumn = table.addColumn("projectSourceId");
|
||||
auto &sourceIdColumn = table.addColumn("sourceId");
|
||||
table.addColumn("moduleId");
|
||||
table.addColumn("fileType");
|
||||
|
||||
table.addPrimaryKeyContraint({projectSourceIdColumn, sourceIdColumn});
|
||||
|
||||
table.initialize(database);
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -2442,6 +2536,22 @@ public:
|
||||
"DELETE FROM exportedTypeNames WHERE exportedTypeNameId=?", database};
|
||||
WriteStatement updateExportedTypeNameTypeIdStatement{
|
||||
"UPDATE exportedTypeNames SET typeId=?2 WHERE exportedTypeNameId=?1", database};
|
||||
mutable ReadStatement<4> selectProjectDatasForModuleIdsStatement{
|
||||
"SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
|
||||
"projectSourceId IN carray(?1) ORDER BY projectSourceId, sourceId",
|
||||
database};
|
||||
WriteStatement insertProjectDataStatement{"INSERT INTO projectDatas(projectSourceId, sourceId, "
|
||||
"moduleId, fileType) VALUES(?1, ?2, ?3, ?4)",
|
||||
database};
|
||||
WriteStatement deleteProjectDataStatement{
|
||||
"DELETE FROM projectDatas WHERE projectSourceId=?1 AND sourceId=?2", database};
|
||||
WriteStatement updateProjectDataStatement{
|
||||
"UPDATE projectDatas SET moduleId=?3, fileType=?4 WHERE projectSourceId=?1 AND sourceId=?2",
|
||||
database};
|
||||
mutable ReadStatement<4> selectProjectDatasForModuleIdStatement{
|
||||
"SELECT projectSourceId, sourceId, moduleId, fileType FROM projectDatas WHERE "
|
||||
"projectSourceId=?1",
|
||||
database};
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -107,4 +107,28 @@ public:
|
||||
const char *what() const noexcept override { return "Cannot parse qml types file!"; }
|
||||
};
|
||||
|
||||
class CannotParseQmlDocumentFile : std::exception
|
||||
{
|
||||
public:
|
||||
const char *what() const noexcept override { return "Cannot parse qml types file!"; }
|
||||
};
|
||||
|
||||
class ProjectDataHasInvalidProjectSourceId : std::exception
|
||||
{
|
||||
public:
|
||||
const char *what() const noexcept override { return "The project source id is invalid!"; }
|
||||
};
|
||||
|
||||
class ProjectDataHasInvalidSourceId : std::exception
|
||||
{
|
||||
public:
|
||||
const char *what() const noexcept override { return "The source id is invalid!"; }
|
||||
};
|
||||
|
||||
class ProjectDataHasInvalidModuleId : std::exception
|
||||
{
|
||||
public:
|
||||
const char *what() const noexcept override { return "The module id is invalid!"; }
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -47,6 +47,8 @@ enum class PropertyDeclarationTraits : unsigned int {
|
||||
|
||||
enum class TypeNameKind { Native = 0, Exported = 1, QualifiedExported = 2 };
|
||||
|
||||
enum class FileType : char { QmlTypes, QmlDocument };
|
||||
|
||||
constexpr PropertyDeclarationTraits operator|(PropertyDeclarationTraits first,
|
||||
PropertyDeclarationTraits second)
|
||||
{
|
||||
@@ -630,7 +632,7 @@ public:
|
||||
PropertyDeclarationId aliasId;
|
||||
};
|
||||
|
||||
enum class ChangeLevel { Full, Minimal };
|
||||
enum class ChangeLevel : char { Full, Minimal, ExcludeExportedTypes };
|
||||
|
||||
class Type
|
||||
{
|
||||
@@ -668,6 +670,18 @@ public:
|
||||
, prototypeId{prototypeId}
|
||||
{}
|
||||
|
||||
explicit Type(Utils::SmallStringView typeName,
|
||||
ImportedTypeName prototype,
|
||||
TypeAccessSemantics accessSemantics,
|
||||
SourceId sourceId,
|
||||
ChangeLevel changeLevel)
|
||||
: typeName{typeName}
|
||||
, prototype{std::move(prototype)}
|
||||
, accessSemantics{accessSemantics}
|
||||
, sourceId{sourceId}
|
||||
, changeLevel{changeLevel}
|
||||
{}
|
||||
|
||||
explicit Type(Utils::SmallStringView typeName,
|
||||
Utils::SmallStringView prototype,
|
||||
int accessSemantics,
|
||||
@@ -721,8 +735,31 @@ using Types = std::vector<Type>;
|
||||
class ProjectData
|
||||
{
|
||||
public:
|
||||
ModuleId extraModuleId;
|
||||
ProjectData(SourceId projectSourceId, SourceId sourceId, ModuleId moduleId, FileType fileType)
|
||||
: projectSourceId{projectSourceId}
|
||||
, sourceId{sourceId}
|
||||
, moduleId{moduleId}
|
||||
, fileType{fileType}
|
||||
{}
|
||||
|
||||
ProjectData(int projectSourceId, int sourceId, int moduleId, int fileType)
|
||||
: projectSourceId{projectSourceId}
|
||||
, sourceId{sourceId}
|
||||
, moduleId{moduleId}
|
||||
, fileType{static_cast<Storage::FileType>(fileType)}
|
||||
{}
|
||||
|
||||
friend bool operator==(const ProjectData &first, const ProjectData &second)
|
||||
{
|
||||
return first.projectSourceId == second.projectSourceId && first.sourceId == second.sourceId
|
||||
&& first.moduleId == second.moduleId && first.fileType == second.fileType;
|
||||
}
|
||||
|
||||
public:
|
||||
SourceId projectSourceId;
|
||||
SourceId sourceId;
|
||||
ModuleId moduleId;
|
||||
FileType fileType;
|
||||
};
|
||||
|
||||
using ProjectDatas = std::vector<ProjectData>;
|
||||
@@ -731,30 +768,38 @@ class SynchronizationPackage
|
||||
{
|
||||
public:
|
||||
SynchronizationPackage() = default;
|
||||
SynchronizationPackage(Imports imports, Types types, SourceIds sourceIds)
|
||||
SynchronizationPackage(Imports imports, Types types, SourceIds updatedSourceIds)
|
||||
: imports{std::move(imports)}
|
||||
, types{std::move(types)}
|
||||
, sourceIds(std::move(sourceIds))
|
||||
, updatedSourceIds(std::move(updatedSourceIds))
|
||||
{}
|
||||
|
||||
SynchronizationPackage(Types types)
|
||||
: types{std::move(types)}
|
||||
{}
|
||||
|
||||
SynchronizationPackage(SourceIds sourceIds)
|
||||
: sourceIds(std::move(sourceIds))
|
||||
SynchronizationPackage(SourceIds updatedSourceIds)
|
||||
: updatedSourceIds(std::move(updatedSourceIds))
|
||||
{}
|
||||
|
||||
SynchronizationPackage(SourceIds sourceIds, FileStatuses fileStatuses)
|
||||
: sourceIds(std::move(sourceIds))
|
||||
SynchronizationPackage(SourceIds updatedFileStatusSourceIds, FileStatuses fileStatuses)
|
||||
: updatedFileStatusSourceIds(std::move(updatedFileStatusSourceIds))
|
||||
, fileStatuses(std::move(fileStatuses))
|
||||
{}
|
||||
|
||||
SynchronizationPackage(SourceIds updatedProjectSourceIds, ProjectDatas projectDatas)
|
||||
: projectDatas(std::move(projectDatas))
|
||||
, updatedProjectSourceIds(std::move(updatedProjectSourceIds))
|
||||
{}
|
||||
|
||||
public:
|
||||
Imports imports;
|
||||
Types types;
|
||||
SourceIds sourceIds;
|
||||
SourceIds updatedSourceIds;
|
||||
FileStatuses fileStatuses;
|
||||
ProjectDatas projectDatas;
|
||||
SourceIds updatedProjectSourceIds;
|
||||
SourceIds updatedFileStatusSourceIds;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner::Storage
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <functional>
|
||||
|
||||
namespace QmlDesigner {
|
||||
namespace {
|
||||
|
||||
ComponentReferences createComponentReferences(const QMultiHash<QString, QmlDirParser::Component> &components)
|
||||
{
|
||||
@@ -50,53 +51,117 @@ ComponentReferences createComponentReferences(const QMultiHash<QString, QmlDirPa
|
||||
return componentReferences;
|
||||
}
|
||||
|
||||
SourceIds filterNotUpdatedSourceIds(SourceIds updatedSourceIds, SourceIds notUpdatedSourceIds)
|
||||
{
|
||||
std::sort(updatedSourceIds.begin(), updatedSourceIds.end());
|
||||
std::sort(notUpdatedSourceIds.begin(), notUpdatedSourceIds.end());
|
||||
|
||||
SourceIds filteredUpdatedSourceIds;
|
||||
filteredUpdatedSourceIds.reserve(updatedSourceIds.size());
|
||||
|
||||
std::set_difference(updatedSourceIds.cbegin(),
|
||||
updatedSourceIds.cend(),
|
||||
notUpdatedSourceIds.cbegin(),
|
||||
notUpdatedSourceIds.cend(),
|
||||
std::back_inserter(filteredUpdatedSourceIds));
|
||||
|
||||
filteredUpdatedSourceIds.erase(std::unique(filteredUpdatedSourceIds.begin(),
|
||||
filteredUpdatedSourceIds.end()),
|
||||
filteredUpdatedSourceIds.end());
|
||||
|
||||
return filteredUpdatedSourceIds;
|
||||
}
|
||||
|
||||
void addSourceIds(SourceIds &sourceIds, const Storage::ProjectDatas &projectDatas)
|
||||
{
|
||||
for (const auto &projectData : projectDatas)
|
||||
sourceIds.push_back(projectData.sourceId);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ProjectUpdater::update()
|
||||
{
|
||||
Storage::SynchronizationPackage package;
|
||||
|
||||
SourceIds notUpdatedFileStatusSourceIds;
|
||||
SourceIds notUpdatedSourceIds;
|
||||
|
||||
for (const QString &qmldirPath : m_projectManager.qtQmlDirs()) {
|
||||
SourcePath qmldirSourcePath{qmldirPath};
|
||||
SourceId qmlDirSourceId = m_pathCache.sourceId(qmldirSourcePath);
|
||||
|
||||
switch (fileState(qmlDirSourceId, package.fileStatuses)) {
|
||||
auto state = fileState(qmlDirSourceId,
|
||||
package.fileStatuses,
|
||||
package.updatedFileStatusSourceIds,
|
||||
notUpdatedFileStatusSourceIds);
|
||||
switch (state) {
|
||||
case FileState::Changed: {
|
||||
QmlDirParser parser;
|
||||
parser.parse(m_fileSystem.contentAsQString(qmldirPath));
|
||||
|
||||
package.sourceIds.push_back(qmlDirSourceId);
|
||||
package.updatedSourceIds.push_back(qmlDirSourceId);
|
||||
|
||||
SourceContextId directoryId = m_pathCache.sourceContextId(qmlDirSourceId);
|
||||
|
||||
Utils::PathString moduleName{parser.typeNamespace()};
|
||||
ModuleId moduleId = m_projectStorage.moduleId(moduleName);
|
||||
|
||||
parseTypeInfos(parser.typeInfos(), directoryId, package);
|
||||
const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
|
||||
addSourceIds(package.updatedSourceIds, qmlProjectDatas);
|
||||
addSourceIds(package.updatedFileStatusSourceIds, qmlProjectDatas);
|
||||
|
||||
parseTypeInfos(parser.typeInfos(),
|
||||
qmlDirSourceId,
|
||||
directoryId,
|
||||
moduleId,
|
||||
package,
|
||||
notUpdatedFileStatusSourceIds,
|
||||
notUpdatedSourceIds);
|
||||
parseQmlComponents(createComponentReferences(parser.components()),
|
||||
qmlDirSourceId,
|
||||
directoryId,
|
||||
moduleId,
|
||||
package);
|
||||
package,
|
||||
notUpdatedFileStatusSourceIds);
|
||||
package.updatedProjectSourceIds.push_back(qmlDirSourceId);
|
||||
break;
|
||||
}
|
||||
case FileState::NotChanged: {
|
||||
auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
|
||||
parseTypeInfos(qmlProjectDatas, package);
|
||||
const auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
|
||||
parseTypeInfos(qmlProjectDatas, package, notUpdatedFileStatusSourceIds, notUpdatedSourceIds);
|
||||
parseQmlComponents(qmlProjectDatas, package, notUpdatedFileStatusSourceIds);
|
||||
break;
|
||||
}
|
||||
case FileState::NotExists: {
|
||||
// sourceIds.push_back(qmlDirSourceId);
|
||||
package.updatedSourceIds.push_back(qmlDirSourceId);
|
||||
auto qmlProjectDatas = m_projectStorage.fetchProjectDatas(qmlDirSourceId);
|
||||
for (const Storage::ProjectData &projectData : qmlProjectDatas) {
|
||||
package.updatedSourceIds.push_back(projectData.sourceId);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
package.updatedSourceIds = filterNotUpdatedSourceIds(std::move(package.updatedSourceIds),
|
||||
std::move(notUpdatedSourceIds));
|
||||
package.updatedFileStatusSourceIds = filterNotUpdatedSourceIds(
|
||||
std::move(package.updatedFileStatusSourceIds), std::move(notUpdatedFileStatusSourceIds));
|
||||
|
||||
m_projectStorage.synchronize(std::move(package));
|
||||
}
|
||||
|
||||
void ProjectUpdater::pathsWithIdsChanged(const std::vector<IdPaths> &idPaths) {}
|
||||
|
||||
void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos,
|
||||
SourceId qmldirSourceId,
|
||||
SourceContextId directoryId,
|
||||
Storage::SynchronizationPackage &package)
|
||||
ModuleId moduleId,
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds,
|
||||
SourceIds ¬UpdatedSourceIds)
|
||||
{
|
||||
QString directory{m_pathCache.sourceContextPath(directoryId)};
|
||||
|
||||
@@ -104,37 +169,140 @@ void ProjectUpdater::parseTypeInfos(const QStringList &typeInfos,
|
||||
SourceId sourceId = m_pathCache.sourceId(directoryId, Utils::SmallString{typeInfo});
|
||||
QString qmltypesPath = directory + "/" + typeInfo;
|
||||
|
||||
Storage::ProjectData projectData{ModuleId{}, sourceId};
|
||||
auto projectData = package.projectDatas.emplace_back(qmldirSourceId,
|
||||
sourceId,
|
||||
moduleId,
|
||||
Storage::FileType::QmlTypes);
|
||||
|
||||
parseTypeInfo(projectData, qmltypesPath, package);
|
||||
parseTypeInfo(projectData,
|
||||
qmltypesPath,
|
||||
package,
|
||||
notUpdatedFileStatusSourceIds,
|
||||
notUpdatedSourceIds);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectUpdater::parseTypeInfos(const Storage::ProjectDatas &projectDatas,
|
||||
Storage::SynchronizationPackage &package)
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds,
|
||||
SourceIds ¬UpdatedSourceIds)
|
||||
{
|
||||
for (const Storage::ProjectData &projectData : projectDatas) {
|
||||
if (projectData.fileType != Storage::FileType::QmlTypes)
|
||||
continue;
|
||||
|
||||
QString qmltypesPath = m_pathCache.sourcePath(projectData.sourceId).toQString();
|
||||
|
||||
parseTypeInfo(projectData, qmltypesPath, package);
|
||||
parseTypeInfo(projectData,
|
||||
qmltypesPath,
|
||||
package,
|
||||
notUpdatedFileStatusSourceIds,
|
||||
notUpdatedSourceIds);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectUpdater::parseTypeInfo(const Storage::ProjectData &projectData,
|
||||
const QString &qmltypesPath,
|
||||
Storage::SynchronizationPackage &package)
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds,
|
||||
SourceIds ¬UpdatedSourceIds)
|
||||
{
|
||||
if (fileState(projectData.sourceId, package.fileStatuses) == FileState::Changed) {
|
||||
package.sourceIds.push_back(projectData.sourceId);
|
||||
auto state = fileState(projectData.sourceId,
|
||||
package.fileStatuses,
|
||||
package.updatedFileStatusSourceIds,
|
||||
notUpdatedFileStatusSourceIds);
|
||||
switch (state) {
|
||||
case FileState::Changed: {
|
||||
package.updatedSourceIds.push_back(projectData.sourceId);
|
||||
|
||||
const auto content = m_fileSystem.contentAsQString(qmltypesPath);
|
||||
m_qmlTypesParser.parse(content, package.imports, package.types, projectData);
|
||||
break;
|
||||
}
|
||||
case FileState::NotChanged: {
|
||||
notUpdatedSourceIds.push_back(projectData.sourceId);
|
||||
break;
|
||||
}
|
||||
case FileState::NotExists:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectUpdater::parseQmlComponent(Utils::SmallStringView fileName,
|
||||
Utils::SmallStringView directory,
|
||||
Utils::SmallStringView typeName,
|
||||
Storage::Version version,
|
||||
ModuleId moduleId,
|
||||
SourceId qmldirSourceId,
|
||||
SourceContextId directoryId,
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds)
|
||||
{
|
||||
SourceId sourceId = m_pathCache.sourceId(directoryId, fileName);
|
||||
|
||||
Storage::Type type;
|
||||
|
||||
auto state = fileState(sourceId,
|
||||
package.fileStatuses,
|
||||
package.updatedFileStatusSourceIds,
|
||||
notUpdatedFileStatusSourceIds);
|
||||
switch (state) {
|
||||
case FileState::NotChanged:
|
||||
type.changeLevel = Storage::ChangeLevel::Minimal;
|
||||
break;
|
||||
case FileState::NotExists:
|
||||
throw CannotParseQmlDocumentFile{};
|
||||
case FileState::Changed:
|
||||
const auto content = m_fileSystem.contentAsQString(
|
||||
QString{Utils::PathString{directory} + "/" + fileName});
|
||||
type = m_qmlDocumentParser.parse(content, package.imports);
|
||||
break;
|
||||
}
|
||||
|
||||
package.projectDatas.emplace_back(qmldirSourceId, sourceId, moduleId, Storage::FileType::QmlDocument);
|
||||
|
||||
package.updatedSourceIds.push_back(sourceId);
|
||||
|
||||
type.typeName = fileName;
|
||||
type.accessSemantics = Storage::TypeAccessSemantics::Reference;
|
||||
type.sourceId = sourceId;
|
||||
type.exportedTypes.push_back(Storage::ExportedType{moduleId, typeName, version});
|
||||
|
||||
package.types.push_back(std::move(type));
|
||||
}
|
||||
|
||||
void ProjectUpdater::parseQmlComponent(Utils::SmallStringView fileName,
|
||||
Utils::SmallStringView filePath,
|
||||
SourceId sourceId,
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds)
|
||||
{
|
||||
auto state = fileState(sourceId,
|
||||
package.fileStatuses,
|
||||
package.updatedFileStatusSourceIds,
|
||||
notUpdatedFileStatusSourceIds);
|
||||
if (state != FileState::Changed)
|
||||
return;
|
||||
|
||||
package.updatedSourceIds.push_back(sourceId);
|
||||
|
||||
const auto content = m_fileSystem.contentAsQString(QString{filePath});
|
||||
auto type = m_qmlDocumentParser.parse(content, package.imports);
|
||||
|
||||
type.typeName = fileName;
|
||||
type.accessSemantics = Storage::TypeAccessSemantics::Reference;
|
||||
type.sourceId = sourceId;
|
||||
type.changeLevel = Storage::ChangeLevel::ExcludeExportedTypes;
|
||||
|
||||
package.types.push_back(std::move(type));
|
||||
}
|
||||
|
||||
void ProjectUpdater::parseQmlComponents(ComponentReferences components,
|
||||
SourceId qmldirSourceId,
|
||||
SourceContextId directoryId,
|
||||
ModuleId moduleId,
|
||||
Storage::SynchronizationPackage &package)
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds)
|
||||
{
|
||||
std::sort(components.begin(), components.end(), [](auto &&first, auto &&second) {
|
||||
return std::tie(first.get().typeName, first.get().majorVersion, first.get().minorVersion)
|
||||
@@ -148,33 +316,43 @@ void ProjectUpdater::parseQmlComponents(ComponentReferences components,
|
||||
|
||||
components.erase(newEnd, components.end());
|
||||
|
||||
QString directory{m_pathCache.sourceContextPath(directoryId)};
|
||||
auto directory = m_pathCache.sourceContextPath(directoryId);
|
||||
|
||||
for (const QmlDirParser::Component &component : components) {
|
||||
Utils::SmallString fileName{component.fileName};
|
||||
SourceId sourceId = m_pathCache.sourceId(directoryId, fileName);
|
||||
|
||||
if (fileState(sourceId, package.fileStatuses) != FileState::Changed)
|
||||
continue;
|
||||
|
||||
package.sourceIds.push_back(sourceId);
|
||||
|
||||
const auto content = m_fileSystem.contentAsQString(directory + "/" + component.fileName);
|
||||
auto type = m_qmlDocumentParser.parse(content, package.imports);
|
||||
|
||||
type.typeName = fileName;
|
||||
type.accessSemantics = Storage::TypeAccessSemantics::Reference;
|
||||
type.sourceId = sourceId;
|
||||
type.exportedTypes.push_back(
|
||||
Storage::ExportedType{moduleId,
|
||||
Utils::SmallString{component.typeName},
|
||||
Storage::Version{component.majorVersion, component.minorVersion}});
|
||||
|
||||
package.types.push_back(std::move(type));
|
||||
parseQmlComponent(Utils::SmallString{component.fileName},
|
||||
directory,
|
||||
Utils::SmallString{component.typeName},
|
||||
Storage::Version{component.majorVersion, component.minorVersion},
|
||||
moduleId,
|
||||
qmldirSourceId,
|
||||
directoryId,
|
||||
package,
|
||||
notUpdatedFileStatusSourceIds);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectUpdater::FileState ProjectUpdater::fileState(SourceId sourceId, FileStatuses &fileStatuses) const
|
||||
void ProjectUpdater::parseQmlComponents(const Storage::ProjectDatas &projectDatas,
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds)
|
||||
{
|
||||
for (const Storage::ProjectData &projectData : projectDatas) {
|
||||
if (projectData.fileType != Storage::FileType::QmlDocument)
|
||||
continue;
|
||||
|
||||
SourcePath qmlDocumentPath = m_pathCache.sourcePath(projectData.sourceId);
|
||||
|
||||
parseQmlComponent(qmlDocumentPath.name(),
|
||||
qmlDocumentPath,
|
||||
projectData.sourceId,
|
||||
package,
|
||||
notUpdatedFileStatusSourceIds);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectUpdater::FileState ProjectUpdater::fileState(SourceId sourceId,
|
||||
FileStatuses &fileStatuses,
|
||||
SourceIds &updatedSourceIds,
|
||||
SourceIds ¬UpdatedSourceIds) const
|
||||
{
|
||||
auto currentFileStatus = m_fileStatusCache.find(sourceId);
|
||||
|
||||
@@ -185,9 +363,11 @@ ProjectUpdater::FileState ProjectUpdater::fileState(SourceId sourceId, FileStatu
|
||||
|
||||
if (!projectStorageFileStatus.isValid() || projectStorageFileStatus != currentFileStatus) {
|
||||
fileStatuses.push_back(currentFileStatus);
|
||||
updatedSourceIds.push_back(currentFileStatus.sourceId);
|
||||
return FileState::Changed;
|
||||
}
|
||||
|
||||
notUpdatedSourceIds.push_back(currentFileStatus.sourceId);
|
||||
return FileState::NotChanged;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,19 +87,49 @@ private:
|
||||
};
|
||||
|
||||
void parseTypeInfos(const QStringList &typeInfos,
|
||||
SourceId qmldirSourceId,
|
||||
SourceContextId directoryId,
|
||||
Storage::SynchronizationPackage &package);
|
||||
ModuleId moduleId,
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds,
|
||||
SourceIds ¬UpdatedSourceIds);
|
||||
void parseTypeInfos(const Storage::ProjectDatas &projectDatas,
|
||||
Storage::SynchronizationPackage &package);
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds,
|
||||
SourceIds ¬UpdatedSourceIds);
|
||||
void parseTypeInfo(const Storage::ProjectData &projectData,
|
||||
const QString &qmltypesPath,
|
||||
Storage::SynchronizationPackage &package);
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds,
|
||||
SourceIds ¬UpdatedSourceIds);
|
||||
void parseQmlComponents(ComponentReferences components,
|
||||
SourceId qmldirSourceId,
|
||||
SourceContextId directoryId,
|
||||
ModuleId moduleId,
|
||||
Storage::SynchronizationPackage &package);
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds);
|
||||
void parseQmlComponents(const Storage::ProjectDatas &projectDatas,
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds);
|
||||
void parseQmlComponent(Utils::SmallStringView fileName,
|
||||
Utils::SmallStringView directory,
|
||||
Utils::SmallStringView typeName,
|
||||
Storage::Version version,
|
||||
ModuleId moduleId,
|
||||
SourceId qmldirSourceId,
|
||||
SourceContextId directoryId,
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds);
|
||||
void parseQmlComponent(Utils::SmallStringView fileName,
|
||||
Utils::SmallStringView filePath,
|
||||
SourceId sourceId,
|
||||
Storage::SynchronizationPackage &package,
|
||||
SourceIds ¬UpdatedFileStatusSourceIds);
|
||||
|
||||
FileState fileState(SourceId sourceId, FileStatuses &fileStatuses) const;
|
||||
FileState fileState(SourceId sourceId,
|
||||
FileStatuses &fileStatuses,
|
||||
SourceIds &updatedSourceIds,
|
||||
SourceIds ¬UpdatedSourceIds) const;
|
||||
|
||||
private:
|
||||
ProjectManagerInterface &m_projectManager;
|
||||
|
||||
@@ -283,7 +283,7 @@ void addTypes(Storage::Types &types,
|
||||
types.reserve(Utils::usize(objects) + types.size());
|
||||
|
||||
for (const auto &object : objects)
|
||||
addType(types, projectData.sourceId, projectData.extraModuleId, *object.get(), storage);
|
||||
addType(types, projectData.sourceId, projectData.moduleId, *object.get(), storage);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -231,6 +231,7 @@ void DesignModeWidget::setup()
|
||||
|
||||
ADS::DockManager::setConfigFlags(ADS::DockManager::DefaultNonOpaqueConfig);
|
||||
ADS::DockManager::setConfigFlag(ADS::DockManager::FocusHighlighting, true);
|
||||
ADS::DockManager::setConfigFlag(ADS::DockManager::OpaqueSplitterResize, true);
|
||||
ADS::DockManager::setConfigFlag(ADS::DockManager::AllTabsHaveCloseButton, true);
|
||||
m_dockManager = new ADS::DockManager(this);
|
||||
m_dockManager->setSettings(settings);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 267 B |
Binary file not shown.
|
Before Width: | Height: | Size: 521 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -31,7 +31,6 @@
|
||||
<file>images/text-edit-icon16.png</file>
|
||||
<file>images/text-input-icon16.png</file>
|
||||
<file>images/webview-icon16.png</file>
|
||||
<file>source/audio.qml</file>
|
||||
<file>source/listview.qml</file>
|
||||
<file>source/listviewv2.qml</file>
|
||||
<file>source/gridview.qml</file>
|
||||
@@ -84,9 +83,6 @@
|
||||
<file>images/loader-icon.png</file>
|
||||
<file>images/loader-icon@2x.png</file>
|
||||
<file>images/loader-icon16.png</file>
|
||||
<file>images/audio-16px.png</file>
|
||||
<file>images/audio-24px.png</file>
|
||||
<file>images/audio-24px@2x.png</file>
|
||||
<file>images/audio-output-16px.png</file>
|
||||
<file>images/audio-output-24px.png</file>
|
||||
<file>images/audio-output-24px@2x.png</file>
|
||||
|
||||
@@ -522,28 +522,6 @@ MetaInfo {
|
||||
}
|
||||
}
|
||||
|
||||
Type {
|
||||
name: "QtMultimedia.MediaPlayer"
|
||||
icon: ":/qtquickplugin/images/audio-16px.png"
|
||||
|
||||
Hints {
|
||||
visibleInNavigator: true
|
||||
canBeDroppedInNavigator: true
|
||||
canBeDroppedInFormEditor: false
|
||||
canBeContainer: false
|
||||
}
|
||||
|
||||
ItemLibraryEntry {
|
||||
name: "Audio"
|
||||
category: "f.Qt Quick - Multimedia"
|
||||
libraryIcon: ":/qtquickplugin/images/audio-24px.png"
|
||||
version: "6.0"
|
||||
requiredImport: "QtMultimedia"
|
||||
|
||||
QmlSource { source: ":/qtquickplugin/source/audio.qml" }
|
||||
}
|
||||
}
|
||||
|
||||
Type {
|
||||
name: "QtMultimedia.AudioOutput"
|
||||
icon: ":/qtquickplugin/images/audio-output-16px.png"
|
||||
@@ -564,6 +542,26 @@ MetaInfo {
|
||||
}
|
||||
}
|
||||
|
||||
Type {
|
||||
name: "QtMultimedia.VideoOutput"
|
||||
icon: ":/qtquickplugin/images/video-output-16px.png"
|
||||
|
||||
Hints {
|
||||
visibleInNavigator: true
|
||||
canBeDroppedInNavigator: true
|
||||
canBeDroppedInFormEditor: false
|
||||
canBeContainer: false
|
||||
}
|
||||
|
||||
ItemLibraryEntry {
|
||||
name: "Video Output"
|
||||
category: "f.Qt Quick - Multimedia"
|
||||
libraryIcon: ":/qtquickplugin/images/video-output-24px.png"
|
||||
version: "6.0"
|
||||
requiredImport: "QtMultimedia"
|
||||
}
|
||||
}
|
||||
|
||||
Type {
|
||||
name: "QtMultimedia.Video"
|
||||
icon: ":/qtquickplugin/images/video-16px.png"
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2021 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtMultimedia 6.0
|
||||
|
||||
MediaPlayer {
|
||||
audioOutput: output
|
||||
|
||||
AudioOutput {
|
||||
id: output
|
||||
}
|
||||
}
|
||||
@@ -123,6 +123,10 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi
|
||||
if (qt6ProjectProperty.isValid() && qt6ProjectProperty.value.toBool())
|
||||
projectItem->setQt6Project(qt6ProjectProperty.value.toBool());
|
||||
|
||||
const auto widgetAppProperty = rootNode->property("widgetApp");
|
||||
if (widgetAppProperty.isValid())
|
||||
projectItem->setWidgetApp(widgetAppProperty.value.toBool());
|
||||
|
||||
if (debug)
|
||||
qDebug() << "importPath:" << importPathsProperty.value << "mainFile:" << mainFileProperty.value;
|
||||
|
||||
|
||||
@@ -78,6 +78,9 @@ public:
|
||||
QString mainFile() const { return m_mainFile; }
|
||||
void setMainFile(const QString &mainFilePath) { m_mainFile = mainFilePath; }
|
||||
|
||||
bool widgetApp() const { return m_widgetApp; }
|
||||
void setWidgetApp(bool widgetApp) { m_widgetApp = widgetApp; }
|
||||
|
||||
void appendContent(QmlProjectContentItem *item) { m_content.append(item); }
|
||||
|
||||
Utils::EnvironmentItems environment() const;
|
||||
@@ -99,6 +102,7 @@ protected:
|
||||
bool m_forceFreeType = false;
|
||||
bool m_qtForMCUs = false;
|
||||
bool m_qt6Project = false;
|
||||
bool m_widgetApp = false;
|
||||
};
|
||||
|
||||
} // namespace QmlProjectManager
|
||||
|
||||
@@ -585,6 +585,13 @@ bool QmlBuildSystem::forceFreeType() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QmlBuildSystem::widgetApp() const
|
||||
{
|
||||
if (m_projectItem)
|
||||
return m_projectItem.data()->widgetApp();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QmlBuildSystem::addFiles(Node *context, const FilePaths &filePaths, FilePaths *)
|
||||
{
|
||||
if (!dynamic_cast<QmlProjectNode *>(context))
|
||||
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
QString primaryLanguage() const;
|
||||
void setPrimaryLanguage(QString language);
|
||||
bool forceFreeType() const;
|
||||
bool widgetApp() const;
|
||||
|
||||
bool addFiles(const QStringList &filePaths);
|
||||
|
||||
|
||||
@@ -227,6 +227,11 @@ QString QmlProjectRunConfiguration::commandLineArguments() const
|
||||
ProcessArgs::addArg(&args, "windows:fontengine=freetype", osType);
|
||||
}
|
||||
|
||||
if (bs->qt6Project() && bs->widgetApp()) {
|
||||
ProcessArgs::addArg(&args, "--apptype", osType);
|
||||
ProcessArgs::addArg(&args, "widget", osType);
|
||||
}
|
||||
|
||||
const QString main = bs->targetFile(FilePath::fromString(mainScript())).toString();
|
||||
if (!main.isEmpty())
|
||||
ProcessArgs::addArg(&args, main, osType);
|
||||
|
||||
@@ -185,7 +185,13 @@ void QnxToolChain::setCpuDir(const QString &cpuDir)
|
||||
|
||||
GccToolChain::DetectedAbisResult QnxToolChain::detectSupportedAbis() const
|
||||
{
|
||||
return detectTargetAbis(m_sdpPath);
|
||||
// "unknown-qnx-gnu"is needed to get the "--target=xxx" parameter sent code model,
|
||||
// which gets translated as "x86_64-qnx-gnu", which gets Clang to happily parse
|
||||
// the QNX code.
|
||||
//
|
||||
// Without it on Windows Clang defaults to a MSVC mode, which breaks with
|
||||
// the QNX code, which is mostly GNU based.
|
||||
return GccToolChain::DetectedAbisResult{detectTargetAbis(m_sdpPath), "unknown-qnx-gnu"};
|
||||
}
|
||||
|
||||
bool QnxToolChain::operator ==(const ToolChain &other) const
|
||||
|
||||
@@ -96,7 +96,7 @@ QPixmap NewProjectDialogImageProvider::requestDefaultPixmap(const QString &id, Q
|
||||
}
|
||||
|
||||
if (pixmap.isNull())
|
||||
return QPixmap{};
|
||||
return {};
|
||||
|
||||
if (requestedSize.isValid())
|
||||
return pixmap.scaled(requestedSize);
|
||||
|
||||
@@ -94,7 +94,7 @@ QdsNewDialog::QdsNewDialog(QWidget *parent)
|
||||
m_dialog->setWindowModality(Qt::ApplicationModal);
|
||||
m_dialog->setWindowFlags(Qt::Dialog);
|
||||
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
m_dialog->setMinimumSize(1110, 554);
|
||||
m_dialog->setMinimumSize(1066, 554);
|
||||
|
||||
QSize screenSize = m_dialog->screen()->geometry().size();
|
||||
if (screenSize.height() < 1080)
|
||||
|
||||
@@ -126,7 +126,7 @@ CodeAssistantPrivate::CodeAssistantPrivate(CodeAssistant *assistant)
|
||||
connect(&m_automaticProposalTimer, &QTimer::timeout,
|
||||
this, &CodeAssistantPrivate::automaticProposalTimeout);
|
||||
|
||||
m_settings = TextEditorSettings::completionSettings();
|
||||
updateFromCompletionSettings(TextEditorSettings::completionSettings());
|
||||
connect(TextEditorSettings::instance(), &TextEditorSettings::completionSettingsChanged,
|
||||
this, &CodeAssistantPrivate::updateFromCompletionSettings);
|
||||
|
||||
|
||||
@@ -93,10 +93,8 @@ bool FindInCurrentFile::isEnabled() const
|
||||
void FindInCurrentFile::handleFileChange(Core::IEditor *editor)
|
||||
{
|
||||
if (!editor) {
|
||||
if (m_currentDocument) {
|
||||
m_currentDocument = nullptr;
|
||||
emit enabledChanged(isEnabled());
|
||||
}
|
||||
m_currentDocument = nullptr;
|
||||
emit enabledChanged(isEnabled());
|
||||
} else {
|
||||
Core::IDocument *document = editor->document();
|
||||
if (document != m_currentDocument) {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QLatin1String>
|
||||
@@ -77,7 +78,7 @@ const QLatin1String kModified("modified");
|
||||
SnippetsCollection::Hint::Hint(int index) : m_index(index)
|
||||
{}
|
||||
|
||||
SnippetsCollection::Hint::Hint(int index, QList<Snippet>::iterator it) : m_index(index), m_it(it)
|
||||
SnippetsCollection::Hint::Hint(int index, QVector<Snippet>::iterator it) : m_index(index), m_it(it)
|
||||
{}
|
||||
|
||||
int SnippetsCollection::Hint::index() const
|
||||
@@ -112,7 +113,7 @@ void SnippetsCollection::insertSnippet(const Snippet &snippet, const Hint &hint)
|
||||
{
|
||||
const int group = groupIndex(snippet.groupId());
|
||||
if (snippet.isBuiltIn() && snippet.isRemoved()) {
|
||||
m_activeSnippetsEnd[group] = m_snippets[group].insert(m_activeSnippetsEnd[group], snippet);
|
||||
m_snippets[group].append(snippet);
|
||||
} else {
|
||||
m_snippets[group].insert(hint.m_it, snippet);
|
||||
updateActiveSnippetsEnd(group);
|
||||
@@ -122,9 +123,12 @@ void SnippetsCollection::insertSnippet(const Snippet &snippet, const Hint &hint)
|
||||
SnippetsCollection::Hint SnippetsCollection::computeInsertionHint(const Snippet &snippet)
|
||||
{
|
||||
const int group = groupIndex(snippet.groupId());
|
||||
QList<Snippet> &snippets = m_snippets[group];
|
||||
QList<Snippet>::iterator it = std::upper_bound(snippets.begin(), m_activeSnippetsEnd.at(group),
|
||||
snippet, snippetComp);
|
||||
QVector<Snippet> &snippets = m_snippets[group];
|
||||
QVector<Snippet>::iterator it = std::upper_bound(snippets.begin(),
|
||||
snippets.begin()
|
||||
+ m_activeSnippetsCount.at(group),
|
||||
snippet,
|
||||
snippetComp);
|
||||
return Hint(static_cast<int>(std::distance(snippets.begin(), it)), it);
|
||||
}
|
||||
|
||||
@@ -157,13 +161,16 @@ SnippetsCollection::Hint SnippetsCollection::computeReplacementHint(int index,
|
||||
const Snippet &snippet)
|
||||
{
|
||||
const int group = groupIndex(snippet.groupId());
|
||||
QList<Snippet> &snippets = m_snippets[group];
|
||||
QList<Snippet>::iterator it = std::lower_bound(snippets.begin(), m_activeSnippetsEnd.at(group),
|
||||
snippet, snippetComp);
|
||||
QVector<Snippet> &snippets = m_snippets[group];
|
||||
auto activeSnippetsEnd = snippets.begin() + m_activeSnippetsCount.at(group);
|
||||
QVector<Snippet>::iterator it = std::lower_bound(snippets.begin(),
|
||||
activeSnippetsEnd,
|
||||
snippet,
|
||||
snippetComp);
|
||||
int hintIndex = static_cast<int>(std::distance(snippets.begin(), it));
|
||||
if (index < hintIndex - 1)
|
||||
return Hint(hintIndex - 1, it);
|
||||
it = std::upper_bound(it, m_activeSnippetsEnd.at(group), snippet, snippetComp);
|
||||
it = std::upper_bound(it, activeSnippetsEnd, snippet, snippetComp);
|
||||
hintIndex = static_cast<int>(std::distance(snippets.begin(), it));
|
||||
if (index > hintIndex)
|
||||
return Hint(hintIndex, it);
|
||||
@@ -176,11 +183,10 @@ void SnippetsCollection::removeSnippet(int index, const QString &groupId)
|
||||
const int group = groupIndex(groupId);
|
||||
Snippet snippet(m_snippets.at(group).at(index));
|
||||
m_snippets[group].removeAt(index);
|
||||
updateActiveSnippetsEnd(group);
|
||||
if (snippet.isBuiltIn()) {
|
||||
snippet.setIsRemoved(true);
|
||||
m_activeSnippetsEnd[group] = m_snippets[group].insert(m_activeSnippetsEnd[group], snippet);
|
||||
} else {
|
||||
updateActiveSnippetsEnd(group);
|
||||
m_snippets[group].append(snippet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,8 +208,7 @@ void SnippetsCollection::setSnippetContent(int index,
|
||||
int SnippetsCollection::totalActiveSnippets(const QString &groupId) const
|
||||
{
|
||||
const int group = groupIndex(groupId);
|
||||
return std::distance<QList<Snippet>::const_iterator>(m_snippets.at(group).begin(),
|
||||
QList<Snippet>::const_iterator(m_activeSnippetsEnd.at(group)));
|
||||
return m_activeSnippetsCount.at(group);
|
||||
}
|
||||
|
||||
int SnippetsCollection::totalSnippets(const QString &groupId) const
|
||||
@@ -225,14 +230,14 @@ void SnippetsCollection::clearSnippets()
|
||||
void SnippetsCollection::clearSnippets(int groupIndex)
|
||||
{
|
||||
m_snippets[groupIndex].clear();
|
||||
m_activeSnippetsEnd[groupIndex] = m_snippets[groupIndex].end();
|
||||
m_activeSnippetsCount[groupIndex] = m_snippets[groupIndex].size();
|
||||
}
|
||||
|
||||
void SnippetsCollection::updateActiveSnippetsEnd(int groupIndex)
|
||||
{
|
||||
m_activeSnippetsEnd[groupIndex] = std::find_if(m_snippets[groupIndex].begin(),
|
||||
m_snippets[groupIndex].end(),
|
||||
[](const Snippet &s) { return s.isRemoved(); });
|
||||
const int index = Utils::indexOf(m_snippets[groupIndex],
|
||||
[](const Snippet &s) { return s.isRemoved(); });
|
||||
m_activeSnippetsCount[groupIndex] = index < 0 ? m_snippets[groupIndex].size() : index;
|
||||
}
|
||||
|
||||
void SnippetsCollection::restoreRemovedSnippets(const QString &groupId)
|
||||
@@ -240,9 +245,11 @@ void SnippetsCollection::restoreRemovedSnippets(const QString &groupId)
|
||||
// The version restored contains the last modifications (if any) by the user.
|
||||
// Reverting the snippet can still bring it to the original version
|
||||
const int group = groupIndex(groupId);
|
||||
QVector<Snippet> toRestore(std::distance(m_activeSnippetsEnd[group], m_snippets[group].end()));
|
||||
std::copy(m_activeSnippetsEnd[group], m_snippets[group].end(), toRestore.begin());
|
||||
m_snippets[group].erase(m_activeSnippetsEnd[group], m_snippets[group].end());
|
||||
if (m_activeSnippetsCount[group] == m_snippets[group].size()) // no removed snippets
|
||||
return;
|
||||
const QVector<Snippet> toRestore = m_snippets[group].mid(m_activeSnippetsCount[group]);
|
||||
m_snippets[group].resize(m_activeSnippetsCount[group]);
|
||||
|
||||
for (Snippet snippet : qAsConst(toRestore)) {
|
||||
snippet.setIsRemoved(false);
|
||||
insertSnippet(snippet);
|
||||
@@ -425,8 +432,8 @@ void SnippetsCollection::identifyGroups()
|
||||
const int groupIndex = m_groupIndexById.size();
|
||||
m_groupIndexById.insert(provider.groupId(), groupIndex);
|
||||
m_snippets.resize(groupIndex + 1);
|
||||
m_activeSnippetsEnd.resize(groupIndex + 1);
|
||||
m_activeSnippetsEnd[groupIndex] = m_snippets[groupIndex].end();
|
||||
m_activeSnippetsCount.resize(groupIndex + 1);
|
||||
m_activeSnippetsCount[groupIndex] = m_snippets[groupIndex].size();
|
||||
}
|
||||
|
||||
reload();
|
||||
|
||||
@@ -61,9 +61,9 @@ public:
|
||||
int index() const;
|
||||
private:
|
||||
explicit Hint(int index);
|
||||
Hint(int index, QList<Snippet>::iterator it);
|
||||
Hint(int index, QVector<Snippet>::iterator it);
|
||||
int m_index;
|
||||
QList<Snippet>::iterator m_it;
|
||||
QVector<Snippet>::iterator m_it;
|
||||
};
|
||||
|
||||
void insertSnippet(const Snippet &snippet);
|
||||
@@ -120,8 +120,8 @@ private:
|
||||
// Snippets for each group are kept in a list. However, not all of them are necessarily
|
||||
// active. Specifically, removed built-in snippets are kept as the last ones (for each
|
||||
// group there is a iterator that marks the logical end).
|
||||
QVector<QList<Snippet> > m_snippets;
|
||||
QVector<QList<Snippet>::iterator> m_activeSnippetsEnd;
|
||||
QVector<QVector<Snippet> > m_snippets;
|
||||
QVector<int> m_activeSnippetsCount;
|
||||
|
||||
QHash<QString, int> m_groupIndexById;
|
||||
};
|
||||
|
||||
@@ -2400,7 +2400,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||
if (camelCaseNavigationEnabled())
|
||||
CamelCaseCursor::left(&cursor, this, QTextCursor::KeepAnchor);
|
||||
else
|
||||
d->moveCursor(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
|
||||
cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor);
|
||||
}
|
||||
cursor.removeSelectedText();
|
||||
setMultiTextCursor(cursor);
|
||||
@@ -2411,7 +2411,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
|
||||
if (camelCaseNavigationEnabled())
|
||||
CamelCaseCursor::right(&cursor, this, QTextCursor::KeepAnchor);
|
||||
else
|
||||
d->moveCursor(QTextCursor::NextWord, QTextCursor::KeepAnchor);
|
||||
cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);
|
||||
}
|
||||
cursor.removeSelectedText();
|
||||
setMultiTextCursor(cursor);
|
||||
@@ -6257,10 +6257,10 @@ MultiTextCursor TextEditorWidget::multiTextCursor() const
|
||||
|
||||
void TextEditorWidget::setMultiTextCursor(const Utils::MultiTextCursor &cursor)
|
||||
{
|
||||
if (d->m_cursors == cursor)
|
||||
return;
|
||||
MultiTextCursor oldCursor = d->m_cursors;
|
||||
const MultiTextCursor oldCursor = d->m_cursors;
|
||||
const_cast<MultiTextCursor &>(d->m_cursors) = cursor;
|
||||
if (oldCursor == d->m_cursors)
|
||||
return;
|
||||
doSetTextCursor(d->m_cursors.mainCursor(), /*keepMultiSelection*/ true);
|
||||
QRect updateRect = d->cursorUpdateRect(oldCursor);
|
||||
if (d->m_highlightCurrentLine)
|
||||
|
||||
Reference in New Issue
Block a user