diff options
Diffstat (limited to 'src/plugins')
105 files changed, 801 insertions, 448 deletions
diff --git a/src/plugins/android/androiddevice.cpp b/src/plugins/android/androiddevice.cpp index fa3d834c038..7fb3e27105c 100644 --- a/src/plugins/android/androiddevice.cpp +++ b/src/plugins/android/androiddevice.cpp @@ -450,6 +450,7 @@ void AndroidDevice::fromMap(const Store &map) // Add Actions for Emulator and hardware if not added already. // This is needed because actions for Emulators and physical devices are not the same. addActionsIfNotFound(); + setFreePorts(PortList::fromString("5555-5585")); } IDevice::Ptr AndroidDevice::create() diff --git a/src/plugins/android/androidplugin.cpp b/src/plugins/android/androidplugin.cpp index abe632e25b8..5541a18f0d3 100644 --- a/src/plugins/android/androidplugin.cpp +++ b/src/plugins/android/androidplugin.cpp @@ -136,15 +136,18 @@ class AndroidPlugin final : public ExtensionSystem::IPlugin void askUserAboutAndroidSetup() { NANOTRACE_SCOPE("Android", "AndroidPlugin::askUserAboutAndroidSetup"); - if (!Core::ICore::infoBar()->canInfoBeAdded(kSetupAndroidSetting)) + Utils::InfoBar *infoBar = Core::ICore::infoBar(); + if (!infoBar->canInfoBeAdded(kSetupAndroidSetting)) return; Utils::InfoBarEntry info(kSetupAndroidSetting, - Tr::tr("Would you like to configure Android options? This will ensure " - "Android kits can be usable and all essential packages are installed. " - "To do it later, select Edit > Preferences > Devices > Android."), + Tr::tr("Automatically create usable Android kits and install all essential " + "packages. " + "To do this later, select Edit > Preferences > Devices > Android."), Utils::InfoBarEntry::GlobalSuppression::Enabled); + info.setTitle(Tr::tr("Configure Android Options?")); + info.setInfoType(Utils::InfoLabel::Information); info.addCustomButton( Tr::tr("Configure Android"), [this] { @@ -154,7 +157,7 @@ class AndroidPlugin final : public ExtensionSystem::IPlugin }, {}, Utils::InfoBarEntry::ButtonAction::SuppressPersistently); - Core::ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } }; diff --git a/src/plugins/android/androidsdkmanager.cpp b/src/plugins/android/androidsdkmanager.cpp index d9add29555b..176665145e0 100644 --- a/src/plugins/android/androidsdkmanager.cpp +++ b/src/plugins/android/androidsdkmanager.cpp @@ -16,6 +16,7 @@ #include <utils/layoutbuilder.h> #include <utils/outputformatter.h> #include <utils/qtcprocess.h> +#include <utils/textcodec.h> #include <QDialogButtonBox> #include <QLabel> @@ -25,7 +26,6 @@ #include <QPointer> #include <QProgressBar> #include <QRegularExpression> -#include <QTextCodec> namespace { Q_LOGGING_CATEGORY(sdkManagerLog, "qtc.android.sdkManager", QtWarningMsg) @@ -190,8 +190,7 @@ static GroupItem licensesRecipe(const Storage<DialogStorage> &dialogStorage) OutputData *outputPtr = outputStorage.activeStorage(); QObject::connect(processPtr, &Process::readyReadStandardOutput, dialog, [processPtr, outputPtr, dialog] { - QTextCodec *codec = QTextCodec::codecForLocale(); - const QString stdOut = codec->toUnicode(processPtr->readAllRawStandardOutput()); + const QString stdOut = processPtr->readAllStandardOutput(); outputPtr->buffer += stdOut; dialog->appendMessage(stdOut, StdOutFormat); const auto progress = parseProgress(stdOut); @@ -241,15 +240,13 @@ static void setupSdkProcess(const QStringList &args, Process *process, args + AndroidConfig::sdkManagerToolArgs()}); QObject::connect(process, &Process::readyReadStandardOutput, dialog, [process, dialog, current, total] { - QTextCodec *codec = QTextCodec::codecForLocale(); - const auto progress = parseProgress(codec->toUnicode(process->readAllRawStandardOutput())); + const auto progress = parseProgress(process->readAllStandardOutput()); if (!progress) return; dialog->setProgress((current * 100.0 + *progress) / total); }); QObject::connect(process, &Process::readyReadStandardError, dialog, [process, dialog] { - QTextCodec *codec = QTextCodec::codecForLocale(); - dialog->appendMessage(codec->toUnicode(process->readAllRawStandardError()), StdErrFormat); + dialog->appendMessage(process->readAllStandardError(), StdErrFormat); }); }; diff --git a/src/plugins/autotest/itestparser.cpp b/src/plugins/autotest/itestparser.cpp index 50dcb6cb0ed..ae08197a27a 100644 --- a/src/plugins/autotest/itestparser.cpp +++ b/src/plugins/autotest/itestparser.cpp @@ -47,7 +47,7 @@ QByteArray CppParser::getFileContent(const FilePath &filePath) const if (const auto source = m_workingCopy.source(filePath)) { fileContent = *source; } else { - const QTextCodec *codec = Core::EditorManager::defaultTextCodec(); + const TextCodec codec = Core::EditorManager::defaultTextCodec(); const Result<> result = TextFileFormat::readFileUtf8(filePath, codec, &fileContent); if (!result) qDebug() << "Failed to read file" << filePath << ":" << result.error(); diff --git a/src/plugins/axivion/axivionperspective.cpp b/src/plugins/axivion/axivionperspective.cpp index 60884f40cc0..207e762ac27 100644 --- a/src/plugins/axivion/axivionperspective.cpp +++ b/src/plugins/axivion/axivionperspective.cpp @@ -190,6 +190,7 @@ public: void updateUi(const QString &kind); void initDashboardList(const QString &preferredProject = {}); void resetDashboard(); + void leaveOrEnterDashboardMode(); void updateNamedFilters(); const std::optional<Dto::TableInfoDto> currentTableInfo() const { return m_currentTableInfo; } @@ -229,6 +230,7 @@ private: QComboBox *m_ownerFilter = nullptr; QComboBox *m_versionStart = nullptr; QComboBox *m_versionEnd = nullptr; + QComboBox *m_localVersions = nullptr; QComboBox *m_namedFilters = nullptr; QToolButton *m_localBuild = nullptr; QToolButton *m_localDashBoard = nullptr; @@ -238,6 +240,7 @@ private: QLabel *m_totalRows = nullptr; BaseTreeView *m_issuesView = nullptr; QStackedWidget *m_stack = nullptr; + QStackedWidget *m_versionsStack = nullptr; IssueHeaderView *m_headerView = nullptr; QPlainTextEdit *m_errorEdit = nullptr; DynamicListModel *m_issuesModel = nullptr; @@ -341,6 +344,16 @@ IssuesWidget::IssuesWidget(QWidget *parent) setAnalysisVersion(m_versionDates.at(index)); }); + m_localVersions = new QComboBox(this); + m_localVersions->setMinimumContentsLength(25); + m_localVersions->addItems({Tr::tr("Reference version"), Tr::tr("Locally changed issues"), + Tr::tr("All local issues")}); + connect(m_localVersions, &QComboBox::currentIndexChanged, this, [this] { + if (m_signalBlocker.isLocked()) + return; + onSearchParameterChanged(); + }); + m_addedFilter = new QPushButton(this); m_addedFilter->setIcon(trendIcon(1, 0)); m_addedFilter->setText("0"); @@ -434,8 +447,15 @@ IssuesWidget::IssuesWidget(QWidget *parent) m_stack->addWidget(m_issuesView); m_stack->addWidget(errorWidget); + Stack { + bindTo(&m_versionsStack), + Row { m_versionStart, m_versionEnd, noMargin }, + Row { m_localVersions, st, noMargin } + }; + m_versionsStack->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); + Column { - Row { m_dashboards, m_dashboardProjects, empty, localLayout, st, m_typesLayout, st, m_versionStart, m_versionEnd, st }, + Row { m_dashboards, m_dashboardProjects, empty, localLayout, empty, m_typesLayout, empty, m_versionsStack, st }, Row { m_addedFilter, m_removedFilter, Space(1), m_ownerFilter, m_pathGlobFilter, m_namedFilters, m_showFilterHelp }, m_stack, Row { st, m_totalRows } @@ -500,6 +520,24 @@ void IssuesWidget::resetDashboard() m_dashboardListUninitialized = true; } +void IssuesWidget::leaveOrEnterDashboardMode() +{ + GuardLocker lock(m_signalBlocker); + + switch (currentDashboardMode()) { + case DashboardMode::Global: + m_versionsStack->setCurrentIndex(int(DashboardMode::Global)); + break; + case DashboardMode::Local: + m_localVersions->setCurrentIndex(1); + m_versionsStack->setCurrentIndex(int(DashboardMode::Local)); + break; + } + + IssueListSearch search = searchFromUi(); + fetchIssues(search); +} + void IssuesWidget::updateNamedFilters() { QList<NamedFilter> globalFilters = knownNamedFiltersFor(m_currentPrefix, true); @@ -789,6 +827,7 @@ void IssuesWidget::updateBasicProjectInfo(const std::optional<Dto::ProjectInfoDt m_ownerFilter->clear(); m_versionStart->clear(); m_versionEnd->clear(); + m_versionEnd->setVisible(true); m_pathGlobFilter->clear(); m_namedFilters->clear(); @@ -890,6 +929,7 @@ void IssuesWidget::setFiltersEnabled(bool enabled) m_removedFilter->setEnabled(enabled); m_ownerFilter->setEnabled(enabled); m_versionStart->setEnabled(enabled); + m_localVersions->setEnabled(enabled); m_versionEnd->setEnabled(enabled); m_pathGlobFilter->setEnabled(enabled); m_namedFilters->setEnabled(enabled); @@ -1016,9 +1056,11 @@ void IssuesWidget::switchDashboard(bool local) { if (local) { QTC_ASSERT(!m_currentProject.isEmpty(), return); - startLocalDashboard(m_currentProject, {}); + auto callback = [] { switchDashboardMode(DashboardMode::Local); }; + m_issuesView->showProgressIndicator(); + startLocalDashboard(m_currentProject, callback); } else { - // TODO switch back + switchDashboardMode(DashboardMode::Global); } } @@ -1124,6 +1166,8 @@ public: void handleAnchorClicked(const QUrl &url); void updateNamedFilters(); + void leaveOrEnterDashboardMode(); + private: IssuesWidget *m_issuesWidget = nullptr; LazyImageBrowser *m_issueDetails = nullptr; @@ -1295,6 +1339,11 @@ void AxivionPerspective::updateNamedFilters() m_issuesWidget->updateNamedFilters(); } +void AxivionPerspective::leaveOrEnterDashboardMode() +{ + m_issuesWidget->leaveOrEnterDashboardMode(); +} + static AxivionPerspective *axivionPerspective() { static GuardedObject<AxivionPerspective> theAxivionPerspective; @@ -1354,6 +1403,12 @@ void updateNamedFilters() axivionPerspective()->updateNamedFilters(); } +void leaveOrEnterDashboardMode() +{ + QTC_ASSERT(axivionPerspective(), return); + axivionPerspective()->leaveOrEnterDashboardMode(); +} + void setupAxivionPerspective() { // Trigger initialization. diff --git a/src/plugins/axivion/axivionperspective.h b/src/plugins/axivion/axivionperspective.h index e5266ab2c39..900579309f7 100644 --- a/src/plugins/axivion/axivionperspective.h +++ b/src/plugins/axivion/axivionperspective.h @@ -15,6 +15,8 @@ void resetDashboard(); void updateIssueDetails(const QString &html); void updateNamedFilters(); +void leaveOrEnterDashboardMode(); + void setupAxivionPerspective(); } // Axivion::Internal diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp index e212a661c5d..f1438dee520 100644 --- a/src/plugins/axivion/axivionplugin.cpp +++ b/src/plugins/axivion/axivionplugin.cpp @@ -265,6 +265,8 @@ public: void fetchIssueInfo(const QString &id); void fetchNamedFilters(); + void switchDashboardMode(DashboardMode mode); + void onSessionLoaded(const QString &sessionName); void onAboutToSaveSession(); @@ -292,6 +294,7 @@ public: QMetaObject::Connection m_fileFinderConnection; QHash<FilePath, QSet<TextMark *>> m_allMarks; bool m_inlineIssuesEnabled = true; + DashboardMode m_dashboardMode = DashboardMode::Global; }; static AxivionPluginPrivate *dd = nullptr; @@ -1172,6 +1175,14 @@ void AxivionPluginPrivate::enableInlineIssues(bool enable) clearAllMarks(); } +void AxivionPluginPrivate::switchDashboardMode(DashboardMode mode) +{ + if (m_dashboardMode == mode) + return; + m_dashboardMode = mode; + leaveOrEnterDashboardMode(); +} + static constexpr char SV_PROJECTNAME[] = "Axivion.ProjectName"; static constexpr char SV_DASHBOARDID[] = "Axivion.DashboardId"; @@ -1294,6 +1305,18 @@ Utils::FilePath findFileForIssuePath(const Utils::FilePath &issuePath) return {}; } +void switchDashboardMode(DashboardMode mode) +{ + QTC_ASSERT(dd, return); + dd->switchDashboardMode(mode); +} + +DashboardMode currentDashboardMode() +{ + QTC_ASSERT(dd, return DashboardMode::Global); + return dd->m_dashboardMode; +} + } // Axivion::Internal #include "axivionplugin.moc" diff --git a/src/plugins/axivion/axivionplugin.h b/src/plugins/axivion/axivionplugin.h index cf675d24d6c..fa222360590 100644 --- a/src/plugins/axivion/axivionplugin.h +++ b/src/plugins/axivion/axivionplugin.h @@ -129,6 +129,10 @@ const std::optional<DashboardInfo> currentDashboardInfo(); void setAnalysisVersion(const QString &version); void enableInlineIssues(bool enable); +enum class DashboardMode { Global, Local }; +void switchDashboardMode(DashboardMode mode); +DashboardMode currentDashboardMode(); + Utils::FilePath findFileForIssuePath(const Utils::FilePath &issuePath); } // Axivion::Internal diff --git a/src/plugins/beautifier/clangformat/clangformat.cpp b/src/plugins/beautifier/clangformat/clangformat.cpp index 7a250d6b94a..cd3837c431a 100644 --- a/src/plugins/beautifier/clangformat/clangformat.cpp +++ b/src/plugins/beautifier/clangformat/clangformat.cpp @@ -37,7 +37,6 @@ #include <QMenu> #include <QRadioButton> #include <QTextBlock> -#include <QTextCodec> #include <QXmlStreamWriter> using namespace TextEditor; @@ -395,16 +394,16 @@ void ClangFormat::formatAtPosition(const int pos, const int length) if (!widget) return; - const QTextCodec *codec = widget->textDocument()->codec(); - if (!codec) { + const TextCodec codec = widget->textDocument()->codec(); + if (!codec.isValid()) { formatCurrentFile(textCommand(pos, length)); return; } const QString &text = widget->textAt(0, pos + length); const QStringView buffer(text); - const int encodedOffset = codec->fromUnicode(buffer.left(pos)).size(); - const int encodedLength = codec->fromUnicode(buffer.mid(pos, length)).size(); + const int encodedOffset = codec.fromUnicode(buffer.left(pos)).size(); + const int encodedLength = codec.fromUnicode(buffer.mid(pos, length)).size(); formatCurrentFile(textCommand(encodedOffset, encodedLength)); } diff --git a/src/plugins/bineditor/bineditorplugin.cpp b/src/plugins/bineditor/bineditorplugin.cpp index d5ea0068e63..ac11a50b053 100644 --- a/src/plugins/bineditor/bineditorplugin.cpp +++ b/src/plugins/bineditor/bineditorplugin.cpp @@ -55,7 +55,6 @@ #include <QSet> #include <QStack> #include <QString> -#include <QTextCodec> #include <QTextDocument> #include <QTextFormat> #include <QToolBar> @@ -246,7 +245,7 @@ public: void copy(bool raw = false); void setMarkup(const QList<Markup> &markup); void setNewWindowRequestAllowed(bool c) { m_canRequestNewWindow = c; } - void setCodec(const QByteArray &codec); + void setCodec(const Utils::TextCodec &codec); QByteArray toByteArray(const QString &s) const; void clearMarkup() { m_markup.clear(); } @@ -339,7 +338,7 @@ public: QList<Markup> m_markup; QLineEdit *m_addressEdit = nullptr; - QTextCodec *m_codec = nullptr; + TextCodec m_codec; }; const QChar MidpointChar(u'\u00B7'); @@ -391,7 +390,7 @@ BinEditorWidget::BinEditorWidget(const std::shared_ptr<BinEditorDocument> &doc) const QByteArray setting = ICore::settings()->value(C_ENCODING_SETTING).toByteArray(); if (!setting.isEmpty()) - setCodec(setting); + setCodec(TextCodec::codecForName(setting)); m_addressEdit = new QLineEdit; auto addressValidator = new QRegularExpressionValidator(QRegularExpression("[0-9a-fA-F]{1,16}"), m_addressEdit); @@ -768,9 +767,9 @@ QChar BinEditorWidget::displayChar(char ch) const const QChar qc = QLatin1Char(ch); if (qc.isPrint() && qc.unicode() < 128) return qc; - if (!m_codec || qc.unicode() < 32) + if (!m_codec.isValid() || qc.unicode() < 32) return MidpointChar; - const QString uc = m_codec->toUnicode(&ch, 1); + const QString uc = m_codec.toUnicode(QByteArrayView(&ch, 1)); if (uc.isEmpty() || !uc.at(0).isLetterOrNumber()) return MidpointChar; return uc.at(0); @@ -1691,8 +1690,8 @@ void BinEditorWidget::copy(bool raw) QByteArray data = m_doc->dataMid(selStart, selectionLength); if (raw) { data.replace(0, ' '); - QTextCodec *codec = m_codec ? m_codec : QTextCodec::codecForName("latin1"); - setClipboardAndSelection(codec->toUnicode(data)); + const TextCodec codec = m_codec.isValid() ? m_codec : TextCodec::latin1(); + setClipboardAndSelection(codec.toUnicode(data)); return; } QString hexString; @@ -1886,20 +1885,19 @@ void BinEditorWidget::jumpToAddress(quint64 address) m_doc->requestNewRange(address); } -void BinEditorWidget::setCodec(const QByteArray &codecName) +void BinEditorWidget::setCodec(const TextCodec &codec) { - QTextCodec *codec = QTextCodec::codecForName(codecName); if (codec == m_codec) return; m_codec = codec; - ICore::settings()->setValue(C_ENCODING_SETTING, codecName); + ICore::settings()->setValue(C_ENCODING_SETTING, codec.name()); viewport()->update(); } QByteArray BinEditorWidget::toByteArray(const QString &s) const { - if (m_codec) - return m_codec->fromUnicode(s); + if (m_codec.isValid()) + return m_codec.fromUnicode(s); return s.toLatin1(); } @@ -2201,7 +2199,7 @@ public: const QVariant setting = ICore::settings()->value(C_ENCODING_SETTING); if (!setting.isNull()) - codecChooser->setAssignedCodec(QTextCodec::codecForName(setting.toByteArray())); + codecChooser->setAssignedCodec(TextCodec::codecForName(setting.toByteArray())); using namespace Layouting; auto w = Row { diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index a198d37b33a..3ac9015a092 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -171,6 +171,8 @@ static void checkSystemForClangdSuitability() "would be higher than what your system can handle."); const Id clangdWarningSetting("WarnAboutClangd"); InfoBarEntry info(clangdWarningSetting, warnStr); + info.setTitle(Tr::tr("Clangd Disabled")); + info.setInfoType(InfoLabel::Warning); info.setDetailsWidgetCreator([] { const auto label = new QLabel(Tr::tr( "With clangd enabled, Qt Creator fully supports modern C++ " diff --git a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp index ba0eaac77bf..1af6da0ba76 100644 --- a/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp +++ b/src/plugins/clangtools/clangfixitsrefactoringchanges.cpp @@ -96,7 +96,7 @@ bool FixitsRefactoringFile::apply() } // Write file - if (!m_textFileFormat.codec()) + if (!m_textFileFormat.codec().isValid()) return false; // Error reading file for (auto it = m_documents.begin(); it != m_documents.end(); ++it) { @@ -143,7 +143,7 @@ QTextDocument *FixitsRefactoringFile::document(const FilePath &filePath) const if (result.code != TextFileFormat::ReadSuccess) { qCDebug(fixitsLog) << "ERROR: Could not read " << filePath.toUserOutput() << ":" << result.error; - m_textFileFormat.setCodec(nullptr); + m_textFileFormat.setCodec({}); } } // always make a QTextDocument to avoid excessive null checks diff --git a/src/plugins/clearcase/clearcaseplugin.cpp b/src/plugins/clearcase/clearcaseplugin.cpp index 1bb1573fd48..f412b15ca2c 100644 --- a/src/plugins/clearcase/clearcaseplugin.cpp +++ b/src/plugins/clearcase/clearcaseplugin.cpp @@ -106,11 +106,6 @@ const char LOG_EDITOR_ID[] = "ClearCase File Log Editor"; const char ANNOTATION_EDITOR_ID[] = "ClearCase Annotation Editor"; const char DIFF_EDITOR_ID[] = "ClearCase Diff Editor"; -static QByteArray debugCodec(const QByteArray &c) -{ - return !c.isEmpty() ? c : QByteArray("Null codec"); -} - class ClearCasePluginPrivate final : public VcsBase::VersionControlBase { Q_OBJECT @@ -240,12 +235,12 @@ private: FilePath ccViewRoot(const FilePath &directory) const; FilePath findTopLevel(const FilePath &directory) const; IEditor *showOutputInEditor(const QString& title, const QString &output, Id id, - const FilePath &source, const QByteArray &codec) const; + const FilePath &source, const TextCodec &codec) const; CommandResult runCleartoolProc(const FilePath &workingDir, const QStringList &arguments) const; CommandResult runCleartool(const FilePath &workingDir, const QStringList &arguments, VcsBase::RunFlags flags = VcsBase::RunFlags::None, - const QByteArray &codec = {}, int timeoutMultiplier = 1) const; + const TextCodec &codec = {}, int timeoutMultiplier = 1) const; static void sync(QPromise<void> &promise, FilePaths files); void history(const FilePath &workingDir, @@ -262,7 +257,7 @@ private: QString diffExternal(QString file1, QString file2 = QString(), bool keep = false); QString getFile(const QString &nativeFile, const QString &prefix); QString runExtDiff(const FilePath &workingDir, const QStringList &arguments, int timeOutS, - const QByteArray &outputCodec = {}); + const TextCodec &outputCodec = {}); static FilePath getDriveLetterOfPath(FilePath directory); FileStatus::Status getFileStatus(const FilePath &fileName) const; @@ -1187,7 +1182,7 @@ void ClearCasePluginPrivate::ccDiffWithPred(const FilePath &workingDir, const QS if (Constants::debug) qDebug() << Q_FUNC_INFO << files; const FilePath source = VcsBaseEditor::getSource(workingDir, files); - QByteArray codec = source.isEmpty() ? QByteArray() : VcsBaseEditor::getCodec(source); + const TextCodec codec = source.isEmpty() ? TextCodec() : VcsBaseEditor::getCodec(source); if ((m_settings.diffType == GraphicalDiff) && (files.count() == 1)) { const QString file = files.first(); @@ -1310,7 +1305,7 @@ void ClearCasePluginPrivate::diffActivity() m_diffPrefix.clear(); const QString title = QString::fromLatin1("%1.patch").arg(activity); IEditor *editor = showOutputInEditor(title, result, DIFF_EDITOR_ID, - FilePath::fromString(activity), nullptr); + FilePath::fromString(activity), {}); setWorkingDirectory(editor, topLevel); } @@ -1444,7 +1439,7 @@ void ClearCasePluginPrivate::history(const FilePath &workingDir, const QStringList &files, bool enableAnnotationContextMenu) { - const QByteArray codec = VcsBaseEditor::getCodec(workingDir, files); + const TextCodec codec = VcsBaseEditor::getCodec(workingDir, files); // no need for temp file QStringList args(QLatin1String("lshistory")); if (m_settings.historyCount > 0) @@ -1514,7 +1509,7 @@ void ClearCasePluginPrivate::ccUpdate(const FilePath &workingDir, const QStringL args << QLatin1String("-noverwrite"); if (!relativePaths.isEmpty()) args.append(relativePaths); - const CommandResult result = runCleartool(workingDir, args, RunFlags::ShowStdOut, nullptr, 10); + const CommandResult result = runCleartool(workingDir, args, RunFlags::ShowStdOut, {}, 10); if (result.result() == ProcessResult::FinishedWithSuccess) emit repositoryChanged(workingDir); } @@ -1534,7 +1529,7 @@ void ClearCasePluginPrivate::vcsAnnotateHelper(const FilePath &workingDir, const qDebug() << Q_FUNC_INFO << file; // FIXME: Should this be something like workingDir.resolvePath(file) ? - const QByteArray codec = VcsBaseEditor::getCodec(FilePath::fromString(file)); + const TextCodec codec = VcsBaseEditor::getCodec(FilePath::fromString(file)); // Determine id QString id = file; @@ -1593,7 +1588,7 @@ void ClearCasePluginPrivate::vcsDescribe(const FilePath &source, const QString & const FilePath relPath = source.relativePathFromDir(topLevel); const QString id = QString::fromLatin1("%1@@%2").arg(relPath.toUserOutput(), changeNr); - const QByteArray codec = VcsBaseEditor::getCodec(source); + const TextCodec codec = VcsBaseEditor::getCodec(source); const CommandResult result = runCleartool(topLevel, {"describe", id}, RunFlags::None, codec); description = result.cleanedStdOut(); if (m_settings.extDiffAvailable) @@ -1631,7 +1626,7 @@ CommandResult ClearCasePluginPrivate::runCleartoolProc(const FilePath &workingDi CommandResult ClearCasePluginPrivate::runCleartool(const FilePath &workingDir, const QStringList &arguments, RunFlags flags, - const QByteArray &codec, + const TextCodec &codec, int timeoutMultiplier) const { if (m_settings.ccBinaryPath.isEmpty()) @@ -1644,11 +1639,11 @@ CommandResult ClearCasePluginPrivate::runCleartool(const FilePath &workingDir, IEditor *ClearCasePluginPrivate::showOutputInEditor(const QString& title, const QString &output, Id id, const FilePath &source, - const QByteArray &codec) const + const TextCodec &codec) const { if (Constants::debug) qDebug() << "ClearCasePlugin::showOutputInEditor" << title << id.name() - << "Size= " << output.size() << debugCodec(codec); + << "Size= " << output.size() << codec.displayName(); QString s = title; IEditor *editor = EditorManager::openEditorWithContents(id, &s, output.toUtf8()); auto e = qobject_cast<ClearCaseEditorWidget*>(editor->widget()); @@ -1661,7 +1656,7 @@ IEditor *ClearCasePluginPrivate::showOutputInEditor(const QString& title, const e->textDocument()->setFallbackSaveAsFileName(s); if (!source.isEmpty()) e->setSource(source); - if (!codec.isEmpty()) + if (codec.isValid()) e->setCodec(codec); return editor; } @@ -1837,8 +1832,7 @@ bool ClearCasePluginPrivate::vcsCheckIn(const FilePath &messageFile, const QStri FCBPointer fcb(new FileChangeBlocker(m_checkInView.pathAppended(fileName).canonicalPath())); blockers.append(fcb); } - const CommandResult result = runCleartool(m_checkInView, args, RunFlags::ShowStdOut, nullptr, - 10); + const CommandResult result = runCleartool(m_checkInView, args, RunFlags::ShowStdOut, {}, 10); static const QRegularExpression checkedIn("Checked in \\\"([^\"]*)\\\""); QRegularExpressionMatch match = checkedIn.match(result.cleanedStdOut()); bool anySucceeded = false; @@ -2209,7 +2203,7 @@ QString ClearCasePluginPrivate::getFile(const QString &nativeFile, const QString // runs external (GNU) diff, and returns the stdout result QString ClearCasePluginPrivate::diffExternal(QString file1, QString file2, bool keep) { - const QByteArray codec = VcsBaseEditor::getCodec(FilePath::fromString(file1)); + const TextCodec codec = VcsBaseEditor::getCodec(FilePath::fromString(file1)); // if file2 is empty, we should compare to predecessor if (file2.isEmpty()) { @@ -2273,11 +2267,11 @@ void ClearCasePluginPrivate::diffGraphical(const QString &file1, const QString & } QString ClearCasePluginPrivate::runExtDiff(const FilePath &workingDir, const QStringList &arguments, - int timeOutS, const QByteArray &outputCodec) + int timeOutS, const TextCodec &outputCodec) { Process process; process.setWorkingDirectory(workingDir); - process.setCodec(outputCodec.isEmpty() ? QByteArray("UTF-8") : outputCodec); + process.setCodec(outputCodec.isValid() ? outputCodec : TextCodec::utf8()); process.setCommand({"diff", {m_settings.diffArgs.split(' ', Qt::SkipEmptyParts), arguments}}); process.runBlocking(seconds(timeOutS), EventLoopMode::On); if (process.result() != ProcessResult::FinishedWithSuccess) diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index f0fc3bb86e1..5b1fa260516 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -501,7 +501,8 @@ void CorePlugin::checkSettings() void CorePlugin::warnAboutCrashReporing() { - if (!ICore::infoBar()->canInfoBeAdded(kWarnCrashReportingSetting)) + InfoBar *infoBar = ICore::infoBar(); + if (!infoBar->canInfoBeAdded(kWarnCrashReportingSetting)) return; QString warnStr = ICore::settings()->value("CrashReportingEnabled", false).toBool() @@ -522,6 +523,7 @@ void CorePlugin::warnAboutCrashReporing() Utils::InfoBarEntry info(kWarnCrashReportingSetting, warnStr, Utils::InfoBarEntry::GlobalSuppression::Enabled); info.setTitle(Tr::tr("Crash Reporting")); + info.setInfoType(InfoLabel::Information); info.addCustomButton( ICore::msgShowOptionsDialog(), [] { ICore::showOptionsDialog(Core::Constants::SETTINGS_ID_SYSTEM); }, @@ -537,7 +539,7 @@ void CorePlugin::warnAboutCrashReporing() label->setContentsMargins(0, 0, 0, 8); return label; }); - ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } // static diff --git a/src/plugins/coreplugin/dialogs/codecselector.cpp b/src/plugins/coreplugin/dialogs/codecselector.cpp index d363b2c313b..50bfd1fb7eb 100644 --- a/src/plugins/coreplugin/dialogs/codecselector.cpp +++ b/src/plugins/coreplugin/dialogs/codecselector.cpp @@ -17,10 +17,11 @@ #include <QLabel> #include <QListWidget> #include <QPushButton> -#include <QTextCodec> #include <QScrollBar> #include <QVBoxLayout> +using namespace Utils; + namespace Core { namespace Internal { @@ -29,7 +30,7 @@ class CodecSelector : public QDialog public: explicit CodecSelector(BaseTextDocument *doc); - QByteArray selectedCodec() const; + TextCodec selectedCodec() const; private: void updateButtons(); @@ -80,7 +81,7 @@ CodecSelector::CodecSelector(BaseTextDocument *doc) QStringList encodings; - const QList<int> mibs = Utils::sorted(QTextCodec::availableMibs()); + const QList<int> mibs = Utils::sorted(TextCodec::availableMibs()); QList<int> sortedMibs; for (const int mib : mibs) if (mib >= 0) @@ -91,13 +92,13 @@ CodecSelector::CodecSelector(BaseTextDocument *doc) int currentIndex = -1; for (const int mib : std::as_const(sortedMibs)) { - QTextCodec *c = QTextCodec::codecForMib(mib); - if (!doc->supportsCodec(c ? c->name() : QByteArray())) + const TextCodec codec = TextCodec::codecForMib(mib); + if (!doc->supportsCodec(codec.isValid() ? codec.name() : QByteArray())) continue; if (!buf.isEmpty()) { // slow, should use a feature from QTextCodec or QTextDecoder (but those are broken currently) - QByteArray verifyBuf = c->fromUnicode(c->toUnicode(buf)); + QByteArray verifyBuf = codec.fromUnicode(codec.toUnicode(buf)); // the minSize trick lets us ignore unicode headers int minSize = qMin(verifyBuf.size(), buf.size()); if (minSize < buf.size() - 4 @@ -105,13 +106,9 @@ CodecSelector::CodecSelector(BaseTextDocument *doc) buf.constData() + buf.size() - minSize, minSize)) continue; } - QString names = QString::fromLatin1(c->name()); - const QList<QByteArray> aliases = c->aliases(); - for (const QByteArray &alias : aliases) - names += QLatin1String(" / ") + QString::fromLatin1(alias); - if (doc->codec() == c) + if (doc->codec() == codec) currentIndex = encodings.count(); - encodings << names; + encodings << codec.fullDisplayName(); } m_listWidget->addItems(encodings); if (currentIndex >= 0) @@ -136,12 +133,12 @@ CodecSelector::CodecSelector(BaseTextDocument *doc) void CodecSelector::updateButtons() { - bool hasCodec = (selectedCodec() != nullptr); + bool hasCodec = selectedCodec().isValid(); m_reloadButton->setEnabled(!m_isModified && hasCodec); m_saveButton->setEnabled(!m_hasDecodingError && hasCodec); } -QByteArray CodecSelector::selectedCodec() const +TextCodec CodecSelector::selectedCodec() const { if (QListWidgetItem *item = m_listWidget->currentItem()) { if (!item->isSelected()) @@ -149,7 +146,7 @@ QByteArray CodecSelector::selectedCodec() const QString codecName = item->text(); if (codecName.contains(QLatin1String(" / "))) codecName = codecName.left(codecName.indexOf(QLatin1String(" / "))); - return codecName.toLatin1(); + return TextCodec::codecForName(codecName.toLatin1()); } return {}; } diff --git a/src/plugins/coreplugin/dialogs/codecselector.h b/src/plugins/coreplugin/dialogs/codecselector.h index fd33b7dfa3f..a8837710141 100644 --- a/src/plugins/coreplugin/dialogs/codecselector.h +++ b/src/plugins/coreplugin/dialogs/codecselector.h @@ -5,7 +5,7 @@ #include "../core_global.h" -#include <QByteArray> +#include <utils/textcodec.h> namespace Core { @@ -13,7 +13,7 @@ struct CORE_EXPORT CodecSelectorResult { enum Action { Cancel, Reload, Save }; Action action; - QByteArray codec; + Utils::TextCodec codec; }; CORE_EXPORT CodecSelectorResult askForCodec(class BaseTextDocument *doc); diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index fe966d7b555..6a1eba91794 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -3794,28 +3794,24 @@ void EditorManager::hideEditorStatusBar(const QString &id) /*! Returns the default text codec as the user specified in the settings. */ -QTextCodec *EditorManager::defaultTextCodec() +TextCodec EditorManager::defaultTextCodec() { QtcSettings *settings = ICore::settings(); const QByteArray codecName = settings->value(Constants::SETTINGS_DEFAULTTEXTENCODING).toByteArray(); - if (QTextCodec *candidate = QTextCodec::codecForName(codecName)) + const TextCodec candidate = TextCodec::codecForName(codecName); + if (candidate.isValid()) return candidate; // Qt5 doesn't return a valid codec when looking up the "System" codec, but will return // such a codec when asking for the codec for locale and no matching codec is available. // So check whether such a codec was saved to the settings. - QTextCodec *localeCodec = QTextCodec::codecForLocale(); - if (codecName == localeCodec->name()) + const TextCodec localeCodec = TextCodec::codecForLocale(); + if (codecName == localeCodec.name()) return localeCodec; - if (QTextCodec *defaultUTF8 = QTextCodec::codecForName("UTF-8")) + const TextCodec defaultUTF8 = TextCodec::utf8(); + if (defaultUTF8.isValid()) return defaultUTF8; - return QTextCodec::codecForLocale(); -} - -QByteArray EditorManager::defaultTextCodecName() -{ - QTextCodec *codec = defaultTextCodec(); - return codec ? codec->name() : QByteArray(); + return TextCodec::codecForLocale(); } /*! diff --git a/src/plugins/coreplugin/editormanager/editormanager.h b/src/plugins/coreplugin/editormanager/editormanager.h index c98500f879c..207988221d1 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.h +++ b/src/plugins/coreplugin/editormanager/editormanager.h @@ -20,6 +20,7 @@ QT_BEGIN_NAMESPACE class QMenu; +class QTextCodec; QT_END_NAMESPACE namespace Utils { class SearchResultItem; } @@ -129,8 +130,7 @@ public: static bool autoSaveAfterRefactoring(); - static QTextCodec *defaultTextCodec(); - static QByteArray defaultTextCodecName(); + static Utils::TextCodec defaultTextCodec(); static Utils::TextFileFormat::LineTerminationMode defaultLineEnding(); diff --git a/src/plugins/coreplugin/fileutils.cpp b/src/plugins/coreplugin/fileutils.cpp index 0da226f4869..a55841bf8c5 100644 --- a/src/plugins/coreplugin/fileutils.cpp +++ b/src/plugins/coreplugin/fileutils.cpp @@ -20,6 +20,7 @@ #include <utils/qtcprocess.h> #include <utils/terminalcommand.h> #include <utils/terminalhooks.h> +#include <utils/textcodec.h> #include <utils/textfileformat.h> #include <utils/unixutils.h> @@ -30,7 +31,6 @@ #include <QPushButton> #include <QRegularExpression> #include <QTextStream> -#include <QTextCodec> #ifdef Q_OS_WIN #ifdef QTCREATOR_PCH_H @@ -190,12 +190,15 @@ static bool updateHeaderFileGuardAfterRename(const QString &headerPath, const QByteArray data = headerFile.readAll(); headerFile.close(); - auto headerFileTextFormat = TextFileFormat::detect(data); - if (!headerFileTextFormat.codec()) - headerFileTextFormat.setCodecName(EditorManager::defaultTextCodecName()); + TextFileFormat headerFileTextFormat; + headerFileTextFormat.detectFromData(data); + if (!headerFileTextFormat.codec().isValid()) + headerFileTextFormat.setCodec(EditorManager::defaultTextCodec()); + QString stringContent; if (!headerFileTextFormat.decode(data, &stringContent)) return false; + QTextStream inStream(&stringContent); int lineCounter = 0; QString line; @@ -276,7 +279,7 @@ static bool updateHeaderFileGuardAfterRename(const QString &headerPath, QFile tmpHeader(headerPath + ".tmp"); if (tmpHeader.open(QFile::WriteOnly)) { - const auto lineEnd = + const QString lineEnd = headerFileTextFormat.lineTerminationMode == TextFileFormat::LFLineTerminator ? QStringLiteral("\n") : QStringLiteral("\r\n"); // write into temporary string, @@ -298,7 +301,7 @@ static bool updateHeaderFileGuardAfterRename(const QString &headerPath, } lineCounter++; } - tmpHeader.write(headerFileTextFormat.codec()->fromUnicode(outString)); + tmpHeader.write(headerFileTextFormat.codec().fromUnicode(outString)); tmpHeader.close(); } else { // if opening the temp file failed report error diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index 7c8dc3bcc1f..cfd083bd31f 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -370,7 +370,7 @@ QByteArray GeneralSettingsWidget::codecForLocale() QtcSettings *settings = ICore::settings(); QByteArray codec = settings->value(settingsKeyCodecForLocale).toByteArray(); if (codec.isEmpty()) - codec = QTextCodec::codecForLocale()->name(); + codec = codecForLocale(); return codec; } diff --git a/src/plugins/coreplugin/generatedfile.cpp b/src/plugins/coreplugin/generatedfile.cpp index 22aae6bbad9..87fdf59ec83 100644 --- a/src/plugins/coreplugin/generatedfile.cpp +++ b/src/plugins/coreplugin/generatedfile.cpp @@ -160,7 +160,7 @@ Result<> GeneratedFilePrivate::writeContents() const } TextFileFormat format; - format.setCodecName(EditorManager::defaultTextCodecName()); + format.setCodec(EditorManager::defaultTextCodec()); format.lineTerminationMode = EditorManager::defaultLineEnding(); return format.writeFile(path, QString::fromUtf8(contents)); } diff --git a/src/plugins/coreplugin/outputwindow.cpp b/src/plugins/coreplugin/outputwindow.cpp index 8ac6e0e0b43..7ce251e93ac 100644 --- a/src/plugins/coreplugin/outputwindow.cpp +++ b/src/plugins/coreplugin/outputwindow.cpp @@ -318,8 +318,8 @@ void OutputWindow::contextMenuEvent(QContextMenuEvent *event) const FilePath file = FileUtils::getSaveFilePath( {}, FileUtils::homePath() / d->outputFileNameHint); if (!file.isEmpty()) { - Utils::TextFileFormat format; - format.setCodecName(EditorManager::defaultTextCodecName()); + TextFileFormat format; + format.setCodec(EditorManager::defaultTextCodec()); format.lineTerminationMode = EditorManager::defaultLineEnding(); if (const Result<> res = format.writeFile(file, toPlainText()); !res) MessageManager::writeDisrupting(res.error()); diff --git a/src/plugins/coreplugin/textdocument.cpp b/src/plugins/coreplugin/textdocument.cpp index c7da3b297f7..30aa753546f 100644 --- a/src/plugins/coreplugin/textdocument.cpp +++ b/src/plugins/coreplugin/textdocument.cpp @@ -40,8 +40,8 @@ public: } // namespace Internal -BaseTextDocument::BaseTextDocument(QObject *parent) : - IDocument(parent), d(new Internal::TextDocumentPrivate) +BaseTextDocument::BaseTextDocument(QObject *parent) + : IDocument(parent), d(new Internal::TextDocumentPrivate) { setCodec(Core::EditorManager::defaultTextCodec()); setLineTerminationMode(Core::EditorManager::defaultLineEnding()); @@ -106,18 +106,6 @@ void BaseTextDocument::setLineTerminationMode(TextFileFormat::LineTerminationMod d->m_format.lineTerminationMode = mode; } -bool BaseTextDocument::isUtf8Codec(const QByteArray &name) -{ - static const auto utf8Codecs = []() -> QList<QByteArray> { - QTextCodec *codec = QTextCodec::codecForName("UTF-8"); - if (QTC_GUARD(codec)) - return QList<QByteArray>{codec->name()} + codec->aliases(); - return {"UTF-8"}; - }(); - - return utf8Codecs.contains(name); -} - /*! Autodetects file format and reads the text file specified by \a filePath into \a plainText. @@ -134,32 +122,19 @@ BaseTextDocument::ReadResult BaseTextDocument::read(const FilePath &filePath) return d->m_readResult; } -const QTextCodec *BaseTextDocument::codec() const +TextCodec BaseTextDocument::codec() const { return d->m_format.codec(); } -QByteArray BaseTextDocument::codecName() const -{ - return d->m_format.codecName(); -} - -void BaseTextDocument::setCodec(const QTextCodec *codec) +void BaseTextDocument::setCodec(const TextCodec &codec) { if (debug) - qDebug() << Q_FUNC_INFO << this << (codec ? codec->name() : QByteArray()); - if (supportsCodec(codec ? codec->name() : QByteArray())) + qDebug() << Q_FUNC_INFO << this << codec.displayName(); + if (supportsCodec(codec.name())) d->m_format.setCodec(codec); } -void BaseTextDocument::setCodec(const QByteArray &name) -{ - if (debug) - qDebug() << Q_FUNC_INFO << this << name; - if (supportsCodec(name)) - d->m_format.setCodecName(name); -} - bool BaseTextDocument::supportsCodec(const QByteArray &) const { return true; diff --git a/src/plugins/coreplugin/textdocument.h b/src/plugins/coreplugin/textdocument.h index cc2eb4a6ab3..c55fdcd33cc 100644 --- a/src/plugins/coreplugin/textdocument.h +++ b/src/plugins/coreplugin/textdocument.h @@ -22,10 +22,8 @@ public: ~BaseTextDocument() override; Utils::TextFileFormat format() const; - const QTextCodec *codec() const; - QByteArray codecName() const; - void setCodec(const QTextCodec *); - void setCodec(const QByteArray &name); + Utils::TextCodec codec() const; + void setCodec(const Utils::TextCodec &codec); virtual bool supportsCodec(const QByteArray &) const; void switchUtf8Bom(); bool supportsUtf8Bom() const; @@ -42,8 +40,6 @@ public: void setSupportsUtf8Bom(bool value); void setLineTerminationMode(Utils::TextFileFormat::LineTerminationMode mode); - static bool isUtf8Codec(const QByteArray &name); - private: Internal::TextDocumentPrivate *d; }; diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 20ccb8c701c..ee8da159933 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -790,6 +790,8 @@ void CppEditorWidget::showRenameWarningIfFileIsGenerated(const Utils::FilePath & } static const Id infoId("cppeditor.renameWarning"); InfoBarEntry info(infoId, warning); + info.setTitle(Tr::tr("Renamed Symbol Will Be Overwritten")); + info.setInfoType(InfoLabel::Warning); if (ec) { info.addCustomButton( CppEditor::Tr::tr("Open \"%1\"").arg(ec->source().fileName()), diff --git a/src/plugins/cppeditor/cppsourceprocessor.h b/src/plugins/cppeditor/cppsourceprocessor.h index cc5ab0f950d..4905bba6656 100644 --- a/src/plugins/cppeditor/cppsourceprocessor.h +++ b/src/plugins/cppeditor/cppsourceprocessor.h @@ -9,6 +9,8 @@ #include <cplusplus/PreprocessorEnvironment.h> #include <cplusplus/pp-engine.h> +#include <utils/textcodec.h> + #include <QHash> #include <QPointer> #include <QSet> @@ -100,7 +102,7 @@ private: QSet<Utils::FilePath> m_processed; QHash<Utils::FilePath, Utils::FilePath> m_fileNameCache; int m_fileSizeLimitInMb = -1; - QTextCodec *m_defaultCodec; + Utils::TextCodec m_defaultCodec; }; } // CppEditor::Internal diff --git a/src/plugins/cppeditor/quickfixes/convertstringliteral.cpp b/src/plugins/cppeditor/quickfixes/convertstringliteral.cpp index 32c81bd917e..015c9eabdf7 100644 --- a/src/plugins/cppeditor/quickfixes/convertstringliteral.cpp +++ b/src/plugins/cppeditor/quickfixes/convertstringliteral.cpp @@ -89,7 +89,7 @@ static QString msgQtStringLiteralDescription(const QString &replacement) static QString msgQtStringLiteralOperatorDescription(const QString &replacement) { - return Tr::tr("Convert to %1 operator").arg(replacement); + return Tr::tr("Append %1 operator").arg(replacement); } static QString stringLiteralReplacement(unsigned actions) diff --git a/src/plugins/cvs/cvsplugin.cpp b/src/plugins/cvs/cvsplugin.cpp index 1328f2e69cb..4d982f22bd4 100644 --- a/src/plugins/cvs/cvsplugin.cpp +++ b/src/plugins/cvs/cvsplugin.cpp @@ -231,10 +231,10 @@ private: bool isCommitEditorOpen() const; Core::IEditor *showOutputInEditor(const QString& title, const QString &output, - Id id, const FilePath &source, const QByteArray &codec); + Id id, const FilePath &source, const TextCodec &codec); CommandResult runCvs(const FilePath &workingDirectory, const QStringList &arguments, - RunFlags flags = RunFlags::None, const QByteArray &outputCodec = {}, + RunFlags flags = RunFlags::None, const TextCodec &outputCodec = {}, int timeoutMultiplier = 1) const; void annotate(const FilePath &workingDir, const QString &file, @@ -918,12 +918,10 @@ void CvsPluginPrivate::startCommit(const FilePath &workingDir, const QString &fi editor->setStateList(statusOutput); } -bool CvsPluginPrivate::commit(const QString &messageFile, - const QStringList &fileList) +bool CvsPluginPrivate::commit(const QString &messageFile, const QStringList &fileList) { const QStringList args{"commit", "-F", messageFile}; - const auto response = runCvs(m_commitRepository, args + fileList, RunFlags::ShowStdOut, nullptr, - 10); + const auto response = runCvs(m_commitRepository, args + fileList, RunFlags::ShowStdOut, {}, 10); return response.result() == ProcessResult::FinishedWithSuccess; } @@ -952,7 +950,7 @@ void CvsPluginPrivate::filelog(const FilePath &workingDir, const QString &file, bool enableAnnotationContextMenu) { - const QByteArray codec = VcsBaseEditor::getCodec(workingDir, QStringList(file)); + const TextCodec codec = VcsBaseEditor::getCodec(workingDir, QStringList(file)); // no need for temp file const QString id = VcsBaseEditor::getTitleId(workingDir, QStringList(file)); const FilePath source = VcsBaseEditor::getSource(workingDir, file); @@ -998,7 +996,7 @@ bool CvsPluginPrivate::update(const FilePath &topLevel, const QString &file) QStringList args{"update", "-dR"}; if (!file.isEmpty()) args.append(file); - const auto response = runCvs(topLevel, args, RunFlags::ShowStdOut, nullptr, 10); + const auto response = runCvs(topLevel, args, RunFlags::ShowStdOut, {}, 10); const bool ok = response.result() == ProcessResult::FinishedWithSuccess; if (ok) emit repositoryChanged(topLevel); @@ -1088,7 +1086,7 @@ void CvsPluginPrivate::annotate(const FilePath &workingDir, const QString &file, int lineNumber /* = -1 */) { const QStringList files(file); - const QByteArray codec = VcsBaseEditor::getCodec(workingDir, files); + const TextCodec codec = VcsBaseEditor::getCodec(workingDir, files); const QString id = VcsBaseEditor::getTitleId(workingDir, files, revision); const FilePath source = VcsBaseEditor::getSource(workingDir, file); QStringList args{"annotate"}; @@ -1127,7 +1125,7 @@ bool CvsPluginPrivate::status(const FilePath &topLevel, const QString &file, con const bool ok = response.result() == ProcessResult::FinishedWithSuccess; if (ok) { showOutputInEditor(title, response.cleanedStdOut(), CVS_COMMANDLOG_EDITOR_ID, - topLevel, nullptr); + topLevel, {}); } return ok; } @@ -1215,7 +1213,7 @@ bool CvsPluginPrivate::describe(const FilePath &toplevel, const QString &file, const QDate date = QDate::fromString(dateS, Qt::ISODate); const QString nextDayS = date.addDays(1).toString(Qt::ISODate); const QStringList args{"log", "-d", dateS + '<' + nextDayS}; - const auto repoLogResponse = runCvs(toplevel, args, RunFlags::None, nullptr, 10); + const auto repoLogResponse = runCvs(toplevel, args, RunFlags::None, {}, 10); if (repoLogResponse.result() != ProcessResult::FinishedWithSuccess) { *errorMessage = repoLogResponse.exitMessage(); return false; @@ -1243,11 +1241,11 @@ bool CvsPluginPrivate::describe(const FilePath &repositoryPath, { // Collect logs QString output; - QByteArray codec; + TextCodec codec; const QList<CvsLogEntry>::iterator lend = entries.end(); for (QList<CvsLogEntry>::iterator it = entries.begin(); it != lend; ++it) { // Before fiddling file names, try to find codec - if (codec.isEmpty()) + if (!codec.isValid()) codec = VcsBaseEditor::getCodec(repositoryPath, QStringList(it->file)); // Run log const QStringList args{"log", "-r", it->revisions.front().revision, it->file}; @@ -1303,7 +1301,7 @@ bool CvsPluginPrivate::describe(const FilePath &repositoryPath, // the working directory (see above). CommandResult CvsPluginPrivate::runCvs(const FilePath &workingDirectory, const QStringList &arguments, RunFlags flags, - const QByteArray &outputCodec, int timeoutMultiplier) const + const TextCodec &outputCodec, int timeoutMultiplier) const { const FilePath executable = settings().binaryPath(); if (executable.isEmpty()) @@ -1317,7 +1315,7 @@ CommandResult CvsPluginPrivate::runCvs(const FilePath &workingDirectory, IEditor *CvsPluginPrivate::showOutputInEditor(const QString& title, const QString &output, Utils::Id id, const FilePath &source, - const QByteArray &codec) + const TextCodec &codec) { QString s = title; IEditor *editor = EditorManager::openEditorWithContents(id, &s, output.toUtf8()); @@ -1330,7 +1328,7 @@ IEditor *CvsPluginPrivate::showOutputInEditor(const QString& title, const QStrin e->setForceReadOnly(true); if (!source.isEmpty()) e->setSource(source); - if (!codec.isEmpty()) + if (codec.isValid()) e->setCodec(codec); return editor; } diff --git a/src/plugins/debugger/dap/pydapengine.cpp b/src/plugins/debugger/dap/pydapengine.cpp index 6f915a80947..034a94977a4 100644 --- a/src/plugins/debugger/dap/pydapengine.cpp +++ b/src/plugins/debugger/dap/pydapengine.cpp @@ -228,9 +228,10 @@ void PyDapEngine::setupEngine() if (missingModuleInstallation(interpreter, "debugpy")) { Utils::InfoBarEntry info(installDebugPyInfoBarId, - Tr::tr( - "Python debugging support is not available. Install the debugpy package."), + Tr::tr("Install the debugpy package to turn on Python debugging support."), Utils::InfoBarEntry::GlobalSuppression::Enabled); + info.setTitle(Tr::tr("Python Debugging Is Not Available")); + info.setInfoType(InfoLabel::Warning); info.addCustomButton( Tr::tr("Install debugpy"), [this] { diff --git a/src/plugins/debugger/debuggeritem.cpp b/src/plugins/debugger/debuggeritem.cpp index b75deb8637e..7d3c37685f5 100644 --- a/src/plugins/debugger/debuggeritem.cpp +++ b/src/plugins/debugger/debuggeritem.cpp @@ -195,6 +195,7 @@ Result<DebuggerItem::TechnicalData> DebuggerItem::TechnicalData::extract( { Environment env = customEnvironment.value_or(fromExecutable.deviceEnvironment()); DebuggerItem::addAndroidLldbPythonEnv(fromExecutable, env); + DebuggerItem::fixupAndroidLlldbPythonDylib(fromExecutable); if (qgetenv("QTC_ENABLE_NATIVE_DAP_DEBUGGERS").toInt() != 0) { for (const auto &dapServerSuffix : {QString{"-dap"}, QString{"-vscode"}}) { @@ -361,6 +362,31 @@ bool DebuggerItem::addAndroidLldbPythonEnv(const Utils::FilePath &lldbCmd, Utils return false; } +bool DebuggerItem::fixupAndroidLlldbPythonDylib(const FilePath &lldbCmd) +{ + if (!lldbCmd.baseName().contains("lldb") + || !lldbCmd.path().contains("/toolchains/llvm/prebuilt/") || !HostOsInfo::isMacHost()) + return false; + + const FilePath lldbBaseDir = lldbCmd.parentDir().parentDir(); + const FilePath pythonLibDir = lldbBaseDir / "python3" / "lib"; + if (!pythonLibDir.exists()) + return false; + + pythonLibDir.iterateDirectory( + [lldbBaseDir](const FilePath &file) { + if (file.fileName().startsWith("libpython3")) { + const FilePath lldbLibPython = lldbBaseDir / "lib" / file.fileName(); + if (!lldbLibPython.exists()) + file.copyFile(lldbLibPython); + return IterationPolicy::Stop; + } + return IterationPolicy::Continue; + }, + {{"*.dylib"}}); + return true; +} + QString DebuggerItem::engineTypeName() const { switch (m_technicalData.engineType) { diff --git a/src/plugins/debugger/debuggeritem.h b/src/plugins/debugger/debuggeritem.h index 3346e1fadce..ceb100a7957 100644 --- a/src/plugins/debugger/debuggeritem.h +++ b/src/plugins/debugger/debuggeritem.h @@ -101,6 +101,7 @@ public: void setGeneric(bool on); static bool addAndroidLldbPythonEnv(const Utils::FilePath &lldbCmd, Utils::Environment &env); + static bool fixupAndroidLlldbPythonDylib(const Utils::FilePath &lldbCmd); private: DebuggerItem(const QVariant &id); diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 7daa4c12f39..a19b75b51e3 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -202,6 +202,8 @@ void LldbEngine::setupEngine() environment.appendOrSet("PYTHONPATH", "/usr/lib/llvm-14/lib/python3.10/dist-packages"); } + DebuggerItem::fixupAndroidLlldbPythonDylib(lldbCmd); + if (runParameters().runAsRoot()) { ProjectExplorer::RunControl::provideAskPassEntry(environment); m_lldbProc.setRunAsRoot(true); diff --git a/src/plugins/designer/formwindowfile.cpp b/src/plugins/designer/formwindowfile.cpp index 4b34b8c7b1f..81f10a883ea 100644 --- a/src/plugins/designer/formwindowfile.cpp +++ b/src/plugins/designer/formwindowfile.cpp @@ -31,7 +31,7 @@ FormWindowFile::FormWindowFile(QDesignerFormWindowInterface *form, QObject *pare setParent(parent); setId(Utils::Id(Designer::Constants::K_DESIGNER_XML_EDITOR_ID)); // Designer needs UTF-8 regardless of settings. - setCodec("UTF-8"); + setCodec(TextCodec::utf8()); connect(m_formWindow->core()->formWindowManager(), &QDesignerFormWindowManagerInterface::formWindowRemoved, this, &FormWindowFile::slotFormWindowRemoved); connect(m_formWindow->commandHistory(), &QUndoStack::indexChanged, @@ -216,7 +216,7 @@ QString FormWindowFile::fallbackSaveAsFileName() const bool FormWindowFile::supportsCodec(const QByteArray &codec) const { - return TextEditor::TextDocument::isUtf8Codec(codec); + return TextCodec::isUtf8Codec(codec); } Result<> FormWindowFile::writeFile(const Utils::FilePath &filePath) const diff --git a/src/plugins/diffeditor/diffeditorplugin.cpp b/src/plugins/diffeditor/diffeditorplugin.cpp index 59a9d484f77..0f2656dc1e0 100644 --- a/src/plugins/diffeditor/diffeditorplugin.cpp +++ b/src/plugins/diffeditor/diffeditorplugin.cpp @@ -154,18 +154,18 @@ DiffFilesController::DiffFilesController(IDocument *document) setReloadRecipe(recipe); } -class DiffCurrentFileController : public DiffFilesController +class DiffCurrentFileController final : public DiffFilesController { public: - DiffCurrentFileController(IDocument *document, const QString &fileName) + DiffCurrentFileController(IDocument *document, const FilePath &filePath) : DiffFilesController(document) - , m_fileName(fileName) {} + , m_filePath(filePath) {} protected: QList<ReloadInput> reloadInputList() const final; private: - const QString m_fileName; + const FilePath m_filePath; }; QList<ReloadInput> DiffCurrentFileController::reloadInputList() const @@ -173,20 +173,20 @@ QList<ReloadInput> DiffCurrentFileController::reloadInputList() const QList<ReloadInput> result; auto textDocument = qobject_cast<TextDocument *>( - DocumentModel::documentForFilePath(FilePath::fromString(m_fileName))); + DocumentModel::documentForFilePath(m_filePath)); if (textDocument && textDocument->isModified()) { TextFileFormat format = textDocument->format(); const TextFileFormat::ReadResult leftResult = format.readFile( - FilePath::fromString(m_fileName), format.codec()); + m_filePath, format.codec()); const QString rightText = textDocument->plainText(); ReloadInput reloadInput; reloadInput.text = {leftResult.content, rightText}; - reloadInput.fileInfo = {DiffFileInfo(m_fileName, Tr::tr("Saved")), - DiffFileInfo(m_fileName, Tr::tr("Modified"))}; + reloadInput.fileInfo = {DiffFileInfo(m_filePath.path(), Tr::tr("Saved")), + DiffFileInfo(m_filePath.path(), Tr::tr("Modified"))}; reloadInput.fileInfo[RightSide].patchBehaviour = DiffFileInfo::PatchEditor; reloadInput.binaryFiles = (leftResult.code == TextFileFormat::ReadEncodingError); @@ -317,7 +317,7 @@ private: QList<ReloadInput> DiffExternalFilesController::reloadInputList() const { TextFileFormat format; - format.setCodecName(EditorManager::defaultTextCodecName()); + format.setCodec(EditorManager::defaultTextCodec()); const TextFileFormat::ReadResult leftResult = format.readFile(m_leftFilePath, format.codec()); const TextFileFormat::ReadResult rightResult = format.readFile(m_rightFilePath, format.codec()); @@ -483,13 +483,14 @@ void DiffEditorPlugin::diffCurrentFile() if (!textDocument) return; - const QString fileName = textDocument->filePath().toUrlishString(); - if (fileName.isEmpty()) + const FilePath filePath = textDocument->filePath(); + if (filePath.isEmpty()) return; - const QString documentId = Constants::DIFF_EDITOR_PLUGIN + QLatin1String(".Diff.") + fileName; - const QString title = Tr::tr("Diff \"%1\"").arg(fileName); - reload<DiffCurrentFileController>(documentId, title, fileName); + const QString documentId = Constants::DIFF_EDITOR_PLUGIN + QLatin1String(".Diff.") + + filePath.toUrlishString(); + const QString title = Tr::tr("Diff \"%1\"").arg(filePath.toUserOutput()); + reload<DiffCurrentFileController>(documentId, title, filePath); } void DiffEditorPlugin::diffOpenFiles() diff --git a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp index a2d421ef56e..ba10ee9cfbb 100644 --- a/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp +++ b/src/plugins/diffeditor/diffeditorwidgetcontroller.cpp @@ -167,7 +167,7 @@ void DiffEditorWidgetController::patch(PatchAction patchAction, int fileIndex, i return; FileChangeBlocker fileChangeBlocker(absFilePath); - if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch), + if (PatchTool::runPatch(EditorManager::defaultTextCodec().fromUnicode(patch), workingDirectory, strip, patchAction)) m_document->reload(); } else { // PatchEditor @@ -190,7 +190,7 @@ void DiffEditorWidgetController::patch(PatchAction patchAction, int fileIndex, i if (patch.isEmpty()) return; - if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch), + if (PatchTool::runPatch(EditorManager::defaultTextCodec().fromUnicode(patch), FilePath::fromString(contentsCopyDir), 0, patchAction)) { if (textDocument->reload(FilePath::fromString(contentsCopyFileName))) m_document->reload(); @@ -300,7 +300,7 @@ void DiffEditorWidgetController::updateCannotDecodeInfo() InfoBarEntry info(selectEncodingId, Tr::tr("<b>Error:</b> Could not decode \"%1\" with \"%2\"-encoding.") .arg(m_document->displayName(), - QString::fromLatin1(m_document->codec()->name()))); + QString::fromLatin1(m_document->codec().name()))); info.addCustomButton(Tr::tr("Select Encoding"), [this] { m_document->selectEncoding(); }); infoBar->addInfo(info); } else { diff --git a/src/plugins/docker/dockercontainerthread.cpp b/src/plugins/docker/dockercontainerthread.cpp index 27cc5b0ed64..25e3caa4f41 100644 --- a/src/plugins/docker/dockercontainerthread.cpp +++ b/src/plugins/docker/dockercontainerthread.cpp @@ -73,6 +73,22 @@ private: { using namespace std::chrono_literals; + Process eventProcess; + // Start an docker event listener to listen for the container start event + eventProcess.setCommand( + {m_init.dockerBinaryPath, + {"events", "--filter", "event=start", "--filter", "container=" + m_containerId}}); + eventProcess.setProcessMode(ProcessMode::Reader); + eventProcess.start(); + if (!eventProcess.waitForStarted(5s)) { + if (eventProcess.state() == QProcess::NotRunning) { + return ResultError( + Tr::tr("Failed starting Docker event listener. Exit code: %1, output: %2") + .arg(eventProcess.exitCode()) + .arg(eventProcess.allOutput())); + } + } + m_startProcess = new Process(this); m_startProcess->setCommand( @@ -90,9 +106,31 @@ private: qCWarning(dockerThreadLog) << "Docker container start process took more than 5 seconds to start."; } - qCDebug(dockerThreadLog) << "Started container: " << m_startProcess->commandLine(); + // Read a line from the eventProcess + while (true) { + if (!eventProcess.waitForReadyRead(5s)) { + m_startProcess->kill(); + if (!m_startProcess->waitForFinished(5s)) { + qCWarning(dockerThreadLog) + << "Docker start process took more than 5 seconds to finish."; + } + return ResultError( + Tr::tr("Failed starting Docker container. Exit code: %1, output: %2") + .arg(eventProcess.exitCode()) + .arg(eventProcess.allOutput())); + } + if (!eventProcess.stdOutLines().isEmpty()) { + break; + } + } + qCDebug(dockerThreadLog) << "Started event received for container: " << m_containerId; + eventProcess.kill(); + if (!eventProcess.waitForFinished(5s)) { + qCWarning(dockerThreadLog) + << "Docker event listener process took more than 5 seconds to finish."; + } return ResultOk; } diff --git a/src/plugins/extensionmanager/extensionmanagerwidget.cpp b/src/plugins/extensionmanager/extensionmanagerwidget.cpp index e88a938ca21..0eac1d1a805 100644 --- a/src/plugins/extensionmanager/extensionmanagerwidget.cpp +++ b/src/plugins/extensionmanager/extensionmanagerwidget.cpp @@ -102,16 +102,18 @@ const char kRestartSetting[] = "RestartAfterPluginEnabledChanged"; static void requestRestart() { - if (ICore::infoBar()->canInfoBeAdded(kRestartSetting)) { + InfoBar *infoBar = ICore::infoBar(); + if (infoBar->canInfoBeAdded(kRestartSetting)) { Utils::InfoBarEntry info(kRestartSetting, Core::Tr::tr("Plugin changes will take effect after restart.")); info.setTitle(Tr::tr("Restart Required")); + info.setInfoType(InfoLabel::Information); info.addCustomButton( Tr::tr("Restart Now"), [] { QTimer::singleShot(0, ICore::instance(), &ICore::restart); }, {}, InfoBarEntry::ButtonAction::Hide); - ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } } diff --git a/src/plugins/git/CMakeLists.txt b/src/plugins/git/CMakeLists.txt index dfe6a9c05f1..742843b4058 100644 --- a/src/plugins/git/CMakeLists.txt +++ b/src/plugins/git/CMakeLists.txt @@ -37,4 +37,5 @@ add_qtc_plugin(Git remotedialog.cpp remotedialog.h remotemodel.cpp remotemodel.h stashdialog.cpp stashdialog.h + temporarypatchfile.cpp temporarypatchfile.h ) diff --git a/src/plugins/git/branchmodel.cpp b/src/plugins/git/branchmodel.cpp index 9d1cf2eb69d..6fd7dbd0376 100644 --- a/src/plugins/git/branchmodel.cpp +++ b/src/plugins/git/branchmodel.cpp @@ -81,6 +81,7 @@ public: bool childOf(BranchNode *node) const { + QTC_ASSERT(node, return false); if (this == node) return true; return parent ? parent->childOf(node) : false; @@ -144,6 +145,7 @@ public: void insert(const QStringList &path, BranchNode *n) { + QTC_ASSERT(n, return); BranchNode *current = this; for (int i = 0; i < path.count(); ++i) { BranchNode *c = current->childOfName(path.at(i)); @@ -157,6 +159,7 @@ public: BranchNode *append(BranchNode *n) { + QTC_ASSERT(n, return nullptr); n->parent = this; children.append(n); return n; @@ -164,6 +167,7 @@ public: BranchNode *prepend(BranchNode *n) { + QTC_ASSERT(n, return nullptr); n->parent = this; children.prepend(n); return n; @@ -691,6 +695,7 @@ bool BranchModel::branchIsMerged(const QModelIndex &idx) static int positionForName(BranchNode *node, const QString &name) { + QTC_ASSERT(node, return 0); int pos = 0; for (pos = 0; pos < node->count(); ++pos) { if (node->children.at(pos)->name >= name) diff --git a/src/plugins/git/commitdata.h b/src/plugins/git/commitdata.h index 0760d1e4816..25683794bee 100644 --- a/src/plugins/git/commitdata.h +++ b/src/plugins/git/commitdata.h @@ -6,6 +6,7 @@ #include "gitsettings.h" // CommitType #include <utils/filepath.h> +#include <utils/textcodec.h> #include <QStringList> #include <QPair> @@ -82,7 +83,7 @@ public: CommitType commitType; QString amendHash; - QByteArray commitEncoding; + Utils::TextCodec commitEncoding; GitSubmitEditorPanelInfo panelInfo; GitSubmitEditorPanelData panelData; bool enablePush = false; diff --git a/src/plugins/git/git.qbs b/src/plugins/git/git.qbs index 1379de7d670..4a9c70f1b8b 100644 --- a/src/plugins/git/git.qbs +++ b/src/plugins/git/git.qbs @@ -61,6 +61,8 @@ QtcPlugin { "remotemodel.h", "stashdialog.cpp", "stashdialog.h", + "temporarypatchfile.cpp", + "temporarypatchfile.h", ] Group { diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp index 1560536b58d..05a9eac3740 100644 --- a/src/plugins/git/gitclient.cpp +++ b/src/plugins/git/gitclient.cpp @@ -11,6 +11,7 @@ #include "gittr.h" #include "gitutils.h" #include "mergetool.h" +#include "temporarypatchfile.h" #include <coreplugin/coreconstants.h> #include <coreplugin/editormanager/editormanager.h> @@ -109,21 +110,15 @@ static QString branchesDisplay(const QString &prefix, QStringList *branches, boo static void stage(DiffEditorController *diffController, const QString &patch, bool revert) { - TemporaryFile patchFile("git-patchfile"); - if (!patchFile.open()) + if (patch.isEmpty()) return; - + TemporaryPatchFile patchFile(patch); const FilePath baseDir = diffController->workingDirectory(); - QTextCodec *codec = EditorManager::defaultTextCodec(); - const QByteArray patchData = codec ? codec->fromUnicode(patch) : patch.toLocal8Bit(); - patchFile.write(patchData); - patchFile.close(); - QStringList args = {"--cached"}; if (revert) args << "--reverse"; QString errorMessage; - if (gitClient().synchronousApplyPatch(baseDir, patchFile.fileName(), + if (gitClient().synchronousApplyPatch(baseDir, patchFile.filePath().toUrlishString(), &errorMessage, args)) { if (errorMessage.isEmpty()) { if (revert) @@ -966,20 +961,20 @@ void GitClient::updateModificationInfos() } } -QByteArray GitClient::defaultCommitEncoding() const +TextCodec GitClient::defaultCommitEncoding() const { // Set default commit encoding to 'UTF-8', when it's not set, // to solve displaying error of commit log with non-latin characters. - return "UTF-8"; + return TextCodec::utf8(); } -QByteArray GitClient::encoding(GitClient::EncodingType encodingType, const FilePath &source) const +TextCodec GitClient::encoding(GitClient::EncodingType encodingType, const FilePath &source) const { auto codec = [this](const FilePath &workingDirectory, const QString &configVar) { const QString codecName = readConfigValue(workingDirectory, configVar).trimmed(); if (codecName.isEmpty()) return defaultCommitEncoding(); - return codecName.toUtf8(); + return TextCodec::codecForName(codecName.toUtf8()); }; switch (encodingType) { @@ -990,7 +985,7 @@ QByteArray GitClient::encoding(GitClient::EncodingType encodingType, const FileP case EncodingCommit: return codec(source, "i18n.commitEncoding"); default: - return QByteArray(); + return {}; } } @@ -1940,7 +1935,7 @@ bool GitClient::executeSynchronousStash(const FilePath &workingDirectory, if (unstagedOnly) arguments << "--keep-index"; if (!message.isEmpty()) - arguments << message; + arguments << "-m" << message; const RunFlags flags = RunFlags::ShowStdOut | RunFlags::ExpectRepoChanges | RunFlags::ShowSuccessMessage; @@ -2702,16 +2697,14 @@ Result<CommitData> GitClient::enrichCommitData(const FilePath &repoDirectory, } CommitData commitData = commitDataIn; - QTextCodec *authorCodec = HostOsInfo::isWindowsHost() - ? QTextCodec::codecForName("UTF-8") - : QTextCodec::codecForName(commitData.commitEncoding); + const TextCodec authorCodec = HostOsInfo::isWindowsHost() + ? TextCodec::utf8() + : commitData.commitEncoding; QByteArray stdOut = result.rawStdOut(); commitData.amendHash = QLatin1String(shiftLogLine(stdOut)); - commitData.panelData.author = authorCodec->toUnicode(shiftLogLine(stdOut)); - commitData.panelData.email = authorCodec->toUnicode(shiftLogLine(stdOut)); - QTextCodec *commitCodec = QTextCodec::codecForName(commitData.commitEncoding); - if (QTC_GUARD(commitCodec)) - commitData.commitTemplate = commitCodec->toUnicode(stdOut); + commitData.panelData.author = authorCodec.toUnicode(shiftLogLine(stdOut)); + commitData.panelData.email = authorCodec.toUnicode(shiftLogLine(stdOut)); + commitData.commitTemplate = commitData.commitEncoding.toUnicode(stdOut); return commitData; } @@ -2967,6 +2960,21 @@ bool GitClient::addAndCommit(const FilePath &repositoryDirectory, return false; } +/** + * Formats the patches given in \a patchRange as multiple singe file patches. + * + * The format for \a patchRange is {"-n", "hash"} where `n` specifies the + * number of commits before `hash`. + */ +void GitClient::formatPatch(const Utils::FilePath &workingDirectory, const QStringList &patchRange) +{ + if (patchRange.isEmpty()) + return; + + const QStringList args = {"format-patch"}; + vcsExec(workingDirectory, args + patchRange, RunFlags::ShowSuccessMessage); +} + /* Revert: This function can be called with a file list (to revert single * files) or a single directory (revert all). Qt Creator currently has only * 'revert single' in its VCS menus, but the code is prepared to deal with @@ -3543,18 +3551,12 @@ QString GitClient::readGitVar(const FilePath &workingDirectory, const QString &c return readOneLine(workingDirectory, {"var", configVar}); } -static QByteArray configFileCodec() +static TextCodec configFileCodec() { // Git for Windows always uses UTF-8 for configuration: // https://github.com/msysgit/msysgit/wiki/Git-for-Windows-Unicode-Support#convert-config-files - static const QByteArray codec = []() -> QByteArray { - if (HostOsInfo::isWindowsHost()) - return "UTF-8"; - if (QTextCodec *codec = QTextCodec::codecForLocale()) - return codec->name(); - QTC_CHECK(false); - return {}; - }(); + static const TextCodec codec = + HostOsInfo::isWindowsHost() ? TextCodec::utf8() : TextCodec::codecForLocale(); return codec; } @@ -3873,7 +3875,7 @@ IEditor *GitClient::openShowEditor(const FilePath &workingDirectory, const QStri if (content.isEmpty()) return nullptr; QByteArray fileContent; - if (TextFileFormat::readFileUtf8(path, nullptr, &fileContent)) { + if (TextFileFormat::readFileUtf8(path, {}, &fileContent)) { if (fileContent == content) return nullptr; // open the file for read/write } diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h index eedc8dce20f..3e99c988be4 100644 --- a/src/plugins/git/gitclient.h +++ b/src/plugins/git/gitclient.h @@ -312,6 +312,8 @@ public: const Utils::FilePath &messageFile, VcsBase::SubmitFileModel *model); + void formatPatch(const Utils::FilePath &workingDirectory, const QStringList &patchRange); + enum StatusResult { StatusChanged, StatusUnchanged, StatusFailed }; StatusResult gitStatus(const Utils::FilePath &workingDirectory, StatusMode mode, QString *output = nullptr, QString *errorMessage = nullptr) const; @@ -359,9 +361,9 @@ public: Author parseAuthor(const QString &authorInfo); Author getAuthor(const Utils::FilePath &workingDirectory); - QByteArray defaultCommitEncoding() const; + Utils::TextCodec defaultCommitEncoding() const; enum EncodingType { EncodingSource, EncodingLogOutput, EncodingCommit, EncodingDefault }; - QByteArray encoding(EncodingType encodingType, const Utils::FilePath &source = {}) const; + Utils::TextCodec encoding(EncodingType encodingType, const Utils::FilePath &source = {}) const; void readConfigAsync(const Utils::FilePath &workingDirectory, const QStringList &arguments, const VcsBase::CommandHandler &handler) const; diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp index 05bf7016857..f39b9804721 100644 --- a/src/plugins/git/gitplugin.cpp +++ b/src/plugins/git/gitplugin.cpp @@ -18,6 +18,7 @@ #include "logchangedialog.h" #include "remotedialog.h" #include "stashdialog.h" +#include "temporarypatchfile.h" #include "gerrit/gerritplugin.h" @@ -66,6 +67,7 @@ #include <QAction> #include <QApplication> +#include <QClipboard> #include <QDebug> #include <QDir> #include <QFileDialog> @@ -243,7 +245,9 @@ public: void cleanProjectDirectory(); void cleanRepository(); void updateSubmodules(); + void createPatchesFromCommits(); void applyCurrentFilePatch(); + void applyClipboardPatch(); void promptApplyPatch(); void stash(bool unstagedOnly = false); @@ -834,12 +838,20 @@ GitPluginPrivate::GitPluginPrivate() patchMenu->menu()->setTitle(Tr::tr("&Patch")); localRepositoryMenu->addMenu(patchMenu); + createRepositoryAction(patchMenu, Tr::tr("Create from Commits..."), + "Git.CreatePatch", context, true, + std::bind(&GitPluginPrivate::createPatchesFromCommits, this)); + // Apply current file as patch is handled specially. m_applyCurrentFilePatchAction = createParameterAction(patchMenu, Tr::tr("Apply from Editor"), Tr::tr("Apply \"%1\""), "Git.ApplyCurrentFilePatch", context, true, std::bind(&GitPluginPrivate::applyCurrentFilePatch, this)); + + createRepositoryAction(patchMenu, Tr::tr("Apply from Clipboard"), "Git.ApplyClipboardPatch", + context, true, std::bind(&GitPluginPrivate::applyClipboardPatch, this)); + createRepositoryAction(patchMenu, Tr::tr("Apply from File..."), "Git.ApplyPatch", context, true, std::bind(&GitPluginPrivate::promptApplyPatch, this)); @@ -1191,6 +1203,21 @@ protected: } }; +class PatchItemDelegate : public IconItemDelegate +{ +public: + PatchItemDelegate(LogChangeWidget *widget) + : IconItemDelegate(widget, Icons::PLUS) + { + } + +protected: + bool hasIcon(int row) const override + { + return isRowSelected(row); + } +}; + void GitPluginPrivate::resetRepository() { if (!DocumentManager::saveAllModifiedDocuments()) @@ -1571,6 +1598,21 @@ void GitPluginPrivate::updateSubmodules() gitClient().updateSubmodulesIfNeeded(state.topLevel(), false); } +void GitPluginPrivate::createPatchesFromCommits() +{ + const VcsBasePluginState state = currentState(); + QTC_ASSERT(state.hasTopLevel(), return); + + LogChangeDialog dialog(false, Core::ICore::dialogParent()); + PatchItemDelegate delegate(dialog.widget()); + dialog.setContiguousSelectionEnabled(true); + dialog.setWindowTitle(Tr::tr("Select commits for patch creation")); + + const Utils::FilePath topLevel = state.topLevel(); + if (dialog.runDialog(topLevel, {}, LogChangeWidget::None)) + gitClient().formatPatch(topLevel, dialog.patchRange()); +} + // If the file is modified in an editor, make sure it is saved. static bool ensureFileSaved(const QString &fileName) { @@ -1588,6 +1630,20 @@ void GitPluginPrivate::applyCurrentFilePatch() applyPatch(state.topLevel(), patchFile); } +void GitPluginPrivate::applyClipboardPatch() +{ + const VcsBasePluginState state = currentState(); + QTC_ASSERT(state.hasTopLevel(), return); + + QClipboard *clipboard = QApplication::clipboard(); + const QString patch = clipboard->text(); + if (patch.isEmpty()) + return; + + const TemporaryPatchFile patchFile(patch); + applyPatch(state.topLevel(), patchFile.filePath().toUrlishString()); +} + void GitPluginPrivate::promptApplyPatch() { const VcsBasePluginState state = currentState(); diff --git a/src/plugins/git/gitsubmiteditor.cpp b/src/plugins/git/gitsubmiteditor.cpp index aef21db3e4a..6b68af5779a 100644 --- a/src/plugins/git/gitsubmiteditor.cpp +++ b/src/plugins/git/gitsubmiteditor.cpp @@ -257,8 +257,8 @@ QByteArray GitSubmitEditor::fileContents() const // Do the encoding convert, When use user-defined encoding // e.g. git config --global i18n.commitencoding utf-8 - if (QTextCodec *codec = QTextCodec::codecForName(m_commitEncoding)) - return codec->fromUnicode(text); + if (m_commitEncoding.isValid()) + return m_commitEncoding.fromUnicode(text); // Using utf-8 as the default encoding return text.toUtf8(); diff --git a/src/plugins/git/gitsubmiteditor.h b/src/plugins/git/gitsubmiteditor.h index fbc8ab09c2b..d768ab7bcd0 100644 --- a/src/plugins/git/gitsubmiteditor.h +++ b/src/plugins/git/gitsubmiteditor.h @@ -47,7 +47,7 @@ private: inline const GitSubmitEditorWidget *submitEditorWidget() const; VcsBase::SubmitFileModel *m_model = nullptr; - QByteArray m_commitEncoding; + Utils::TextCodec m_commitEncoding; CommitType m_commitType = SimpleCommit; QString m_amenHash; Utils::FilePath m_workingDirectory; diff --git a/src/plugins/git/instantblame.cpp b/src/plugins/git/instantblame.cpp index 8d317366074..35fbd3f258d 100644 --- a/src/plugins/git/instantblame.cpp +++ b/src/plugins/git/instantblame.cpp @@ -495,17 +495,17 @@ bool InstantBlame::refreshWorkingDirectory(const FilePath &workingDirectory) m_workingDirectory = workingDirectory; const auto commitCodecHandler = [this, workingDirectory](const CommandResult &result) { - QByteArray codec; + TextCodec codec; if (result.result() == ProcessResult::FinishedWithSuccess) { const QString codecName = result.cleanedStdOut().trimmed(); - codec = codecName.toUtf8(); + codec = TextCodec::codecForName(codecName.toUtf8()); } else { codec = gitClient().defaultCommitEncoding(); } if (m_codec != codec) { - qCInfo(log) << "Setting new text codec:" << codec; + qCInfo(log) << "Setting new text codec:" << codec.displayName(); m_codec = codec; force(); } diff --git a/src/plugins/git/instantblame.h b/src/plugins/git/instantblame.h index 2ffea3b7bf8..e4d9de22d05 100644 --- a/src/plugins/git/instantblame.h +++ b/src/plugins/git/instantblame.h @@ -65,7 +65,7 @@ private: void slotDocumentChanged(); Utils::FilePath m_workingDirectory; - QByteArray m_codec; + Utils::TextCodec m_codec; Author m_author; int m_lastVisitedEditorLine = -1; Core::IDocument *m_document = nullptr; diff --git a/src/plugins/git/logchangedialog.cpp b/src/plugins/git/logchangedialog.cpp index a198b22782b..dbd2c460817 100644 --- a/src/plugins/git/logchangedialog.cpp +++ b/src/plugins/git/logchangedialog.cpp @@ -104,6 +104,30 @@ int LogChangeWidget::commitIndex() const return -1; } +/** + * Returns a commit range suitable for `git format-patch`. + * + * The format is {"-n", "hash"} or an empty string list if nothing was selected. + */ +QStringList LogChangeWidget::patchRange() const +{ + const QModelIndexList selected = selectionModel()->selectedRows(); + if (selected.isEmpty()) + return {}; + + const QString size = QString::number(selected.size()); + const QStandardItem *highestItem = m_model->item(selected.first().row()); + QTC_ASSERT(highestItem, return {}); + const QString highestText = highestItem->text(); + const QStringList result = {"-" + size, highestText}; + return result; +} + +bool LogChangeWidget::isRowSelected(int row) const +{ + return selectionModel()->isRowSelected(row); +} + QString LogChangeWidget::earliestCommit() const { int rows = m_model->rowCount(); @@ -241,6 +265,14 @@ LogChangeDialog::LogChangeDialog(bool isReset, QWidget *parent) : resize(600, 400); } +void LogChangeDialog::setContiguousSelectionEnabled(bool enabled) +{ + if (enabled) + m_widget->setSelectionMode(QAbstractItemView::ContiguousSelection); + else + m_widget->setSelectionMode(QAbstractItemView::SingleSelection); +} + bool LogChangeDialog::runDialog(const FilePath &repository, const QString &commit, LogChangeWidget::LogFlags flags) @@ -266,6 +298,11 @@ int LogChangeDialog::commitIndex() const return m_widget->commitIndex(); } +QStringList LogChangeDialog::patchRange() const +{ + return m_widget->patchRange(); +} + QString LogChangeDialog::resetFlag() const { if (!m_resetTypeComboBox) @@ -288,6 +325,11 @@ int LogItemDelegate::currentRow() const return m_widget->commitIndex(); } +int LogItemDelegate::isRowSelected(int row) const +{ + return m_widget->isRowSelected(row); +} + IconItemDelegate::IconItemDelegate(LogChangeWidget *widget, const Utils::Icon &icon) : LogItemDelegate(widget) , m_icon(icon.icon()) diff --git a/src/plugins/git/logchangedialog.h b/src/plugins/git/logchangedialog.h index 932fcdf887e..2377bde8456 100644 --- a/src/plugins/git/logchangedialog.h +++ b/src/plugins/git/logchangedialog.h @@ -43,6 +43,8 @@ public: bool init(const Utils::FilePath &repository, const QString &commit = {}, LogFlags flags = None); QString commit() const; int commitIndex() const; + QStringList patchRange() const; + bool isRowSelected(int row) const; QString earliestCommit() const; void setItemDelegate(QAbstractItemDelegate *delegate); void setExcludedRemote(const QString &remote) { m_excludedRemote = remote; } @@ -67,11 +69,14 @@ class LogChangeDialog : public QDialog public: LogChangeDialog(bool isReset, QWidget *parent); + void setContiguousSelectionEnabled(bool enabled); + bool runDialog(const Utils::FilePath &repository, const QString &commit = QString(), LogChangeWidget::LogFlags flags = LogChangeWidget::None); QString commit() const; int commitIndex() const; + QStringList patchRange() const; QString resetFlag() const; LogChangeWidget *widget() const; @@ -87,6 +92,7 @@ protected: LogItemDelegate(LogChangeWidget *widget); int currentRow() const; + int isRowSelected(int row) const; private: LogChangeWidget *m_widget; diff --git a/src/plugins/git/temporarypatchfile.cpp b/src/plugins/git/temporarypatchfile.cpp new file mode 100644 index 00000000000..9a4f21e09fa --- /dev/null +++ b/src/plugins/git/temporarypatchfile.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2025 Andre Hartmann <[email protected]> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "temporarypatchfile.h" + +#include <coreplugin/editormanager/editormanager.h> + +#include <QTextCodec> + +using namespace Utils; + +TemporaryPatchFile::TemporaryPatchFile(const QString &patch) + : patchFile(new Utils::TemporaryFile("git-patchfile")) +{ + if (!patchFile->open()) + return; + + QString normalized = patch; + normalized.replace("\r\n", "\n").replace('\r', '\n'); + const TextCodec codec = Core::EditorManager::defaultTextCodec(); + const QByteArray patchData = codec.isValid() ? codec.fromUnicode(normalized) : normalized.toLocal8Bit(); + patchFile->write(patchData); + patchFile->close(); +} + +Utils::FilePath TemporaryPatchFile::filePath() const +{ + return Utils::FilePath::fromString(patchFile->fileName()); +} diff --git a/src/plugins/git/temporarypatchfile.h b/src/plugins/git/temporarypatchfile.h new file mode 100644 index 00000000000..d933b5ed169 --- /dev/null +++ b/src/plugins/git/temporarypatchfile.h @@ -0,0 +1,18 @@ +// Copyright (C) 2025 Andre Hartmann <[email protected]> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include <utils/filepath.h> +#include <utils/temporaryfile.h> + +class TemporaryPatchFile +{ +public: + TemporaryPatchFile(const QString &patch); + + Utils::FilePath filePath() const; + +private: + std::unique_ptr<Utils::TemporaryFile> patchFile; +}; diff --git a/src/plugins/languageclient/languageclientsymbolsupport.cpp b/src/plugins/languageclient/languageclientsymbolsupport.cpp index cd730903751..772d9b5215e 100644 --- a/src/plugins/languageclient/languageclientsymbolsupport.cpp +++ b/src/plugins/languageclient/languageclientsymbolsupport.cpp @@ -289,7 +289,7 @@ QStringList SymbolSupport::getFileContents(const FilePath &filePath) } else { TextFileFormat format; format.lineTerminationMode = TextFileFormat::LFLineTerminator; - const QTextCodec *codec = Core::EditorManager::defaultTextCodec(); + const TextCodec codec = Core::EditorManager::defaultTextCodec(); const TextFileFormat::ReadResult result = format.readFile(filePath, codec); fileContent = result.content; if (result.code != TextFileFormat::ReadSuccess) { diff --git a/src/plugins/lua/bindings/fetch.cpp b/src/plugins/lua/bindings/fetch.cpp index 71f1e30c3bf..21eaed9025a 100644 --- a/src/plugins/lua/bindings/fetch.cpp +++ b/src/plugins/lua/bindings/fetch.cpp @@ -221,6 +221,8 @@ void setupFetchModule() infoBarId, Tr::tr("Allow the extension \"%1\" to fetch data from the internet?") .arg(pluginName)}; + entry.setTitle(Tr::tr("Allow Fetching Data?")); + entry.setInfoType(InfoLabel::Warning); entry.setDetailsWidgetCreator([pluginName, url] { const QString markdown = Tr::tr("Allow the extension \"%1\" to fetch data " "from the following URL:\n\n") diff --git a/src/plugins/lua/bindings/gui.cpp b/src/plugins/lua/bindings/gui.cpp index b6b96bb4a6e..62b0ff17be9 100644 --- a/src/plugins/lua/bindings/gui.cpp +++ b/src/plugins/lua/bindings/gui.cpp @@ -103,6 +103,11 @@ void constructWidget(std::unique_ptr<T> &widget, const sol::table &children) template<class T> concept has_##name = requires { \ { std::declval<T>().name(__VA_ARGS__) } -> std::same_as<void>; \ }; + +#define CREATE_HAS_FUNC_NAMED(name, hasFuncName, ...) \ + template<class T> concept has_##hasFuncName = requires { \ + { std::declval<T>().name(__VA_ARGS__) } -> std::same_as<void>; \ + }; // clang-format on CREATE_HAS_FUNC(onTextChanged, nullptr, nullptr) @@ -139,7 +144,8 @@ CREATE_HAS_FUNC(setCursor, Qt::CursorShape()) CREATE_HAS_FUNC(setMinimumWidth, int()); CREATE_HAS_FUNC(setEnableCodeCopyButton, bool()); CREATE_HAS_FUNC(setDefaultAction, nullptr); -CREATE_HAS_FUNC(setRole, QtcButton::Role()); +CREATE_HAS_FUNC_NAMED(setRole, setRoleButton, QtcButton::Role()); +CREATE_HAS_FUNC_NAMED(setRole, setRoleLabel, QtcLabel::Role()); template<class T> void setProperties(std::unique_ptr<T> &item, const sol::table &children, QObject *guard) @@ -375,12 +381,17 @@ void setProperties(std::unique_ptr<T> &item, const sol::table &children, QObject if (openExternalLinks) item->setOpenExternalLinks(*openExternalLinks); } - if constexpr (has_setRole<T>) { + if constexpr (has_setRoleButton<T>) { sol::optional<QtcButton::Role> role = children.get<sol::optional<QtcButton::Role>>( "role"sv); if (role) item->setRole(*role); } + if constexpr (has_setRoleLabel<T>) { + sol::optional<QtcLabel::Role> role = children.get<sol::optional<QtcLabel::Role>>("role"sv); + if (role) + item->setRole(*role); + } } template<class T> @@ -579,7 +590,7 @@ void setupGuiModule() sol::base_classes, sol::bases<Widget, Object, Thing>()); - gui.new_usertype<Utils::QtcWidgets::Button>( + auto qtcButton = gui.new_usertype<Utils::QtcWidgets::Button>( "QtcButton", sol::call_constructor, sol::factories([](const sol::table &children) { @@ -609,6 +620,19 @@ void setupGuiModule() sol::base_classes, sol::bases<Widget, Object, Thing>()); + auto qtcLabel = gui.new_usertype<Utils::QtcWidgets::Label>( + "QtcLabel", + sol::call_constructor, + sol::factories([guard](const sol::table &children) { + return constructWidgetType<Utils::QtcWidgets::Label>(children, guard); + }), + "setText", + &Utils::QtcWidgets::Label::setText, + "setRole", + &Utils::QtcWidgets::Label::setRole, + sol::base_classes, + sol::bases<Widget, Object, Thing>()); + gui.new_usertype<Label>( "Label", sol::call_constructor, @@ -660,7 +684,8 @@ void setupGuiModule() mirrorEnum(gui, QMetaEnum::fromType<Qt::TextFormat>()); mirrorEnum(gui, QMetaEnum::fromType<Qt::TextInteractionFlag>()); mirrorEnum(gui, QMetaEnum::fromType<Qt::CursorShape>()); - mirrorEnum(gui, QMetaEnum::fromType<QtcButton::Role>()); + mirrorEnum(gui.get<sol::table>("QtcButton"), QMetaEnum::fromType<QtcButton::Role>()); + mirrorEnum(gui.get<sol::table>("QtcLabel"), QMetaEnum::fromType<QtcLabel::Role>()); auto sizePolicy = gui.create_named("QSizePolicy"); mirrorEnum(sizePolicy, QMetaEnum::fromType<QSizePolicy::Policy>()); diff --git a/src/plugins/lua/bindings/install.cpp b/src/plugins/lua/bindings/install.cpp index 434c5b2e91a..1fd163eec71 100644 --- a/src/plugins/lua/bindings/install.cpp +++ b/src/plugins/lua/bindings/install.cpp @@ -364,6 +364,8 @@ void setupInstallModule() InfoBarEntry entry(infoBarId, msg, InfoBarEntry::GlobalSuppression::Enabled); + entry.setInfoType(InfoLabel::Warning); + entry.addCustomButton( Tr::tr("Install"), [install]() { install(); }, diff --git a/src/plugins/lua/bindings/utils.h b/src/plugins/lua/bindings/utils.h index 13135e35ff4..3e6c7e05b29 100644 --- a/src/plugins/lua/bindings/utils.h +++ b/src/plugins/lua/bindings/utils.h @@ -43,12 +43,20 @@ inline std::shared_ptr<Utils::Icon> toIcon(const IconFilePathOrString &v) v); } +inline void mirrorEnum(sol::table &&target, QMetaEnum metaEnum, const QString &name = {}) +{ + sol::table luaEnumTable = target.create( + name.isEmpty() ? QString::fromUtf8(metaEnum.name()) : name, metaEnum.keyCount()); + for (int i = 0; i < metaEnum.keyCount(); ++i) + luaEnumTable.set(metaEnum.key(i), metaEnum.value(i)); +}; + inline void mirrorEnum(sol::table &target, QMetaEnum metaEnum, const QString &name = {}) { - sol::table widgetAttributes = target.create( + sol::table luaEnumTable = target.create( name.isEmpty() ? QString::fromUtf8(metaEnum.name()) : name, metaEnum.keyCount()); for (int i = 0; i < metaEnum.keyCount(); ++i) - widgetAttributes.set(metaEnum.key(i), metaEnum.value(i)); + luaEnumTable.set(metaEnum.key(i), metaEnum.value(i)); }; template <typename E> diff --git a/src/plugins/lua/meta/gui.lua b/src/plugins/lua/meta/gui.lua index 378d4370af6..05403022927 100644 --- a/src/plugins/lua/meta/gui.lua +++ b/src/plugins/lua/meta/gui.lua @@ -1,5 +1,4 @@ ---@meta Gui - local gui = {} ---The base class of all ui related classes. @@ -169,12 +168,30 @@ local pushButton = {} function gui.PushButton(options) end +---@class QtcLabel : Widget +local QtcLabel = {} + +---Enum representing the QtcLabel types +---@enum QtcLabel.Role +QtcLabel.Role = { + Primary = 0, + Secondary = 0, +} + +---@class QtcLabelOptions : BaseWidgetOptions +---@field role? QtcLabel.Role e The role of the label. (default: "Primary") +---@field text? string The text of the label. + +---@param options QtcLabelOptions +---@return QtcLabel +function gui.QtcLabel(options) end + ---@class QtcButton : Widget local QtcButton = {} ---- Enum representing text format types ----@enum Role -gui.Role = { +--- Enum representing the QtcButton roles +---@enum QtcButton.Role +QtcButton.Role = { LargePrimary = 0, LargeSecondary = 0, LargeTertiary = 0, @@ -187,7 +204,7 @@ gui.Role = { } ---@class QtcButtonOptions : BaseWidgetOptions ----@field role? Role The role of the button. (default: "LargePrimary") +---@field role? QtcButton.Role The role of the button. (default: "LargePrimary") ---@field text? string The text of the button. ---@field icon? IconFilePathOrString The icon of the button. diff --git a/src/plugins/mcusupport/mcukitmanager.cpp b/src/plugins/mcusupport/mcukitmanager.cpp index 68aa123b3f2..2894bd678d3 100644 --- a/src/plugins/mcusupport/mcukitmanager.cpp +++ b/src/plugins/mcusupport/mcukitmanager.cpp @@ -507,12 +507,14 @@ static void askUserAboutMcuSupportKitsUpgrade(const SettingsHandler::Ptr &settin { const char upgradeMcuSupportKits[] = "UpgradeMcuSupportKits"; - if (!ICore::infoBar()->canInfoBeAdded(upgradeMcuSupportKits)) + InfoBar *infoBar = ICore::infoBar(); + if (!infoBar->canInfoBeAdded(upgradeMcuSupportKits)) return; InfoBarEntry info(upgradeMcuSupportKits, Tr::tr("New version of Qt for MCUs detected. Upgrade existing kits?"), InfoBarEntry::GlobalSuppression::Enabled); + info.setInfoType(InfoLabel::Information); using McuKitManager::UpgradeOption; static UpgradeOption selectedOption = UpgradeOption::Keep; @@ -534,7 +536,7 @@ static void askUserAboutMcuSupportKitsUpgrade(const SettingsHandler::Ptr &settin {}, InfoBarEntry::ButtonAction::Hide); - ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } void createAutomaticKits(const SettingsHandler::Ptr &settingsHandler) diff --git a/src/plugins/mcusupport/mcusupportoptions.cpp b/src/plugins/mcusupport/mcusupportoptions.cpp index 2c5118df247..8f93b841d35 100644 --- a/src/plugins/mcusupport/mcusupportoptions.cpp +++ b/src/plugins/mcusupport/mcusupportoptions.cpp @@ -261,7 +261,8 @@ void McuSupportOptions::displayKitCreationMessages(const MessagesList messages, if (messages.isEmpty() || !qtMCUsPackage->isValidStatus()) return; static const char mcuKitCreationErrorInfoId[] = "ErrorWhileCreatingMCUKits"; - if (!Core::ICore::infoBar()->canInfoBeAdded(mcuKitCreationErrorInfoId)) + InfoBar *infoBar = Core::ICore::infoBar(); + if (!infoBar->canInfoBeAdded(mcuKitCreationErrorInfoId)) return; Utils::InfoBarEntry info(mcuKitCreationErrorInfoId, @@ -278,7 +279,7 @@ void McuSupportOptions::displayKitCreationMessages(const MessagesList messages, {}, InfoBarEntry::ButtonAction::Hide); - Core::ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } void McuSupportOptions::checkUpgradeableKits() diff --git a/src/plugins/mcusupport/mcusupportplugin.cpp b/src/plugins/mcusupport/mcusupportplugin.cpp index 0dba35bd245..c40a2797e03 100644 --- a/src/plugins/mcusupport/mcusupportplugin.cpp +++ b/src/plugins/mcusupport/mcusupportplugin.cpp @@ -123,7 +123,8 @@ static bool isQtMCUsProject(ProjectExplorer::Project *p) static void askUserAboutMcuSupportKitsSetup() { - if (!ICore::infoBar()->canInfoBeAdded(setupMcuSupportKits) + InfoBar *infoBar = ICore::infoBar(); + if (!infoBar->canInfoBeAdded(setupMcuSupportKits) || dd->m_options.qulDirFromSettings().isEmpty() || !McuKitManager::existingKits(nullptr).isEmpty()) return; @@ -138,7 +139,7 @@ static void askUserAboutMcuSupportKitsSetup() [] { QTimer::singleShot(0, []() { ICore::showOptionsDialog(Constants::SETTINGS_ID); }); }, {}, InfoBarEntry::ButtonAction::Hide); - ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } static void askUserAboutRemovingUninstalledTargetsKits() @@ -146,7 +147,8 @@ static void askUserAboutRemovingUninstalledTargetsKits() const char removeUninstalledKits[] = "RemoveUninstalledKits"; QList<Kit *> uninstalledTargetsKits; - if (!ICore::infoBar()->canInfoBeAdded(removeUninstalledKits) + InfoBar *infoBar = ICore::infoBar(); + if (!infoBar->canInfoBeAdded(removeUninstalledKits) || (uninstalledTargetsKits = McuKitManager::findUninstalledTargetsKits()).isEmpty()) return; @@ -169,7 +171,7 @@ static void askUserAboutRemovingUninstalledTargetsKits() {}, InfoBarEntry::ButtonAction::Hide); - ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } class McuSupportPlugin final : public ExtensionSystem::IPlugin @@ -241,7 +243,8 @@ void McuSupportPlugin::initialize() connect(ProjectManager::instance(), &ProjectManager::projectFinishedParsing, [&](ProjectExplorer::Project *p) { - if (!isQtMCUsProject(p) || !ICore::infoBar()->canInfoBeAdded(qdsMcuDocInfoEntry)) + InfoBar *infoBar = ICore::infoBar(); + if (!isQtMCUsProject(p) || !infoBar->canInfoBeAdded(qdsMcuDocInfoEntry)) return; Utils::InfoBarEntry docInfo( qdsMcuDocInfoEntry, @@ -255,7 +258,7 @@ void McuSupportPlugin::initialize() }, {}, InfoBarEntry::ButtonAction::Suppress); - ICore::infoBar()->addInfo(docInfo); + infoBar->addInfo(docInfo); }); } diff --git a/src/plugins/perforce/perforceplugin.cpp b/src/plugins/perforce/perforceplugin.cpp index 4779c06d23a..2643747cc6c 100644 --- a/src/plugins/perforce/perforceplugin.cpp +++ b/src/plugins/perforce/perforceplugin.cpp @@ -238,7 +238,7 @@ public: IEditor *showOutputInEditor(const QString &title, const QString &output, Id id, const FilePath &source, - const QByteArray &codec = {}); + const TextCodec &codec = {}); // args are passed as command line arguments // extra args via a tempfile and the option -x "temp-filename" @@ -247,13 +247,13 @@ public: unsigned flags = CommandToWindow|StdErrToWindow|ErrorToWindow, const QStringList &extraArgs = {}, const QByteArray &stdInput = {}, - const QByteArray &outputCodec = {}) const; + const Utils::TextCodec &outputCodec = {}) const; PerforceResponse synchronousProcess(const FilePath &workingDir, const QStringList &args, unsigned flags, const QByteArray &stdInput, - const QByteArray &outputCodec) const; + const Utils::TextCodec &outputCodec) const; void annotate(const FilePath &workingDir, const QString &fileName, const QString &changeList = QString(), int lineNumber = -1); @@ -547,7 +547,7 @@ void PerforcePluginPrivate::revertCurrentFile() const VcsBasePluginState state = currentState(); QTC_ASSERT(state.hasFile(), return); - const QByteArray codec = VcsBaseEditor::getCodec(state.currentFile()); + const TextCodec codec = VcsBaseEditor::getCodec(state.currentFile()); QStringList args; args << QLatin1String("diff") << QLatin1String("-sa") << state.relativeCurrentFile(); PerforceResponse result = runP4Cmd(state.currentFileTopLevel(), args, @@ -796,7 +796,7 @@ void PerforcePluginPrivate::annotate(const FilePath &workingDir, int lineNumber /* = -1 */) { const QStringList files = QStringList(fileName); - const QByteArray codec = VcsBaseEditor::getCodec(workingDir, files); + const TextCodec codec = VcsBaseEditor::getCodec(workingDir, files); const QString id = VcsBaseEditor::getTitleId(workingDir, files, changeList); const FilePath source = VcsBaseEditor::getSource(workingDir, files); QStringList args; @@ -850,7 +850,7 @@ void PerforcePluginPrivate::filelog(const FilePath &workingDir, const QString &f bool enableAnnotationContextMenu) { const QString id = VcsBaseEditor::getTitleId(workingDir, QStringList(fileName)); - const QByteArray codec = VcsBaseEditor::getCodec(workingDir, QStringList(fileName)); + const TextCodec codec = VcsBaseEditor::getCodec(workingDir, QStringList(fileName)); QStringList args; args << QLatin1String("filelog") << QLatin1String("-li"); if (settings().logCount() > 0) @@ -872,7 +872,7 @@ void PerforcePluginPrivate::filelog(const FilePath &workingDir, const QString &f void PerforcePluginPrivate::changelists(const FilePath &workingDir, const QString &fileName) { const QString id = VcsBaseEditor::getTitleId(workingDir, QStringList(fileName)); - const QByteArray codec = VcsBaseEditor::getCodec(workingDir, QStringList(fileName)); + const TextCodec codec = VcsBaseEditor::getCodec(workingDir, QStringList(fileName)); QStringList args; args << QLatin1String("changelists") << QLatin1String("-lit"); if (settings().logCount() > 0) @@ -1161,13 +1161,13 @@ PerforceResponse PerforcePluginPrivate::synchronousProcess(const FilePath &worki const QStringList &args, unsigned flags, const QByteArray &stdInput, - const QByteArray &outputCodec) const + const TextCodec &outputCodec) const { // Run, connect stderr to the output window Process process; process.setWriteData(stdInput); const int timeOutS = (flags & LongTimeOut) ? settings().longTimeOutS() : settings().timeOutS(); - if (!outputCodec.isEmpty()) + if (outputCodec.isValid()) process.setCodec(outputCodec); if (flags & OverrideDiffEnvironment) process.setEnvironment(overrideDiffEnvironmentVariable()); @@ -1209,7 +1209,7 @@ PerforceResponse PerforcePluginPrivate::runP4Cmd(const FilePath &workingDir, unsigned flags, const QStringList &extraArgs, const QByteArray &stdInput, - const QByteArray &outputCodec) const + const TextCodec &outputCodec) const { if (!settings().isValid()) { VcsOutputWindow::appendError(Tr::tr("Perforce is not correctly configured.")); @@ -1243,7 +1243,7 @@ IEditor *PerforcePluginPrivate::showOutputInEditor(const QString &title, const QString &output, Id id, const FilePath &source, - const QByteArray &codec) + const TextCodec &codec) { QString s = title; QString content = output; @@ -1263,7 +1263,7 @@ IEditor *PerforcePluginPrivate::showOutputInEditor(const QString &title, e->setSource(source); s.replace(QLatin1Char(' '), QLatin1Char('_')); e->textDocument()->setFallbackSaveAsFileName(s); - if (!codec.isEmpty()) + if (codec.isValid()) e->setCodec(codec); return editor; } @@ -1337,7 +1337,7 @@ void PerforcePluginPrivate::p4Diff(const FilePath &workingDir, const QStringList void PerforcePluginPrivate::p4Diff(const PerforceDiffParameters &p) { - const QByteArray codec = VcsBaseEditor::getCodec(p.workingDir, p.files); + const TextCodec codec = VcsBaseEditor::getCodec(p.workingDir, p.files); const QString id = VcsBaseEditor::getTitleId(p.workingDir, p.files); // Reuse existing editors for that id const QString tag = VcsBaseEditor::editorTag(DiffOutput, p.workingDir, p.files); @@ -1381,7 +1381,7 @@ void PerforcePluginPrivate::p4Diff(const PerforceDiffParameters &p) void PerforcePluginPrivate::vcsDescribe(const FilePath &source, const QString &n) { - const QByteArray codec = source.isEmpty() ? QByteArray() : VcsBaseEditor::getCodec(source); + const TextCodec codec = source.isEmpty() ? TextCodec() : VcsBaseEditor::getCodec(source); QStringList args; args << QLatin1String("describe") << QLatin1String("-du") << n; const PerforceResponse result = runP4Cmd(settings().topLevel(), args, CommandToWindow|StdErrToWindow|ErrorToWindow, diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp index 6b30fa44606..2f01446fb63 100644 --- a/src/plugins/projectexplorer/allprojectsfind.cpp +++ b/src/plugins/projectexplorer/allprojectsfind.cpp @@ -63,15 +63,15 @@ FileContainer AllProjectsFind::filesForProjects(const QStringList &nameFilters, QMap<FilePath, QTextCodec *> encodings; for (const Project *project : projects) { const EditorConfiguration *config = project->editorConfiguration(); - QByteArray projectCodec = config->useGlobalSettings() - ? Core::EditorManager::defaultTextCodecName() + TextCodec projectCodec = config->useGlobalSettings() + ? Core::EditorManager::defaultTextCodec() : config->textCodec(); const FilePaths filteredFiles = filterFiles(project->files(Project::SourceFiles)); for (const FilePath &fileName : filteredFiles) { - QByteArray codec = openEditorEncodings.value(fileName); - if (codec.isEmpty()) + TextCodec codec = TextCodec::codecForName(openEditorEncodings.value(fileName)); + if (!codec.isValid()) codec = projectCodec; - encodings.insert(fileName, QTextCodec::codecForName(codec)); + encodings.insert(fileName, codec.asQTextCodec()); } } return FileListContainer(encodings.keys(), encodings.values()); diff --git a/src/plugins/projectexplorer/customparserssettingspage.cpp b/src/plugins/projectexplorer/customparserssettingspage.cpp index f64b9938893..b3ea4efaff0 100644 --- a/src/plugins/projectexplorer/customparserssettingspage.cpp +++ b/src/plugins/projectexplorer/customparserssettingspage.cpp @@ -213,7 +213,7 @@ Qt::ItemFlags CustomParsersModel::flags(const QModelIndex &index) const if (!index.isValid()) return Qt::NoItemFlags; - Qt::ItemFlags flags = Qt::ItemIsEnabled; + Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if (index.column() > 0) flags |= Qt::ItemIsUserCheckable; diff --git a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp index 94ff92ac4aa..6e42d694f4d 100644 --- a/src/plugins/projectexplorer/devicesupport/devicemanager.cpp +++ b/src/plugins/projectexplorer/devicesupport/devicemanager.cpp @@ -411,6 +411,7 @@ DeviceManager::~DeviceManager() { delete d->writer; m_instance = nullptr; + d.reset(); } IDevice::Ptr DeviceManager::deviceAt(int idx) diff --git a/src/plugins/projectexplorer/editorconfiguration.cpp b/src/plugins/projectexplorer/editorconfiguration.cpp index 00bd0fb2860..550eda15b5f 100644 --- a/src/plugins/projectexplorer/editorconfiguration.cpp +++ b/src/plugins/projectexplorer/editorconfiguration.cpp @@ -44,7 +44,7 @@ struct EditorConfigurationPrivate m_storageSettings(globalStorageSettings()), m_behaviorSettings(globalBehaviorSettings()), m_extraEncodingSettings(globalExtraEncodingSettings()), - m_textCodec(Core::EditorManager::defaultTextCodecName()) + m_textCodec(Core::EditorManager::defaultTextCodec()) { } ICodeStylePreferences *m_defaultCodeStyle = nullptr; @@ -54,7 +54,7 @@ struct EditorConfigurationPrivate bool m_useGlobal = true; ExtraEncodingSettings m_extraEncodingSettings; MarginSettings m_marginSettings; - QByteArray m_textCodec; + TextCodec m_textCodec; QMap<Utils::Id, ICodeStylePreferences *> m_languageCodeStylePreferences; QList<Core::IEditor *> m_editors; @@ -110,10 +110,10 @@ void EditorConfiguration::cloneGlobalSettings() setBehaviorSettings(globalBehaviorSettings()); setExtraEncodingSettings(globalExtraEncodingSettings()); setMarginSettings(TextEditorSettings::marginSettings()); - d->m_textCodec = Core::EditorManager::defaultTextCodecName(); + d->m_textCodec = Core::EditorManager::defaultTextCodec(); } -QByteArray EditorConfiguration::textCodec() const +TextCodec EditorConfiguration::textCodec() const { return d->m_textCodec; } @@ -168,7 +168,7 @@ Store EditorConfiguration::toMap() const { Store map = { {kUseGlobal, d->m_useGlobal}, - {kCodec, d->m_textCodec}, + {kCodec, d->m_textCodec.name()}, {kCodeStyleCount, d->m_languageCodeStylePreferences.count()} }; @@ -196,10 +196,10 @@ Store EditorConfiguration::toMap() const void EditorConfiguration::fromMap(const Store &map) { - const QByteArray &codecName = map.value(kCodec, d->m_textCodec).toByteArray(); - d->m_textCodec = codecName; - if (d->m_textCodec.isEmpty()) - d->m_textCodec = Core::EditorManager::defaultTextCodecName(); + const QByteArray codecName = map.value(kCodec, d->m_textCodec.name()).toByteArray(); + d->m_textCodec = TextCodec::codecForName(codecName); + if (!d->m_textCodec.isValid()) + d->m_textCodec = Core::EditorManager::defaultTextCodec(); const int codeStyleCount = map.value(kCodeStyleCount, 0).toInt(); for (int i = 0; i < codeStyleCount; ++i) { @@ -348,7 +348,7 @@ void EditorConfiguration::setMarginSettings(const MarginSettings &settings) } } -void EditorConfiguration::setTextCodec(const QByteArray &textCodec) +void EditorConfiguration::setTextCodec(const TextCodec &textCodec) { d->m_textCodec = textCodec; } diff --git a/src/plugins/projectexplorer/editorconfiguration.h b/src/plugins/projectexplorer/editorconfiguration.h index a6befe99946..387e26e3893 100644 --- a/src/plugins/projectexplorer/editorconfiguration.h +++ b/src/plugins/projectexplorer/editorconfiguration.h @@ -26,7 +26,11 @@ class MarginSettings; } // namespace TextEditor namespace Core { class IEditor; } -namespace Utils { class FilePath; } + +namespace Utils { +class FilePath; +class TextCodec; +}; namespace ProjectExplorer { @@ -46,7 +50,7 @@ public: void cloneGlobalSettings(); // The default codec is returned in the case the project doesn't override it. - QByteArray textCodec() const; + Utils::TextCodec textCodec() const; const TextEditor::TypingSettings &typingSettings() const; const TextEditor::StorageSettings &storageSettings() const; @@ -75,7 +79,7 @@ public: void setUseIndenter(bool onoff); void setWrapColumn(int column); - void setTextCodec(const QByteArray &textCodec); + void setTextCodec(const Utils::TextCodec &textCodec); void slotAboutToRemoveProject(ProjectExplorer::Project *project); diff --git a/src/plugins/projectexplorer/editorsettingspropertiespage.cpp b/src/plugins/projectexplorer/editorsettingspropertiespage.cpp index ba0e4936f91..e43e3bb0182 100644 --- a/src/plugins/projectexplorer/editorsettingspropertiespage.cpp +++ b/src/plugins/projectexplorer/editorsettingspropertiespage.cpp @@ -18,12 +18,12 @@ #include <texteditor/typingsettings.h> #include <utils/layoutbuilder.h> +#include <utils/textcodec.h> #include <QCheckBox> #include <QGroupBox> #include <QPushButton> #include <QSpinBox> -#include <QTextCodec> namespace ProjectExplorer::Internal { diff --git a/src/plugins/projectexplorer/filesinallprojectsfind.cpp b/src/plugins/projectexplorer/filesinallprojectsfind.cpp index 62ac4e48392..691b087fc82 100644 --- a/src/plugins/projectexplorer/filesinallprojectsfind.cpp +++ b/src/plugins/projectexplorer/filesinallprojectsfind.cpp @@ -57,7 +57,7 @@ FileContainerProvider FilesInAllProjectsFind::fileContainerProvider() const return p->projectFilePath().parentDir(); }); return SubDirFileContainer(FilePaths(dirs.constBegin(), dirs.constEnd()), nameFilters, - exclusionFilters, Core::EditorManager::defaultTextCodec()); + exclusionFilters, Core::EditorManager::defaultTextCodec().asQTextCodec()); }; } diff --git a/src/plugins/projectexplorer/projectwelcomepage.cpp b/src/plugins/projectexplorer/projectwelcomepage.cpp index 3de1e0eff32..5a65944efdf 100644 --- a/src/plugins/projectexplorer/projectwelcomepage.cpp +++ b/src/plugins/projectexplorer/projectwelcomepage.cpp @@ -346,7 +346,7 @@ public: m_rename = new QtcButton(Tr::tr("Rename"), QtcButton::SmallTertiary); m_delete = new QtcButton(Tr::tr("Delete"), QtcButton::SmallTertiary); - auto buttonGroup = new QButtonGroup; + auto buttonGroup = new QButtonGroup(this); buttonGroup->addButton(m_clone, ActionClone); buttonGroup->addButton(m_rename, ActionRename); buttonGroup->addButton(m_delete, ActionDelete); diff --git a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp index 2b335f8f43d..7aca556b072 100644 --- a/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeparsernodes.cpp @@ -903,7 +903,7 @@ bool QmakePriFile::setProVariable(const QString &var, const QStringList &values, void QmakePriFile::save(const QStringList &lines) { { - QTC_ASSERT(m_textFormat.codec(), return); + QTC_ASSERT(m_textFormat.codec().isValid(), return); FileChangeBlocker changeGuard(filePath()); if (const Result<> res = m_textFormat.writeFile(filePath(), lines.join('\n')); !res) QMessageBox::critical(Core::ICore::dialogParent(), Tr::tr("File Error"), res.error()); diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index 14053312a70..65533756206 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -315,7 +315,7 @@ void DocumentManager::goIntoComponent(const QString &fileName) bool DocumentManager::createFile(const QString &filePath, const QString &contents) { TextFileFormat textFileFormat; - textFileFormat.setCodecName(Core::EditorManager::defaultTextCodecName()); + textFileFormat.setCodec(Core::EditorManager::defaultTextCodec()); return textFileFormat.writeFile(FilePath::fromString(filePath), contents).has_value(); } diff --git a/src/plugins/qmljseditor/qmljseditordocument.cpp b/src/plugins/qmljseditor/qmljseditordocument.cpp index 5b78ae916f5..062fbc9b84d 100644 --- a/src/plugins/qmljseditor/qmljseditordocument.cpp +++ b/src/plugins/qmljseditor/qmljseditordocument.cpp @@ -742,13 +742,13 @@ QmlJSEditorDocument::QmlJSEditorDocument(Utils::Id id) connect(this, &TextEditor::TextDocument::tabSettingsChanged, d, &Internal::QmlJSEditorDocumentPrivate::invalidateFormatterCache); resetSyntaxHighlighter([] { return new QmlJSHighlighter(); }); - setCodec("UTF-8"); // qml files are defined to be utf-8 + setCodec(TextCodec::utf8()); // qml files are defined to be utf-8 setIndenter(createQmlJsIndenter(document())); } bool QmlJSEditorDocument::supportsCodec(const QByteArray &codec) const { - return TextEditor::TextDocument::isUtf8Codec(codec); + return TextCodec::isUtf8Codec(codec); } QmlJSEditorDocument::~QmlJSEditorDocument() diff --git a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp index 1535e9083b8..741b4a7eaed 100644 --- a/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp +++ b/src/plugins/qmlprojectmanager/buildsystem/qmlbuildsystem.cpp @@ -321,8 +321,9 @@ bool QmlBuildSystem::setFileSettingInProjectFile(const QString &setting, } TextFileFormat textFileFormat; - const QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // qml files are defined to be utf-8 - const TextFileFormat::ReadResult readResult = textFileFormat.readFile(qmlProjectFilePath, codec); + // qml files are defined to be utf-8 + const TextFileFormat::ReadResult readResult = + textFileFormat.readFile(qmlProjectFilePath, TextCodec::utf8()); if (readResult.code != TextFileFormat::ReadSuccess) qWarning() << "Failed to read file" << qmlProjectFilePath << ":" << readResult.error; @@ -482,8 +483,9 @@ bool QmlBuildSystem::setMainUiFileInMainFile(const Utils::FilePath &newMainUiFil } TextFileFormat textFileFormat; - const QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // qml files are defined to be utf-8 - const TextFileFormat::ReadResult res = textFileFormat.readFile(mainFilePath(), codec); + // qml files are defined to be utf-8 + const TextFileFormat::ReadResult res = + textFileFormat.readFile(mainFilePath(), TextCodec::utf8()); if (res.code != TextFileFormat::ReadSuccess) qWarning() << "Failed to read file" << mainFilePath() << ":" << res.error; diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp index bd3c954644a..d302c351b7c 100644 --- a/src/plugins/qtsupport/qtsupportplugin.cpp +++ b/src/plugins/qtsupport/qtsupportplugin.cpp @@ -153,10 +153,11 @@ const char kLinkWithQtInstallationSetting[] = "LinkWithQtInstallation"; static void askAboutQtInstallation() { + InfoBar *infoBar = ICore::infoBar(); // if the install settings exist, the Qt Creator installation is (probably) already linked to // a Qt installation, so don't ask if (!LinkWithQtSupport::canLinkWithQt() || LinkWithQtSupport::isLinkedWithQt() - || !ICore::infoBar()->canInfoBeAdded(kLinkWithQtInstallationSetting)) + || !infoBar->canInfoBeAdded(kLinkWithQtInstallationSetting)) return; Utils::InfoBarEntry info( @@ -165,13 +166,14 @@ static void askAboutQtInstallation() "Link with a Qt installation to automatically register Qt versions and kits? To do " "this later, select Edit > Preferences > Kits > Qt Versions > Link with Qt."), Utils::InfoBarEntry::GlobalSuppression::Enabled); - info.setTitle(Tr::tr("Link with Qt")); + info.setTitle(Tr::tr("Link with an Installed Qt?")); + info.setInfoType(InfoLabel::Information); info.addCustomButton( Tr::tr("Link with Qt"), [] { QTimer::singleShot(0, ICore::dialogParent(), &LinkWithQtSupport::linkWithQt); }, {}, InfoBarEntry::ButtonAction::Hide); - ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } void QtSupportPlugin::extensionsInitialized() diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index d5f64683db1..1d76e4296f3 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -1233,7 +1233,10 @@ void LinuxDevicePrivate::announceConnectionAttempt() "This might take a moment.").arg(q->displayName()); qCDebug(linuxDeviceLog) << message; if (isMainThread()) { - Core::ICore::infoBar()->addInfo(InfoBarEntry(announceId(), message)); + InfoBarEntry info(announceId(), message); + info.setTitle(Tr::tr("Establishing a Connection")); + info.setInfoType(InfoLabel::Ok); + Core::ICore::infoBar()->addInfo(info); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); // Yes, twice. } @@ -1250,13 +1253,15 @@ bool LinuxDevicePrivate::checkDisconnectedWithWarning() if (!m_disconnected()) return false; - QMetaObject::invokeMethod(Core::ICore::infoBar(), [id = q->id(), name = q->displayName()] { + InfoBar *infoBar = Core::ICore::infoBar(); + QMetaObject::invokeMethod(infoBar, [id = q->id(), name = q->displayName(), infoBar] { const Id errorId = id.withPrefix("error_"); - if (!Core::ICore::infoBar()->canInfoBeAdded(errorId)) + if (!infoBar->canInfoBeAdded(errorId)) return; const QString warnStr = Tr::tr("Device \"%1\" is currently marked as disconnected.").arg(name); InfoBarEntry info(errorId, warnStr, InfoBarEntry::GlobalSuppression::Enabled); + info.setTitle(Tr::tr("Device is Disconnected")); info.setDetailsWidgetCreator([] { const auto label = new QLabel(Tr::tr( "The device was not available when trying to connect previously.<br>" @@ -1269,7 +1274,7 @@ bool LinuxDevicePrivate::checkDisconnectedWithWarning() }); return label; }); - Core::ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); }); return true; } diff --git a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp index e36d8b3b65e..800103a6668 100644 --- a/src/plugins/resourceeditor/qrceditor/resourcefile.cpp +++ b/src/plugins/resourceeditor/qrceditor/resourcefile.cpp @@ -111,9 +111,9 @@ Result<> ResourceFile::load() } QByteArray data = file.readAll(); // Detect line ending style - m_textFileFormat = TextFileFormat::detect(data); + m_textFileFormat.detectFromData(data); // we always write UTF-8 when saving - m_textFileFormat.setCodecName("UTF-8"); + m_textFileFormat.setCodec(TextCodec::utf8()); file.close(); QString error_msg; diff --git a/src/plugins/scxmleditor/scxmleditordocument.cpp b/src/plugins/scxmleditor/scxmleditordocument.cpp index 720d96bd2fd..4e9b5e4e976 100644 --- a/src/plugins/scxmleditor/scxmleditordocument.cpp +++ b/src/plugins/scxmleditor/scxmleditordocument.cpp @@ -29,7 +29,7 @@ ScxmlEditorDocument::ScxmlEditorDocument(MainWidget *designWidget, QObject *pare setId(Utils::Id(ScxmlEditor::Constants::K_SCXML_EDITOR_ID)); // Designer needs UTF-8 regardless of settings. - setCodec("UTF-8"); + setCodec(TextCodec::utf8()); connect(m_designWidget.data(), &Common::MainWidget::dirtyChanged, this, [this]{ emit changed(); }); @@ -122,7 +122,7 @@ Result<> ScxmlEditorDocument::reload(ReloadFlag flag, ChangeType type) bool ScxmlEditorDocument::supportsCodec(const QByteArray &codec) const { - return TextEditor::TextDocument::isUtf8Codec(codec); + return TextCodec::isUtf8Codec(codec); } QString ScxmlEditorDocument::designWidgetContents() const diff --git a/src/plugins/subversion/subversionplugin.cpp b/src/plugins/subversion/subversionplugin.cpp index 0bbc5208f8d..8fb89e6dbdd 100644 --- a/src/plugins/subversion/subversionplugin.cpp +++ b/src/plugins/subversion/subversionplugin.cpp @@ -85,11 +85,6 @@ const char CMD_ID_UPDATE[] = "Subversion.Update"; const char CMD_ID_COMMIT_PROJECT[] = "Subversion.CommitProject"; const char CMD_ID_DESCRIBE[] = "Subversion.Describe"; -static QByteArray debugCodec(const QByteArray &c) -{ - return !c.isEmpty() ? c : QByteArray("Null codec"); -} - // Parse "svn status" output for added/conflicted/deleted/modified files // "M<7blanks>file" using StatusList = QList<SubversionSubmitEditor::StatusFilePair>; @@ -170,7 +165,7 @@ public: QString monitorFile(const FilePath &repository) const; QString synchronousTopic(const FilePath &repository) const; CommandResult runSvn(const FilePath &workingDir, const CommandLine &command, - RunFlags flags = RunFlags::None, const QByteArray &outputCodec = {}, + RunFlags flags = RunFlags::None, const TextCodec &outputCodec = {}, int timeoutMutiplier = 1) const; void vcsAnnotateHelper(const FilePath &workingDir, const QString &file, const QString &revision = {}, int lineNumber = -1); @@ -205,7 +200,7 @@ private: inline bool isCommitEditorOpen() const; Core::IEditor *showOutputInEditor(const QString &title, const QString &output, Id id, const FilePath &source, - const QByteArray &codec); + const TextCodec &codec); void filelog(const FilePath &workingDir, const QString &file = {}, @@ -801,7 +796,7 @@ void SubversionPluginPrivate::svnUpdate(const FilePath &workingDir, const QStrin args << Constants::NON_INTERACTIVE_OPTION; if (!relativePath.isEmpty()) args << relativePath; - const auto response = runSvn(workingDir, args, RunFlags::ShowStdOut, nullptr, 10); + const auto response = runSvn(workingDir, args, RunFlags::ShowStdOut, {}, 10); if (response.result() == ProcessResult::FinishedWithSuccess) emit repositoryChanged(workingDir); } @@ -818,7 +813,7 @@ void SubversionPluginPrivate::vcsAnnotateHelper(const FilePath &workingDir, cons int lineNumber /* = -1 */) { const FilePath source = VcsBaseEditor::getSource(workingDir, file); - const QByteArray codec = VcsBaseEditor::getCodec(source); + const TextCodec codec = VcsBaseEditor::getCodec(source); CommandLine args{settings().binaryPath(), {"annotate"}}; args << SubversionClient::AddAuthOptions(); @@ -902,7 +897,7 @@ void SubversionPluginPrivate::slotDescribe() CommandResult SubversionPluginPrivate::runSvn(const FilePath &workingDir, const CommandLine &command, RunFlags flags, - const QByteArray &outputCodec, int timeoutMutiplier) const + const TextCodec &outputCodec, int timeoutMutiplier) const { if (settings().binaryPath().isEmpty()) return CommandResult(ProcessResult::StartFailed, Tr::tr("No subversion executable specified.")); @@ -913,11 +908,11 @@ CommandResult SubversionPluginPrivate::runSvn(const FilePath &workingDir, IEditor *SubversionPluginPrivate::showOutputInEditor(const QString &title, const QString &output, Id id, const FilePath &source, - const QByteArray &codec) + const TextCodec &codec) { if (Subversion::Constants::debug) qDebug() << "SubversionPlugin::showOutputInEditor" << title << id.toString() - << "Size= " << output.size() << " Type=" << id << debugCodec(codec); + << "Size= " << output.size() << " Type=" << id << codec.displayName(); QString s = title; IEditor *editor = EditorManager::openEditorWithContents(id, &s, output.toUtf8()); auto e = qobject_cast<SubversionEditorWidget*>(editor->widget()); @@ -930,7 +925,7 @@ IEditor *SubversionPluginPrivate::showOutputInEditor(const QString &title, const e->textDocument()->setFallbackSaveAsFileName(s); if (!source.isEmpty()) e->setSource(source); - if (!codec.isEmpty()) + if (codec.isValid()) e->setCodec(codec); return editor; } diff --git a/src/plugins/texteditor/behaviorsettingspage.cpp b/src/plugins/texteditor/behaviorsettingspage.cpp index a6883b8960f..eb2917aaccd 100644 --- a/src/plugins/texteditor/behaviorsettingspage.cpp +++ b/src/plugins/texteditor/behaviorsettingspage.cpp @@ -101,7 +101,7 @@ public: d->m_behaviorWidget->setAssignedStorageSettings(globalStorageSettings()); d->m_behaviorWidget->setAssignedBehaviorSettings(globalBehaviorSettings()); d->m_behaviorWidget->setAssignedExtraEncodingSettings(globalExtraEncodingSettings()); - d->m_behaviorWidget->setAssignedCodec(Core::EditorManager::defaultTextCodecName()); + d->m_behaviorWidget->setAssignedCodec(Core::EditorManager::defaultTextCodec()); d->m_behaviorWidget->setAssignedLineEnding(Core::EditorManager::defaultLineEnding()); } diff --git a/src/plugins/texteditor/behaviorsettingswidget.cpp b/src/plugins/texteditor/behaviorsettingswidget.cpp index 9fd1d49414a..65277fb7077 100644 --- a/src/plugins/texteditor/behaviorsettingswidget.cpp +++ b/src/plugins/texteditor/behaviorsettingswidget.cpp @@ -316,11 +316,11 @@ void BehaviorSettingsWidget::setActive(bool active) d->groupBoxStorageSettings->setEnabled(active); } -void BehaviorSettingsWidget::setAssignedCodec(const QByteArray &codec) +void BehaviorSettingsWidget::setAssignedCodec(const Utils::TextCodec &codec) { const QString codecName = Core::ICore::settings()->value( Core::Constants::SETTINGS_DEFAULTTEXTENCODING).toString(); - d->encodingBox->setAssignedCodec(QTextCodec::codecForName(codec), codecName); + d->encodingBox->setAssignedCodec(codec, codecName); } QByteArray BehaviorSettingsWidget::assignedCodecName() const diff --git a/src/plugins/texteditor/behaviorsettingswidget.h b/src/plugins/texteditor/behaviorsettingswidget.h index 03411c73fb0..7aace92f095 100644 --- a/src/plugins/texteditor/behaviorsettingswidget.h +++ b/src/plugins/texteditor/behaviorsettingswidget.h @@ -7,6 +7,8 @@ #include <QWidget> +#include <utils/textcodec.h> + namespace TextEditor { class ICodeStylePreferences; @@ -28,7 +30,7 @@ public: void setActive(bool active); - void setAssignedCodec(const QByteArray &codec); + void setAssignedCodec(const Utils::TextCodec &codec); QByteArray assignedCodecName() const; void setCodeStyle(ICodeStylePreferences *preferences); @@ -55,7 +57,7 @@ signals: void storageSettingsChanged(const TextEditor::StorageSettings &settings); void behaviorSettingsChanged(const TextEditor::BehaviorSettings &settings); void extraEncodingSettingsChanged(const TextEditor::ExtraEncodingSettings &settings); - void textCodecChanged(const QByteArray &codec); + void textCodecChanged(const Utils::TextCodec &codec); private: void slotTypingSettingsChanged(); diff --git a/src/plugins/texteditor/codecchooser.cpp b/src/plugins/texteditor/codecchooser.cpp index 4a7e0196e27..88928d6228b 100644 --- a/src/plugins/texteditor/codecchooser.cpp +++ b/src/plugins/texteditor/codecchooser.cpp @@ -7,6 +7,10 @@ #include <QTextCodec> +using namespace Utils; + +namespace TextEditor { + static bool isSingleByte(int mib) { // Encodings are listed at https://www.iana.org/assignments/character-sets/character-sets.xhtml @@ -18,8 +22,6 @@ static bool isSingleByte(int mib) || (mib >= 2106); } -namespace TextEditor { - CodecChooser::CodecChooser(Filter filter) { QList<int> mibs = Utils::sorted(QTextCodec::availableMibs()); @@ -30,14 +32,8 @@ CodecChooser::CodecChooser(Filter filter) for (int mib : std::as_const(mibs)) { if (filter == Filter::SingleByte && !isSingleByte(mib)) continue; - if (QTextCodec *codec = QTextCodec::codecForMib(mib)) { - QString compoundName = QLatin1String(codec->name()); - const QList<QByteArray> aliases = codec->aliases(); - for (const QByteArray &alias : aliases) { - compoundName += QLatin1String(" / "); - compoundName += QString::fromLatin1(alias); - } - addItem(compoundName); + if (const TextCodec codec = TextCodec::codecForMib(mib); codec.isValid()) { + addItem(codec.fullDisplayName()); m_codecs.append(codec); } } @@ -48,22 +44,22 @@ CodecChooser::CodecChooser(Filter filter) void CodecChooser::prependNone() { insertItem(0, "None"); - m_codecs.prepend(nullptr); + m_codecs.prepend({}); } -QByteArray CodecChooser::currentCodec() const +TextCodec CodecChooser::currentCodec() const { return codecAt(currentIndex()); } -QByteArray CodecChooser::codecAt(int index) const +TextCodec CodecChooser::codecAt(int index) const { if (index < 0) index = 0; - return m_codecs[index] ? m_codecs[index]->name() : QByteArray(); + return m_codecs[index].isValid() ? m_codecs[index] : TextCodec(); } -void CodecChooser::setAssignedCodec(QTextCodec *codec, const QString &name) +void CodecChooser::setAssignedCodec(const TextCodec &codec, const QString &name) { int rememberedSystemPosition = -1; for (int i = 0, total = m_codecs.size(); i < total; ++i) { @@ -85,7 +81,7 @@ QByteArray CodecChooser::assignedCodecName() const const int index = currentIndex(); return index == 0 ? QByteArray("System") // we prepend System to the available codecs - : m_codecs.at(index)->name(); + : m_codecs.at(index).name(); } } // TextEditor diff --git a/src/plugins/texteditor/codecchooser.h b/src/plugins/texteditor/codecchooser.h index a1e33366d18..c0840da48b2 100644 --- a/src/plugins/texteditor/codecchooser.h +++ b/src/plugins/texteditor/codecchooser.h @@ -5,11 +5,9 @@ #include "texteditor_global.h" -#include <QComboBox> +#include <utils/textcodec.h> -QT_BEGIN_NAMESPACE -class QTextCodec; -QT_END_NAMESPACE +#include <QComboBox> namespace TextEditor { @@ -19,18 +17,20 @@ class TEXTEDITOR_EXPORT CodecChooser : public QComboBox public: enum class Filter { All, SingleByte }; + explicit CodecChooser(Filter filter = Filter::All); + void prependNone(); - QByteArray currentCodec() const; - void setAssignedCodec(QTextCodec *codec, const QString &name = {}); + Utils::TextCodec currentCodec() const; + void setAssignedCodec(const Utils::TextCodec &codec, const QString &name = {}); QByteArray assignedCodecName() const; signals: - void codecChanged(const QByteArray &codec); + void codecChanged(const Utils::TextCodec &codec); private: - QByteArray codecAt(int index) const; - QList<QTextCodec *> m_codecs; + Utils::TextCodec codecAt(int index) const; + QList<Utils::TextCodec> m_codecs; }; } // namespace TextEditor diff --git a/src/plugins/texteditor/findincurrentfile.cpp b/src/plugins/texteditor/findincurrentfile.cpp index 622ce4df691..639f567efd2 100644 --- a/src/plugins/texteditor/findincurrentfile.cpp +++ b/src/plugins/texteditor/findincurrentfile.cpp @@ -72,7 +72,7 @@ FileContainerProvider FindInCurrentFile::fileContainerProvider() const const QMap<FilePath, QByteArray> encodings = TextDocument::openedTextDocumentEncodings(); QByteArray codec = encodings.value(fileName); if (codec.isEmpty()) - codec = Core::EditorManager::defaultTextCodecName(); + codec = Core::EditorManager::defaultTextCodec().name(); return FileListContainer({fileName}, {QTextCodec::codecForName(codec)}); }; } diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp index 559cc8ef34c..c86a1c454aa 100644 --- a/src/plugins/texteditor/findinfiles.cpp +++ b/src/plugins/texteditor/findinfiles.cpp @@ -53,7 +53,7 @@ FileContainerProvider FindInFiles::fileContainerProvider() const return [nameFilters = fileNameFilters(), exclusionFilters = fileExclusionFilters(), filePath = searchDir()] { return SubDirFileContainer({filePath}, nameFilters, exclusionFilters, - EditorManager::defaultTextCodec()); + EditorManager::defaultTextCodec().asQTextCodec()); }; } diff --git a/src/plugins/texteditor/findinopenfiles.cpp b/src/plugins/texteditor/findinopenfiles.cpp index 6f26f2c4f64..4c6d0070f77 100644 --- a/src/plugins/texteditor/findinopenfiles.cpp +++ b/src/plugins/texteditor/findinopenfiles.cpp @@ -72,7 +72,7 @@ FileContainerProvider FindInOpenFiles::fileContainerProvider() const fileNames.append(fileName); QByteArray codec = encodings.value(fileName); if (codec.isEmpty()) - codec = Core::EditorManager::defaultTextCodecName(); + codec = Core::EditorManager::defaultTextCodec().name(); codecs.append(QTextCodec::codecForName(codec)); } } diff --git a/src/plugins/texteditor/refactoringchanges.cpp b/src/plugins/texteditor/refactoringchanges.cpp index 7f87d16e602..f295b04091f 100644 --- a/src/plugins/texteditor/refactoringchanges.cpp +++ b/src/plugins/texteditor/refactoringchanges.cpp @@ -72,7 +72,7 @@ bool RefactoringFile::create(const QString &contents, bool reindent, bool openIn // Write the file to disk: TextFileFormat format; - format.setCodecName(EditorManager::defaultTextCodecName()); + format.setCodec(EditorManager::defaultTextCodec()); const Result<> saveOk = format.writeFile(m_filePath, m_document->toPlainText()); delete m_document; m_document = nullptr; @@ -114,7 +114,7 @@ QTextDocument *RefactoringFile::mutableDocument() const result = m_textFileFormat.readFile(m_filePath, EditorManager::defaultTextCodec()); if (result.code != TextFileFormat::ReadSuccess) { qWarning() << "Could not read " << m_filePath << ". Error: " << result.error; - m_textFileFormat.setCodec(nullptr); + m_textFileFormat.setCodec({}); } } // always make a QTextDocument to avoid excessive null checks @@ -257,7 +257,7 @@ bool RefactoringFile::apply() c.endEditBlock(); // if this document doesn't have an editor, write the result to a file - if (!m_editor && m_textFileFormat.codec()) { + if (!m_editor && m_textFileFormat.codec().isValid()) { QTC_ASSERT(!m_filePath.isEmpty(), return false); // suppress "file has changed" warnings if the file is open in a read-only editor Core::FileChangeBlocker block(m_filePath); diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index 3a5ff178394..5f900504cbf 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -38,7 +38,6 @@ #include <QFutureInterface> #include <QScrollBar> #include <QStringList> -#include <QTextCodec> using namespace Core; using namespace Utils; @@ -281,7 +280,7 @@ QMap<FilePath, QByteArray> TextDocument::openedTextDocumentEncodings() if (!textEditorDocument) continue; const FilePath fileName = textEditorDocument->filePath(); - workingCopy[fileName] = textEditorDocument->codecName(); + workingCopy[fileName] = textEditorDocument->codec().name(); } return workingCopy; } @@ -671,8 +670,8 @@ Result<> TextDocument::saveImpl(const FilePath &filePath, bool autoSave) } // check if UTF8-BOM has to be added or removed - Utils::TextFileFormat saveFormat = format(); - if (saveFormat.codecName() == "UTF-8" && supportsUtf8Bom()) { + TextFileFormat saveFormat = format(); + if (saveFormat.codec().isUtf8() && supportsUtf8Bom()) { switch (d->m_extraEncodingSettings.m_utf8BomSetting) { case ExtraEncodingSettings::AlwaysAdd: saveFormat.hasUtf8Bom = true; @@ -830,9 +829,9 @@ Result<> TextDocument::openImpl(const FilePath &filePath, return ResultOk; } -Result<> TextDocument::reload(const QByteArray &codec) +Result<> TextDocument::reload(const TextCodec &codec) { - QTC_ASSERT(!codec.isEmpty(), return ResultError("No codec given")); + QTC_ASSERT(codec.isValid(), return ResultError("No codec given")); setCodec(codec); return reload(); } diff --git a/src/plugins/texteditor/textdocument.h b/src/plugins/texteditor/textdocument.h index 2d6b0d9c556..9477a7df315 100644 --- a/src/plugins/texteditor/textdocument.h +++ b/src/plugins/texteditor/textdocument.h @@ -129,7 +129,7 @@ public: void resetSyntaxHighlighter(const SyntaxHighLighterCreator &creator); SyntaxHighlighter *syntaxHighlighter() const; - Utils::Result<> reload(const QByteArray &codec); + Utils::Result<> reload(const Utils::TextCodec &codec); void cleanWhitespace(const QTextCursor &cursor); virtual void triggerPendingUpdates(); diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index cd1aaa723cb..5f13a540cd0 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -2054,7 +2054,7 @@ void TextEditorWidget::updateTextLineEndingLabel() void TextEditorWidget::updateTextCodecLabel() { - QString text = QString::fromLatin1(d->m_document->codec()->name()); + QString text = QString::fromLatin1(d->m_document->codec().name()); d->m_fileEncodingButton->setText(text); } @@ -2097,7 +2097,7 @@ void TextEditorWidgetPrivate::updateCannotDecodeInfo() return; InfoBarEntry info(selectEncodingId, Tr::tr("<b>Error:</b> Could not decode \"%1\" with \"%2\"-encoding. Editing not possible.") - .arg(m_document->displayName(), QString::fromLatin1(m_document->codec()->name()))); + .arg(m_document->displayName(), m_document->codec().displayName())); info.addCustomButton(Tr::tr("Select Encoding"), [this] { q->selectEncoding(); }); infoBar->addInfo(info); } else { @@ -9804,7 +9804,7 @@ void TextEditorWidget::appendStandardContextMenuActions(QMenu *menu) if (Command *bomCmd = ActionManager::command(Constants::SWITCH_UTF8BOM)) { QAction *a = bomCmd->action(); TextDocument *doc = textDocument(); - if (doc->codec()->name() == QByteArray("UTF-8") && doc->supportsUtf8Bom()) { + if (doc->codec().isUtf8() && doc->supportsUtf8Bom()) { a->setVisible(true); a->setText(doc->format().hasUtf8Bom ? Tr::tr("Delete UTF-8 BOM on Save") : Tr::tr("Add UTF-8 BOM on Save")); diff --git a/src/plugins/updateinfo/updateinfoplugin.cpp b/src/plugins/updateinfo/updateinfoplugin.cpp index 0a7e29a4fba..fca2185a1cd 100644 --- a/src/plugins/updateinfo/updateinfoplugin.cpp +++ b/src/plugins/updateinfo/updateinfoplugin.cpp @@ -194,6 +194,7 @@ static void showUpdateInfo(const QList<Update> &updates, { InfoBarEntry info(InstallUpdates, infoTitle(updates, newQt)); info.setTitle(Tr::tr("Updates Available")); + info.setInfoType(InfoLabel::Information); info.addCustomButton( Tr::tr("Open Settings"), [] { ICore::showOptionsDialog(FILTER_OPTIONS_PAGE_ID); }, @@ -235,9 +236,10 @@ static void showUpdateInfo(const QList<Update> &updates, return scrollArea; }); } - ICore::infoBar()->removeInfo(InstallUpdates); // remove any existing notifications - ICore::infoBar()->unsuppressInfo(InstallUpdates); - ICore::infoBar()->addInfo(info); + InfoBar *infoBar = ICore::infoBar(); + infoBar->removeInfo(InstallUpdates); // remove any existing notifications + infoBar->unsuppressInfo(InstallUpdates); + infoBar->addInfo(info); } void UpdateInfoPlugin::checkForUpdatesFinished() diff --git a/src/plugins/vcpkg/vcpkgmanifesteditor.cpp b/src/plugins/vcpkg/vcpkgmanifesteditor.cpp index 4e090b272c5..fa26b02b159 100644 --- a/src/plugins/vcpkg/vcpkgmanifesteditor.cpp +++ b/src/plugins/vcpkg/vcpkgmanifesteditor.cpp @@ -43,7 +43,7 @@ static QString cmakeCodeForPackage(const QString &package) Project *currentProject = ProjectTree::currentProject(); const FilePath usageFile = - settings(currentProject).vcpkgRoot.expandedValue() / "ports" / package / "usage"; + settings(currentProject)->vcpkgRoot.expandedValue() / "ports" / package / "usage"; if (usageFile.exists()) { if (const Result<QByteArray> res = usageFile.fileContents()) result = QString::fromUtf8(*res); @@ -123,14 +123,14 @@ public: }); updateToolBar(); - connect(&settings(ProjectTree::currentProject()).vcpkgRoot, &Utils::BaseAspect::changed, + connect(&settings(ProjectTree::currentProject())->vcpkgRoot, &Utils::BaseAspect::changed, this, &VcpkgManifestEditorWidget::updateToolBar); } void updateToolBar() { Utils::FilePath vcpkgRoot = - settings(ProjectTree::currentProject()).vcpkgRoot.expandedValue(); + settings(ProjectTree::currentProject())->vcpkgRoot.expandedValue(); Utils::FilePath vcpkg = vcpkgRoot.pathAppended("vcpkg").withExecutableSuffix(); const bool vcpkgEncabled = vcpkg.isExecutableFile(); m_searchPkgAction->setEnabled(vcpkgEncabled); diff --git a/src/plugins/vcpkg/vcpkgplugin.cpp b/src/plugins/vcpkg/vcpkgplugin.cpp index 9bd8031b6af..5dc1609c733 100644 --- a/src/plugins/vcpkg/vcpkgplugin.cpp +++ b/src/plugins/vcpkg/vcpkgplugin.cpp @@ -34,13 +34,13 @@ public: void extensionsInitialized() final { - settings(nullptr).setVcpkgRootEnvironmentVariable(); + settings(nullptr)->setVcpkgRootEnvironmentVariable(); connect( ProjectManager::instance(), &ProjectManager::startupProjectChanged, this, - [](Project *project) { settings(project).setVcpkgRootEnvironmentVariable(); }); + [](Project *project) { settings(project)->setVcpkgRootEnvironmentVariable(); }); } }; diff --git a/src/plugins/vcpkg/vcpkgsearch.cpp b/src/plugins/vcpkg/vcpkgsearch.cpp index ac25677841f..e84ba5a1526 100644 --- a/src/plugins/vcpkg/vcpkgsearch.cpp +++ b/src/plugins/vcpkg/vcpkgsearch.cpp @@ -209,7 +209,7 @@ void VcpkgPackageSearchDialog::updatePackages() AsyncTask<VcpkgManifest>{ [](Async<VcpkgManifest> &task) { FilePath vcpkgRoot = - settings(ProjectTree::currentProject()).vcpkgRoot.expandedValue(); + settings(ProjectTree::currentProject())->vcpkgRoot.expandedValue(); task.setConcurrentCallData(vcpkgManifests, vcpkgRoot); }, [this](const Async<VcpkgManifest> &task) { m_allPackages = task.results(); } diff --git a/src/plugins/vcpkg/vcpkgsettings.cpp b/src/plugins/vcpkg/vcpkgsettings.cpp index ee3267935f3..6ff135f78c8 100644 --- a/src/plugins/vcpkg/vcpkgsettings.cpp +++ b/src/plugins/vcpkg/vcpkgsettings.cpp @@ -28,7 +28,7 @@ using namespace Utils; namespace Vcpkg::Internal { -static VcpkgSettings &projectSettings(Project *project) +static VcpkgSettings *projectSettings(Project *project) { const Key key = "VcpkgProjectSettings"; QVariant v = project->extraData(key); @@ -36,18 +36,18 @@ static VcpkgSettings &projectSettings(Project *project) v = QVariant::fromValue(new VcpkgSettings(project, true)); project->setExtraData(key, v); } - return *v.value<VcpkgSettings*>(); + return v.value<VcpkgSettings *>(); } -VcpkgSettings &settings(Project *project) +VcpkgSettings *settings(Project *project) { static VcpkgSettings theSettings{nullptr, false}; if (!project) - return theSettings; + return &theSettings; - VcpkgSettings& projSettings = projectSettings(project); - if (projSettings.useGlobalSettings) - return theSettings; + VcpkgSettings *projSettings = projectSettings(project); + if (projSettings->useGlobalSettings) + return &theSettings; return projSettings; } @@ -148,7 +148,7 @@ public: setId(Constants::Settings::GENERAL_ID); setDisplayName("Vcpkg"); setCategory(Constants::Settings::CATEGORY); - setSettingsProvider([] { return &settings(nullptr); }); + setSettingsProvider([] { return settings(nullptr); }); } }; @@ -174,39 +174,37 @@ public: m_widget->setEnabled(!useGlobalSettings()); if (project) { - VcpkgSettings& projSettings = projectSettings(project); + VcpkgSettings *projSettings = projectSettings(project); - connect( - this, &ProjectSettingsWidget::useGlobalSettingsChanged, - this, [this, &projSettings](bool useGlobal) { - m_widget->setEnabled(!useGlobal); - m_displayedSettings.useGlobalSettings = useGlobal; - m_displayedSettings.copyFrom( - useGlobal ? settings(nullptr) : projSettings); + connect(this, &ProjectSettingsWidget::useGlobalSettingsChanged, + this, [this, projSettings](bool useGlobal) { + m_widget->setEnabled(!useGlobal); + m_displayedSettings.useGlobalSettings = useGlobal; + m_displayedSettings.copyFrom(useGlobal ? *settings(nullptr) : *projSettings); - projSettings.useGlobalSettings = useGlobal; - projSettings.writeSettings(); - projSettings.setVcpkgRootEnvironmentVariable(); - }); + projSettings->useGlobalSettings = useGlobal; + projSettings->writeSettings(); + projSettings->setVcpkgRootEnvironmentVariable(); + }); // React on Global settings changes - connect(&settings(nullptr), &AspectContainer::changed, this, [this] { + connect(settings(nullptr), &AspectContainer::changed, this, [this] { if (m_displayedSettings.useGlobalSettings) - m_displayedSettings.copyFrom(settings(nullptr)); + m_displayedSettings.copyFrom(*settings(nullptr)); }); // Reflect changes to the project settings in the displayed settings - connect(&projSettings, &AspectContainer::changed, this, [this, &projSettings] { + connect(projSettings, &AspectContainer::changed, this, [this, projSettings] { if (!m_displayedSettings.useGlobalSettings) - m_displayedSettings.copyFrom(projSettings); + m_displayedSettings.copyFrom(*projSettings); }); // React on displayed settings changes in the project settings - connect(&m_displayedSettings, &AspectContainer::changed, this, [this, &projSettings] { + connect(&m_displayedSettings, &AspectContainer::changed, this, [this, projSettings] { if (!m_displayedSettings.useGlobalSettings) { - projSettings.copyFrom(m_displayedSettings); - projSettings.writeSettings(); - projSettings.setVcpkgRootEnvironmentVariable(); + projSettings->copyFrom(m_displayedSettings); + projSettings->writeSettings(); + projSettings->setVcpkgRootEnvironmentVariable(); } }); } diff --git a/src/plugins/vcpkg/vcpkgsettings.h b/src/plugins/vcpkg/vcpkgsettings.h index debc736e052..5a3bb09c77b 100644 --- a/src/plugins/vcpkg/vcpkgsettings.h +++ b/src/plugins/vcpkg/vcpkgsettings.h @@ -30,6 +30,6 @@ private: ProjectExplorer::Project *m_project{nullptr}; }; -VcpkgSettings &settings(ProjectExplorer::Project *project); +VcpkgSettings *settings(ProjectExplorer::Project *project); } // Vcpkg::Internal diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index a861f2abc57..a849283fd7b 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -130,7 +130,8 @@ QString VcsBaseClientImpl::stripLastNewline(const QString &in) } CommandResult VcsBaseClientImpl::vcsSynchronousExec(const FilePath &workingDir, - const QStringList &args, RunFlags flags, int timeoutS, const QByteArray &codec) const + const QStringList &args, RunFlags flags, + int timeoutS, const TextCodec &codec) const { return vcsSynchronousExec(workingDir, {vcsBinary(workingDir), args}, flags, timeoutS, codec); } @@ -139,7 +140,7 @@ CommandResult VcsBaseClientImpl::vcsSynchronousExec(const FilePath &workingDir, const CommandLine &cmdLine, RunFlags flags, int timeoutS, - const QByteArray &codec) const + const TextCodec &codec) const { return VcsCommand::runBlocking(workingDir, processEnvironment(workingDir), @@ -171,7 +172,7 @@ void VcsBaseClientImpl::vcsExecWithHandler(const FilePath &workingDirectory, const QStringList &arguments, const QObject *context, const CommandHandler &handler, - RunFlags additionalFlags, const QByteArray codec) const + RunFlags additionalFlags, const TextCodec codec) const { VcsCommand *command = createCommand(workingDirectory); command->addFlags(additionalFlags); @@ -221,7 +222,7 @@ VcsCommand *VcsBaseClientImpl::createVcsCommand(const FilePath &defaultWorkingDi VcsBaseEditorWidget *VcsBaseClientImpl::createVcsEditor(Id kind, QString title, const FilePath &source, - const QByteArray &codecName, + const TextCodec &codec, const char *registerDynamicProperty, const QString &dynamicPropertyValue) const { @@ -243,8 +244,8 @@ VcsBaseEditorWidget *VcsBaseClientImpl::createVcsEditor(Id kind, QString title, this, &VcsBaseClientImpl::annotateRevisionRequested); baseEditor->setSource(source); baseEditor->setDefaultLineNumber(1); - if (!codecName.isEmpty()) - baseEditor->setCodec(codecName); + if (codec.isValid()) + baseEditor->setCodec(codec); } baseEditor->setForceReadOnly(true); @@ -383,7 +384,7 @@ void VcsBaseClient::diff(const FilePath &workingDir, const QStringList &files) args << editorConfig->arguments(); args << files; VcsCommand *command = createCommand(workingDir, editor); - command->setCodec(source.isEmpty() ? QByteArray() : VcsBaseEditor::getCodec(source)); + command->setCodec(source.isEmpty() ? TextCodec() : VcsBaseEditor::getCodec(source)); enqueueJob(command, args, workingDir, exitCodeInterpreter(DiffCommand)); } diff --git a/src/plugins/vcsbase/vcsbaseclient.h b/src/plugins/vcsbase/vcsbaseclient.h index 8321543ef49..7417a17c8dc 100644 --- a/src/plugins/vcsbase/vcsbaseclient.h +++ b/src/plugins/vcsbase/vcsbaseclient.h @@ -10,6 +10,7 @@ #include <utils/id.h> #include <utils/processenums.h> +#include <utils/textcodec.h> #include <QStringList> #include <QVariant> @@ -46,7 +47,7 @@ public: VcsBaseEditorWidget *createVcsEditor(Utils::Id kind, QString title, const Utils::FilePath &source, - const QByteArray &codecName, + const Utils::TextCodec &codec, const char *registerDynamicProperty, const QString &dynamicPropertyValue) const; @@ -76,18 +77,18 @@ public: // Fully synchronous VCS execution (QProcess-based) CommandResult vcsSynchronousExec(const Utils::FilePath &workingDir, const QStringList &args, RunFlags flags = RunFlags::None, - int timeoutS = -1, const QByteArray &codec = {}) const; + int timeoutS = -1, const Utils::TextCodec &codec = {}) const; CommandResult vcsSynchronousExec(const Utils::FilePath &workingDir, const Utils::CommandLine &cmdLine, RunFlags flags = RunFlags::None, - int timeoutS = -1, const QByteArray &codec = {}) const; + int timeoutS = -1, const Utils::TextCodec &codec = {}) const; void vcsExecWithHandler(const Utils::FilePath &workingDirectory, const QStringList &arguments, const QObject *context, const CommandHandler &handler, RunFlags additionalFlags = RunFlags::None, - const QByteArray codec = {}) const; + const Utils::TextCodec codec = {}) const; void vcsExec(const Utils::FilePath &workingDirectory, const QStringList &arguments, RunFlags additionalFlags = RunFlags::None) const; diff --git a/src/plugins/vcsbase/vcsbaseeditor.cpp b/src/plugins/vcsbase/vcsbaseeditor.cpp index fa77e6f9dac..005ae88a5df 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.cpp +++ b/src/plugins/vcsbase/vcsbaseeditor.cpp @@ -833,14 +833,14 @@ void VcsBaseEditorWidget::setWorkingDirectory(const FilePath &wd) d->m_workingDirectory = wd; } -QByteArray VcsBaseEditorWidget::codec() const +TextCodec VcsBaseEditorWidget::codec() const { - return textDocument()->codecName(); + return textDocument()->codec(); } -void VcsBaseEditorWidget::setCodec(const QByteArray &codec) +void VcsBaseEditorWidget::setCodec(const TextCodec &codec) { - if (!codec.isEmpty()) + if (codec.isValid()) textDocument()->setCodec(codec); else qWarning("%s: Attempt to set no codec.", Q_FUNC_INFO); @@ -1223,49 +1223,46 @@ DiffChunk VcsBaseEditorWidget::diffChunk(QTextCursor cursor) const unicode += QLatin1Char('\n'); } } - const QTextCodec *cd = textDocument()->codec(); - rc.chunk = cd ? cd->fromUnicode(unicode) : unicode.toLocal8Bit(); - rc.header = cd ? cd->fromUnicode(header) : header.toLocal8Bit(); + const TextCodec cd = textDocument()->codec(); + rc.chunk = cd.isValid() ? cd.fromUnicode(unicode) : unicode.toLocal8Bit(); + rc.header = cd.isValid() ? cd.fromUnicode(header) : header.toLocal8Bit(); return rc; } // Find the codec used for a file querying the editor. -static QTextCodec *findFileCodec(const FilePath &source) +static TextCodec findFileCodec(const FilePath &source) { IDocument *document = DocumentModel::documentForFilePath(source); if (auto textDocument = qobject_cast<BaseTextDocument *>(document)) - return const_cast<QTextCodec *>(textDocument->codec()); - return nullptr; + return textDocument->codec(); + return {}; } // Find the codec by checking the projects (root dir of project file) -static QTextCodec *findProjectCodec(const FilePath &dirPath) +static TextCodec findProjectCodec(const FilePath &dirPath) { // Try to find a project under which file tree the file is. const auto projects = ProjectExplorer::ProjectManager::projects(); const auto *p = findOrDefault(projects, equal(&ProjectExplorer::Project::projectDirectory, dirPath)); - return p ? QTextCodec::codecForName(p->editorConfiguration()->textCodec()) : nullptr; + return p ? p->editorConfiguration()->textCodec() : TextCodec(); } -QByteArray VcsBaseEditor::getCodec(const FilePath &source) +TextCodec VcsBaseEditor::getCodec(const FilePath &source) { if (!source.isEmpty()) { // Check file if (source.isFile()) - if (QTextCodec *fc = findFileCodec(source)) - return fc->name(); + if (TextCodec fc = findFileCodec(source); fc.isValid()) + return fc; // Find by project via directory - if (QTextCodec *pc = findProjectCodec(source.isFile() ? source.absolutePath() : source)) - return pc->name(); + if (TextCodec pc = findProjectCodec(source.isFile() ? source.absolutePath() : source); pc.isValid()) + return pc; } - if (QTextCodec *sys = QTextCodec::codecForLocale()) - return sys->name(); - QTC_CHECK(false); - return {}; + return TextCodec::codecForLocale(); } -QByteArray VcsBaseEditor::getCodec(const FilePath &workingDirectory, const QStringList &files) +TextCodec VcsBaseEditor::getCodec(const FilePath &workingDirectory, const QStringList &files) { if (files.empty()) return getCodec(workingDirectory); diff --git a/src/plugins/vcsbase/vcsbaseeditor.h b/src/plugins/vcsbase/vcsbaseeditor.h index ecfe037edf2..e93e121fc1c 100644 --- a/src/plugins/vcsbase/vcsbaseeditor.h +++ b/src/plugins/vcsbase/vcsbaseeditor.h @@ -71,8 +71,8 @@ public: // the editor manager and the project managers (defaults to system codec). // The codec should be set on editors displaying diff or annotation // output. - static QByteArray getCodec(const Utils::FilePath &source); - static QByteArray getCodec(const Utils::FilePath &workingDirectory, const QStringList &files); + static Utils::TextCodec getCodec(const Utils::FilePath &source); + static Utils::TextCodec getCodec(const Utils::FilePath &workingDirectory, const QStringList &files); // Utility to return the widget from the IEditor returned by the editor // manager which is a BaseTextEditor. @@ -174,8 +174,8 @@ public: void setHighlightingEnabled(bool e); - QByteArray codec() const; - void setCodec(const QByteArray &codec); + Utils::TextCodec codec() const; + void setCodec(const Utils::TextCodec &codec); // Base directory for diff views Utils::FilePath workingDirectory() const; diff --git a/src/plugins/vcsbase/vcscommand.cpp b/src/plugins/vcsbase/vcscommand.cpp index 3b1bc0125fb..4d96213fea8 100644 --- a/src/plugins/vcsbase/vcscommand.cpp +++ b/src/plugins/vcsbase/vcscommand.cpp @@ -12,6 +12,7 @@ #include <utils/globalfilechangeblocker.h> #include <utils/qtcprocess.h> #include <utils/qtcassert.h> +#include <utils/textcodec.h> #include <utils/threadutils.h> using namespace Core; @@ -66,7 +67,7 @@ public: QString m_displayName; const FilePath m_defaultWorkingDirectory; Environment m_environment; - QByteArray m_codec; + TextCodec m_codec; ProgressParser m_progressParser = {}; QList<Job> m_jobs; @@ -104,7 +105,7 @@ void VcsCommandPrivate::setupProcess(Process *process, const Job &job) process->setEnvironment(environment()); if (m_flags & RunFlags::MergeOutputChannels) process->setProcessChannelMode(QProcess::MergedChannels); - if (!m_codec.isEmpty()) + if (m_codec.isValid()) process->setCodec(m_codec); process->setUseCtrlCStub(true); @@ -289,7 +290,7 @@ ProcessResult VcsCommand::result() const CommandResult VcsCommand::runBlocking(const FilePath &workingDirectory, const Environment &environment, const CommandLine &command, RunFlags flags, - int timeoutS, const QByteArray &codec) + int timeoutS, const TextCodec &codec) { VcsCommand vcsCommand(workingDirectory, environment); vcsCommand.addFlags(flags); @@ -316,7 +317,7 @@ CommandResult VcsCommand::runBlockingHelper(const CommandLine &command, int time return CommandResult(process); } -void VcsCommand::setCodec(const QByteArray &codec) +void VcsCommand::setCodec(const TextCodec &codec) { d->m_codec = codec; } diff --git a/src/plugins/vcsbase/vcscommand.h b/src/plugins/vcsbase/vcscommand.h index bfe3e1140c3..785364d27ac 100644 --- a/src/plugins/vcsbase/vcscommand.h +++ b/src/plugins/vcsbase/vcscommand.h @@ -74,7 +74,7 @@ public: void addFlags(RunFlags f); - void setCodec(const QByteArray &codecName); + void setCodec(const Utils::TextCodec &codec); void setProgressParser(const Core::ProgressParser &parser); @@ -83,7 +83,7 @@ public: const Utils::CommandLine &command, RunFlags flags, int timeoutS, - const QByteArray &codec); + const Utils::TextCodec &codec); void cancel(); QString cleanedStdOut() const; diff --git a/src/plugins/webassembly/webassemblydevice.cpp b/src/plugins/webassembly/webassemblydevice.cpp index 9caf7caae28..d72043d2f10 100644 --- a/src/plugins/webassembly/webassemblydevice.cpp +++ b/src/plugins/webassembly/webassemblydevice.cpp @@ -53,7 +53,8 @@ static void askUserAboutEmSdkSetup() { const char setupWebAssemblyEmSdk[] = "SetupWebAssemblyEmSdk"; - if (!ICore::infoBar()->canInfoBeAdded(setupWebAssemblyEmSdk) + InfoBar *infoBar = ICore::infoBar(); + if (!infoBar->canInfoBeAdded(setupWebAssemblyEmSdk) || !WebAssemblyQtVersion::isQtVersionInstalled() || areToolChainsRegistered()) return; @@ -62,12 +63,14 @@ static void askUserAboutEmSdkSetup() Tr::tr("Setup Emscripten SDK for WebAssembly? " "To do it later, select Edit > Preferences > Devices > WebAssembly."), InfoBarEntry::GlobalSuppression::Enabled); + info.setTitle(Tr::tr("Set up WebAssembly?")); + info.setInfoType(InfoLabel::Information); info.addCustomButton( Tr::tr("Setup Emscripten SDK"), [] { QTimer::singleShot(0, []() { ICore::showOptionsDialog(Constants::SETTINGS_ID); }); }, {}, InfoBarEntry::ButtonAction::Hide); - ICore::infoBar()->addInfo(info); + infoBar->addInfo(info); } class WebAssemblyDeviceFactory final : public IDeviceFactory diff --git a/src/plugins/welcome/introductionwidget.cpp b/src/plugins/welcome/introductionwidget.cpp index ebf8c0d8bcd..03f3ba1040c 100644 --- a/src/plugins/welcome/introductionwidget.cpp +++ b/src/plugins/welcome/introductionwidget.cpp @@ -426,11 +426,11 @@ void askUserAboutIntroduction() InfoBarEntry info(kTakeTourSetting, - Tr::tr("Would you like to take a quick UI tour? This tour highlights important user " - "interface elements and shows how they are used. To take the tour later, " - "select Help > UI Tour."), + Tr::tr("See where the important UI elements are and how they are used. " + "To take the tour later, select Help > UI Tour."), InfoBarEntry::GlobalSuppression::Enabled); - info.setTitle(Tr::tr("UI Tour")); + info.setTitle(Tr::tr("Take a UI Tour?")); + info.setInfoType(InfoLabel::Information); info.addCustomButton( Tr::tr("Take UI Tour"), [] { runUiTour(); }, |