From f0c2239fa3f348ce3b768c15543e39beee5ea0eb Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 25 Jul 2024 10:55:44 +0200 Subject: [PATCH] Core: Merge actionmanager/commandsfile pair into their only user Also, de-QObject-ify and inline the Context wrapper structure for the key strings. Change-Id: I21f3afec61ef9ecfcc4c3d89afb9fb3a1548afae Reviewed-by: Eike Ziller --- src/plugins/coreplugin/CMakeLists.txt | 2 - .../actionmanager/commandmappings.cpp | 2 - .../coreplugin/actionmanager/commandsfile.cpp | 170 ------------------ .../coreplugin/actionmanager/commandsfile.h | 34 ---- src/plugins/coreplugin/coreplugin.qbs | 1 - .../coreplugin/dialogs/shortcutsettings.cpp | 169 +++++++++++++++-- .../coreplugin/dialogs/shortcutsettings.h | 18 +- 7 files changed, 161 insertions(+), 235 deletions(-) delete mode 100644 src/plugins/coreplugin/actionmanager/commandsfile.cpp delete mode 100644 src/plugins/coreplugin/actionmanager/commandsfile.h diff --git a/src/plugins/coreplugin/CMakeLists.txt b/src/plugins/coreplugin/CMakeLists.txt index 866b43b9e4e..99787ff98a9 100644 --- a/src/plugins/coreplugin/CMakeLists.txt +++ b/src/plugins/coreplugin/CMakeLists.txt @@ -13,8 +13,6 @@ add_qtc_plugin(Core actionmanager/command_p.h actionmanager/commandmappings.cpp actionmanager/commandmappings.h - actionmanager/commandsfile.cpp - actionmanager/commandsfile.h actionsfilter.cpp actionsfilter.h basefilewizard.cpp diff --git a/src/plugins/coreplugin/actionmanager/commandmappings.cpp b/src/plugins/coreplugin/actionmanager/commandmappings.cpp index 276004bdb78..3e19bec44ae 100644 --- a/src/plugins/coreplugin/actionmanager/commandmappings.cpp +++ b/src/plugins/coreplugin/actionmanager/commandmappings.cpp @@ -18,8 +18,6 @@ #include #include -Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*) - using namespace Utils; namespace Core { diff --git a/src/plugins/coreplugin/actionmanager/commandsfile.cpp b/src/plugins/coreplugin/actionmanager/commandsfile.cpp deleted file mode 100644 index 9cf530d7ff4..00000000000 --- a/src/plugins/coreplugin/actionmanager/commandsfile.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "commandsfile.h" -#include "command.h" -#include "../dialogs/shortcutsettings.h" -#include "../icore.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace Utils; - -namespace Core { -namespace Internal { - -struct Context // XML parsing context with strings. -{ - const QString mappingElement = "mapping"; - const QString shortCutElement = "shortcut"; - const QString idAttribute = "id"; - const QString keyElement = "key"; - const QString valueAttribute = "value"; -}; - -/*! - \class Core::Internal::CommandsFile - \internal - \inmodule QtCreator - \brief The CommandsFile class provides a collection of import and export commands. - \inheaderfile commandsfile.h -*/ - -/*! - \internal -*/ -CommandsFile::CommandsFile(const FilePath &filename) - : m_filePath(filename) -{ - -} - -// XML attributes cannot contain these characters, and -// QXmlStreamWriter just bails out with an error. -// QKeySequence::toString() should probably not result in these -// characters, but it currently does, see QTCREATORBUG-29431 -static bool containsInvalidCharacters(const QString &s) -{ - const auto end = s.constEnd(); - for (auto it = s.constBegin(); it != end; ++it) { - // from QXmlStreamWriterPrivate::writeEscaped - if (*it == u'\v' || *it == u'\f' || *it <= u'\x1F' || *it >= u'\uFFFE') { - return true; - } - } - return false; -} - -static QString toAttribute(const QString &s) -{ - if (containsInvalidCharacters(s)) - return "0x" + QString::fromUtf8(s.toUtf8().toHex()); - return s; -} - -static QString fromAttribute(const QStringView &s) -{ - if (s.startsWith(QLatin1String("0x"))) - return QString::fromUtf8(QByteArray::fromHex(s.sliced(2).toUtf8())); - return s.toString(); -} - -/*! - \internal -*/ -QMap> CommandsFile::importCommands() const -{ - QMap> result; - - QFile file(m_filePath.toString()); - if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) - return result; - - Context ctx; - QXmlStreamReader r(&file); - - QString currentId; - - while (!r.atEnd()) { - switch (r.readNext()) { - case QXmlStreamReader::StartElement: { - const auto name = r.name(); - if (name == ctx.shortCutElement) { - currentId = r.attributes().value(ctx.idAttribute).toString(); - if (!result.contains(currentId)) - result.insert(currentId, {}); - } else if (name == ctx.keyElement) { - QTC_ASSERT(!currentId.isEmpty(), continue); - const QXmlStreamAttributes attributes = r.attributes(); - if (attributes.hasAttribute(ctx.valueAttribute)) { - QString keyString = fromAttribute(attributes.value(ctx.valueAttribute)); - if (HostOsInfo::isMacHost()) - keyString = keyString.replace("AlwaysCtrl", "Meta"); - else - keyString = keyString.replace("AlwaysCtrl", "Ctrl"); - - QList keys = result.value(currentId); - result.insert(currentId, keys << QKeySequence(keyString)); - } - } // if key element - } // case QXmlStreamReader::StartElement - default: - break; - } // switch - } // while !atEnd - file.close(); - return result; -} - -/*! - \internal -*/ -bool CommandsFile::exportCommands(const QList &items) -{ - FileSaver saver(m_filePath, QIODevice::Text); - if (!saver.hasError()) { - const Context ctx; - QXmlStreamWriter w(saver.file()); - w.setAutoFormatting(true); - w.setAutoFormattingIndent(1); // Historical, used to be QDom. - w.writeStartDocument(); - w.writeDTD(QLatin1String("")); - w.writeComment(QString::fromLatin1(" Written by %1, %2. "). - arg(ICore::versionString(), - QDateTime::currentDateTime().toString(Qt::ISODate))); - w.writeStartElement(ctx.mappingElement); - for (const ShortcutItem *item : std::as_const(items)) { - const Id id = item->m_cmd->id(); - if (item->m_keys.isEmpty() || item->m_keys.first().isEmpty()) { - w.writeEmptyElement(ctx.shortCutElement); - w.writeAttribute(ctx.idAttribute, id.toString()); - } else { - w.writeStartElement(ctx.shortCutElement); - w.writeAttribute(ctx.idAttribute, id.toString()); - for (const QKeySequence &k : item->m_keys) { - w.writeEmptyElement(ctx.keyElement); - w.writeAttribute(ctx.valueAttribute, toAttribute(k.toString())); - } - w.writeEndElement(); // Shortcut - } - } - w.writeEndElement(); - w.writeEndDocument(); - - if (!saver.setResult(&w)) - qWarning() << saver.errorString(); - } - return saver.finalize(); -} - -} // namespace Internal -} // namespace Core diff --git a/src/plugins/coreplugin/actionmanager/commandsfile.h b/src/plugins/coreplugin/actionmanager/commandsfile.h deleted file mode 100644 index 29559453755..00000000000 --- a/src/plugins/coreplugin/actionmanager/commandsfile.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -#include -#include -#include - -QT_FORWARD_DECLARE_CLASS(QKeySequence) - -namespace Core { -namespace Internal { - -struct ShortcutItem; - -class CommandsFile : public QObject -{ - Q_OBJECT - -public: - CommandsFile(const Utils::FilePath &filePath); - - QMap > importCommands() const; - bool exportCommands(const QList &items); - -private: - Utils::FilePath m_filePath; -}; - -} // namespace Internal -} // namespace Core diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index ebfe13d5e88..f55fb727afb 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -187,7 +187,6 @@ QtcPlugin { "actionmanager.cpp", "actionmanager.h", "actionmanager_p.h", "command.cpp", "command.h", "command_p.h", "commandmappings.cpp", "commandmappings.h", - "commandsfile.cpp", "commandsfile.h", ] } diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp index d6f813c8ba5..5e12b1ba0e9 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.cpp +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.cpp @@ -3,15 +3,14 @@ #include "shortcutsettings.h" +#include "ioptionspage.h" +#include "../actionmanager/actionmanager.h" +#include "../actionmanager/command.h" +#include "../actionmanager/commandmappings.h" #include "../coreconstants.h" #include "../coreplugintr.h" #include "../documentmanager.h" #include "../icore.h" -#include "../actionmanager/actionmanager.h" -#include "../actionmanager/command.h" -#include "../actionmanager/commandsfile.h" -#include "../actionmanager/commandmappings.h" -#include "ioptionspage.h" #include #include @@ -22,8 +21,9 @@ #include #include +#include #include -#include +#include #include #include #include @@ -34,19 +34,168 @@ #include #include #include +#include +#include +#include #include using namespace Utils; -Q_DECLARE_METATYPE(Core::Internal::ShortcutItem*) - namespace Core::Internal { const char kSeparator[] = " | "; -static int translateModifiers(Qt::KeyboardModifiers state, - const QString &text) +struct ShortcutItem final +{ + Command *m_cmd; + QList m_keys; + QTreeWidgetItem *m_item; +}; + +/*! + \class Core::Internal::CommandsFile + \internal + \inmodule QtCreator + \brief The CommandsFile class provides a collection of import and export commands. +*/ + +class CommandsFile final +{ +public: + CommandsFile(const FilePath &filePath) : m_filePath(filePath) {} + + QMap > importCommands() const; + bool exportCommands(const QList &items); + +private: + const QString mappingElement = "mapping"; + const QString shortCutElement = "shortcut"; + const QString idAttribute = "id"; + const QString keyElement = "key"; + const QString valueAttribute = "value"; + + FilePath m_filePath; +}; + + +// XML attributes cannot contain these characters, and +// QXmlStreamWriter just bails out with an error. +// QKeySequence::toString() should probably not result in these +// characters, but it currently does, see QTCREATORBUG-29431 +static bool containsInvalidCharacters(const QString &s) +{ + const auto end = s.constEnd(); + for (auto it = s.constBegin(); it != end; ++it) { + // from QXmlStreamWriterPrivate::writeEscaped + if (*it == u'\v' || *it == u'\f' || *it <= u'\x1F' || *it >= u'\uFFFE') { + return true; + } + } + return false; +} + +static QString toAttribute(const QString &s) +{ + if (containsInvalidCharacters(s)) + return "0x" + QString::fromUtf8(s.toUtf8().toHex()); + return s; +} + +static QString fromAttribute(const QStringView &s) +{ + if (s.startsWith(QLatin1String("0x"))) + return QString::fromUtf8(QByteArray::fromHex(s.sliced(2).toUtf8())); + return s.toString(); +} + +/*! + \internal +*/ +QMap> CommandsFile::importCommands() const +{ + QMap> result; + + QFile file(m_filePath.toString()); + if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) + return result; + + QXmlStreamReader r(&file); + + QString currentId; + + while (!r.atEnd()) { + switch (r.readNext()) { + case QXmlStreamReader::StartElement: { + const auto name = r.name(); + if (name == shortCutElement) { + currentId = r.attributes().value(idAttribute).toString(); + if (!result.contains(currentId)) + result.insert(currentId, {}); + } else if (name == keyElement) { + QTC_ASSERT(!currentId.isEmpty(), continue); + const QXmlStreamAttributes attributes = r.attributes(); + if (attributes.hasAttribute(valueAttribute)) { + QString keyString = fromAttribute(attributes.value(valueAttribute)); + if (HostOsInfo::isMacHost()) + keyString = keyString.replace("AlwaysCtrl", "Meta"); + else + keyString = keyString.replace("AlwaysCtrl", "Ctrl"); + + QList keys = result.value(currentId); + result.insert(currentId, keys << QKeySequence(keyString)); + } + } // if key element + } // case QXmlStreamReader::StartElement + default: + break; + } // switch + } // while !atEnd + file.close(); + return result; +} + +/*! + \internal +*/ +bool CommandsFile::exportCommands(const QList &items) +{ + FileSaver saver(m_filePath, QIODevice::Text); + if (!saver.hasError()) { + QXmlStreamWriter w(saver.file()); + w.setAutoFormatting(true); + w.setAutoFormattingIndent(1); // Historical, used to be QDom. + w.writeStartDocument(); + w.writeDTD(QLatin1String("")); + w.writeComment(QString::fromLatin1(" Written by %1, %2. "). + arg(ICore::versionString(), + QDateTime::currentDateTime().toString(Qt::ISODate))); + w.writeStartElement(mappingElement); + for (const ShortcutItem *item : std::as_const(items)) { + const Id id = item->m_cmd->id(); + if (item->m_keys.isEmpty() || item->m_keys.first().isEmpty()) { + w.writeEmptyElement(shortCutElement); + w.writeAttribute(idAttribute, id.toString()); + } else { + w.writeStartElement(shortCutElement); + w.writeAttribute(idAttribute, id.toString()); + for (const QKeySequence &k : item->m_keys) { + w.writeEmptyElement(keyElement); + w.writeAttribute(valueAttribute, toAttribute(k.toString())); + } + w.writeEndElement(); // Shortcut + } + } + w.writeEndElement(); + w.writeEndDocument(); + + if (!saver.setResult(&w)) + qWarning() << saver.errorString(); + } + return saver.finalize(); +} + +static int translateModifiers(Qt::KeyboardModifiers state, const QString &text) { int result = 0; // The shift modifier only counts when it is not used to type a symbol diff --git a/src/plugins/coreplugin/dialogs/shortcutsettings.h b/src/plugins/coreplugin/dialogs/shortcutsettings.h index 00c68c76581..abc495a53fb 100644 --- a/src/plugins/coreplugin/dialogs/shortcutsettings.h +++ b/src/plugins/coreplugin/dialogs/shortcutsettings.h @@ -3,22 +3,8 @@ #pragma once -#include "../actionmanager/commandmappings.h" - -namespace Core { - -class Command; - -namespace Internal { - -struct ShortcutItem -{ - Command *m_cmd; - QList m_keys; - QTreeWidgetItem *m_item; -}; +namespace Core::Internal { void setupShortcutSettings(); -} // namespace Internal -} // namespace Core +} // Core::Core