diff --git a/share/qtcreator/translations/qtcreator_de.ts b/share/qtcreator/translations/qtcreator_de.ts
index 033acd385d0..2d1a13ead00 100644
--- a/share/qtcreator/translations/qtcreator_de.ts
+++ b/share/qtcreator/translations/qtcreator_de.ts
@@ -11934,7 +11934,7 @@ Lokale Commits werden nicht zum Master-Branch gepusht, bis ein normaler Commit e
Local filesystem:
- Dateisystem:
+ Lokales Dateisystem:Options
@@ -11942,7 +11942,7 @@ Lokale Commits werden nicht zum Master-Branch gepusht, bis ein normaler Commit e
Remember specified location as default
- Obige Einstellung als Vorgabe übernehmen
+ Angegebenen Ort als Vorgabe übernehmenOverwrite
@@ -12124,7 +12124,7 @@ Lokale Pull-Operationen werden nicht auf den Master-Branch angewandt.
Update...
- Auf aktuellen Stand bringen...
+ Aktualisieren...Commit...
@@ -12160,7 +12160,7 @@ Lokale Pull-Operationen werden nicht auf den Master-Branch angewandt.
Unable to create a commit editor.
- Es konnte kein Editor für den Commit angelegt werden.
+ Es konnte kein Commit-Editor angelegt werden.Commit changes for "%1".
@@ -27079,497 +27079,499 @@ zu deaktivieren, deaktiviert auch die folgenden Plugins:
QtC::FossilCommit Editor
- Commit-Editor
+ Commit-EditorConfigure Repository
-
+ Repository konfigurierenExisting user to become an author of changes made to the repository.
-
+ Vorhandener Benutzer, der Autor der Änderungen im Repository werden soll.SSL/TLS Identity Key
-
+ SSL/TLS Identity KeySSL/TLS client identity key to use if requested by the server.
-
+ SSL/TLS Client Identity Key, der benutzt werden soll, wenn der Server diesen anfordert.Disable auto-sync
-
+ Automatisches Synchronisieren (autosync) deaktivierenDisable automatic pull prior to commit or update and automatic push after commit or tag or branch creation.
-
+ Deaktiviert die automatische Pull-Operation vor Commits oder Aktualisierungen und die automatische Push-Operation nach Commits oder dem Erstellen von Tags oder Branches.Repository User
-
+ Benutzer des RepositorysUser:
- Nutzer:
+ Nutzer:Repository Settings
-
+ Repository-EinstellungenSSL/TLS identity:
-
+ SSL/TLS Identity:Ignore All Whitespace
-
+ Alle Leerzeichen ignorierenStrip Trailing CR
-
+ CR-Zeichen am Zeilenende entfernenShow Committers
-
+ Committer anzeigenList Versions
-
+ Versionen anzeigenAncestors
-
+ VorfahrenDescendants
-
+ NachfahrenUnfiltered
- Ungefiltert
+ UngefiltertLineage
-
+ AbstammungVerbose
- Ausführlich
+ AusführlichShow files changed in each revision
- Geänderte Dateien jeder Revision anzeigen
+ Geänderte Dateien jeder Revision anzeigenAll Items
-
+ Alle ElementeFile Commits
-
+ Datei-CommitsTechnical Notes
-
+ Technische Anmerkungen (technotes)Tags
- Tags
+ TagsTickets
-
+ TicketsWiki Commits
-
+ Wiki-CommitsItem Types
-
+ Element-TypenPrivate
-
+ PrivatCreate a private check-in that is never synced.
Children of private check-ins are automatically private.
Private check-ins are not pushed to the remote repository by default.
-
+ Erstelle einen privaten Check-In, der niemals synchronisiert wird.
+Kinder von privaten Check-Ins sind automatisch privat.
+Private Check-Ins werden standardmäßig nicht zum entfernten Repository gepusht.Tag names to apply; comma-separated.
-
+ Kommaseparierte Liste von Tag-Namen, die angewendet werden sollen.Current Information
-
+ Aktuelle InformationenLocal root:
-
+ Lokale Root:Branch:
- Branch:
+ Branch:Tags:
- Schlüsselworte:
+ Tags:Commit Information
- Informationen zu Commit
+ Informationen zum CommitNew branch:
-
+ Neuer Branch:Author:
- Autor:
+ Autor:Message check failed.
-
+ Die Überprüfung der Beschreibung schlug fehl.&Annotate %1
-
+ &Annotation für %1Annotate &Parent Revision %1
-
+ Annotation der über&geordneten Revision %1&Fossil
-
+ &FossilAnnotate Current File
- Annotation für Datei
+ Annotation für DateiAnnotate "%1"
- Annotation für "%1"
+ Annotation für "%1"Diff Current File
-
+ Diff für aktuelle DateiDiff "%1"
- Diff für "%1"
+ Diff für "%1"Meta+I,Meta+D
-
+ Meta+I,Meta+DALT+I,Alt+D
-
+ ALT+I,Alt+DTimeline Current File
-
+ Zeitleiste für aktuelle DateiTimeline "%1"
-
+ Zeitleiste für "%1"Meta+I,Meta+L
-
+ Meta+I,Meta+LALT+I,Alt+L
-
+ ALT+I,Alt+LStatus Current File
- Status der Datei
+ Status der aktuellen DateiStatus "%1"
- Status von "%1"
+ Status von "%1"Meta+I,Meta+S
-
+ Meta+I,Meta+SALT+I,Alt+S
-
+ ALT+I,Alt+SAdd Current File
-
+ Aktuelle Datei hinzufügenAdd "%1"
- "%1" hinzufügen
+ "%1" hinzufügenDelete Current File...
-
+ Aktuelle Datei löschen...Delete "%1"...
- Lösche "%1"...
+ Lösche "%1"...Revert Current File...
- Änderungen der Datei rückgängig machen...
+ Änderungen der aktuellen Datei rückgängig machen...Revert "%1"...
- Änderungen in "%1" rückgängig machen...
+ Änderungen in "%1" rückgängig machen...Diff
- Diff
+ DiffTimeline
-
+ ZeitleisteMeta+I,Meta+T
-
+ Meta+I,Meta+TALT+I,Alt+T
-
+ ALT+I,Alt+TRevert...
- Rückgängig machen...
+ Rückgängig machen...Status
- Status
+ StatusRevert
- Rückgängig machen
+ Rückgängig machenPull...
- Pull...
+ Pull...Push...
- Push...
+ Push...Update...
- Auf aktuellen Stand bringen...
+ Aktualisieren...Meta+I,Meta+U
-
+ Meta+I,Meta+UALT+I,Alt+U
-
+ ALT+I,Alt+UCommit...
- Commit...
+ Commit...Meta+I,Meta+C
-
+ Meta+I,Meta+CALT+I,Alt+C
-
+ ALT+I,Alt+CSettings ...
-
+ Einstellungen...Create Repository...
- Repository erzeugen...
+ Repository erzeugen...Remote repository is not defined.
-
+ Es ist kein entferntes Repository definiert.Update
- Aktualisieren
+ AktualisierenThere are no changes to commit.
- Es sind keine ausstehenden Änderungen vorhanden.
+ Es sind keine ausstehenden Änderungen vorhanden.Unable to create an editor for the commit.
- Es konnte kein Editor für den Commit angelegt werden.
+ Es konnte kein Editor für den Commit angelegt werden.Unable to create a commit editor.
- Es konnte kein Editor für den Commit angelegt werden.
+ Es konnte kein Commit-Editor angelegt werden.Commit changes for "%1".
- Commit der Änderungen in "%1".
+ Commit der Änderungen in "%1".Choose Checkout Directory
-
+ Verzeichnis für Checkout wählenThe directory "%1" is already managed by a version control system (%2). Would you like to specify another directory?
- Das Verzeichnis "%1" steht bereits unter Verwaltung eines Versionskontrollsystems (%2). Möchten Sie einen anderes Verzeichnis angeben?
+ Das Verzeichnis "%1" steht bereits unter Verwaltung eines Versionskontrollsystems (%2). Möchten Sie ein anderes Verzeichnis angeben?Repository already under version control
- Repository bereits unter Versionskontrolle
+ Repository bereits unter VersionskontrolleRepository Created
- Repository erstellt
+ Repository erstelltA version control repository has been created in %1.
- Ein Repository für Versionskontrolle wurde im Verzeichnis %1 erstellt.
+ Ein Repository für Versionskontrolle wurde im Verzeichnis %1 erstellt.Repository Creation Failed
- Fehlschlag bei Erstellung des Repositorys
+ Fehlschlag bei Erstellung des RepositorysA version control repository could not be created in %1.
- Im Verzeichnis %1 konnte kein Repository für die Versionskontrolle erstellt werden.
+ Im Verzeichnis %1 konnte kein Repository für die Versionskontrolle erstellt werden.Fossil
-
+ FossilSpecify a revision other than the default?
- Möchten Sie eine Revision angeben?
+ Möchten Sie eine Revision angeben?Checkout revision, can also be a branch or a tag name.
-
+ Checkout der Revision erstellen, kann auch der Name eines Branches oder Tags sein.Revision
- Revision
+ RevisionFossil Command
-
+ Fossil-KommandoCommand:
-
+ Kommando:Fossil Repositories
-
+ Fossil-RepositorysDefault path:
-
+ Vorgabeverzeichnis:Directory to store local repositories by default.
-
+ Vorgabeverzeichnis für lokale Repositorys.Default user:
-
+ Vorgabe-Benutzer:Log width:
-
+ Breite des Logs:The width of log entry line (>20). Choose 0 to see a single line per entry.
-
+ Die Breite der Zeilen in Logs (>20). Wählen Sie 0, um eine einzelne Zeile pro Eintrag anzuzeigen.Timeout:
- Zeitlimit:
+ Zeitlimit:s
- s
+ sLog count:
- Log-Anzeige beschränken auf:
+ Log-Anzeige beschränken auf:The number of recent commit log entries to show. Choose 0 to see all entries.
-
+ Zahl der anzuzeigenden Logeinträge, 0 für unbegrenzt.Configuration
- Konfiguration
+ KonfigurationLocal Repositories
-
+ Lokale RepositorysUser
- Nutzer
+ NutzerMiscellaneous
- Sonstige Einstellungen
+ Sonstige EinstellungenPull Source
-
+ Quelle für Pull-OperationPush Destination
-
+ Ziel für Push-OperationDefault location
- Vorgabe
+ VorgabeLocal filesystem:
- Dateisystem:
+ Lokales Dateisystem:Specify URL:
- URL:
+ URL:For example: https://[user[:pass]@]host[:port]/[path]
-
+ Zum Beispiel: https://[user[:pass]@]host[:port]/[path]Remember specified location as default
- Obige Einstellung als Vorgabe übernehmen
+ Angegebenen Ort als Vorgabe übernehmenInclude private branches
-
+ Private Branches einbeziehenAllow transfer of private branches.
-
+ Übertragen von privaten Branches erlauben.Remote Location
-
+ Entfernter OrtOptions
- Einstellungen
+ Einstellungen
@@ -32653,7 +32655,7 @@ Beispiel: *.cpp%1*.h
Local filesystem:
- Dateisystem:
+ Lokales Dateisystem:Default Location
@@ -32813,7 +32815,7 @@ Beispiel: *.cpp%1*.h
Update...
- Auf aktuellen Stand bringen...
+ Aktualisieren...Import...
diff --git a/src/plugins/qtsupport/exampleslistmodel.cpp b/src/plugins/qtsupport/exampleslistmodel.cpp
index 84e1b57ab1c..5beb9c80a35 100644
--- a/src/plugins/qtsupport/exampleslistmodel.cpp
+++ b/src/plugins/qtsupport/exampleslistmodel.cpp
@@ -4,7 +4,6 @@
#include "exampleslistmodel.h"
#include "examplesparser.h"
-#include "qtsupporttr.h"
#include
#include
@@ -326,61 +325,6 @@ static bool isValidExampleOrDemo(ExampleItem *item)
return ok || debugExamples();
}
-static bool sortByHighlightedAndName(ExampleItem *first, ExampleItem *second)
-{
- if (first->isHighlighted && !second->isHighlighted)
- return true;
- if (!first->isHighlighted && second->isHighlighted)
- return false;
- return first->name.compare(second->name, Qt::CaseInsensitive) < 0;
-}
-
-static QList>> getCategories(
- const QList &items, bool sortIntoCategories)
-{
- static const QString otherDisplayName = Tr::tr("Other", "Category for all other examples");
- const bool useCategories = sortIntoCategories
- || qtcEnvironmentVariableIsSet("QTC_USE_EXAMPLE_CATEGORIES");
- QList other;
- QMap> categoryMap;
- if (useCategories) {
- for (ExampleItem *item : items) {
- const QStringList itemCategories = item->metaData.value("category");
- for (const QString &category : itemCategories)
- categoryMap[category].append(item);
- if (itemCategories.isEmpty())
- other.append(item);
- }
- }
- QList>> categories;
- if (categoryMap.isEmpty()) {
- // The example set doesn't define categories. Consider the "highlighted" ones as "featured"
- QList featured;
- QList allOther;
- std::tie(featured, allOther) = Utils::partition(items, [](ExampleItem *i) {
- return i->isHighlighted;
- });
- if (!featured.isEmpty())
- categories.append(
- {{Tr::tr("Featured", "Category for highlighted examples"), 0}, featured});
- if (!allOther.isEmpty())
- categories.append({{otherDisplayName, 1}, allOther});
- } else {
- int index = 0;
- const auto end = categoryMap.constKeyValueEnd();
- for (auto it = categoryMap.constKeyValueBegin(); it != end; ++it) {
- categories.append({{it->first, index, /*maxRows=*/index == 0 ? 2 : 1}, it->second});
- ++index;
- }
- if (!other.isEmpty())
- categories.append({{otherDisplayName, index, /*maxRows=*/1}, other});
- }
- const auto end = categories.end();
- for (auto it = categories.begin(); it != end; ++it)
- sort(it->second, sortByHighlightedAndName);
- return categories;
-}
-
void ExamplesViewController::updateExamples()
{
QString examplesInstallPath;
diff --git a/src/plugins/qtsupport/examplesparser.cpp b/src/plugins/qtsupport/examplesparser.cpp
index c44919f2e12..84469ca2c4d 100644
--- a/src/plugins/qtsupport/examplesparser.cpp
+++ b/src/plugins/qtsupport/examplesparser.cpp
@@ -3,7 +3,10 @@
#include "examplesparser.h"
+#include "qtsupporttr.h"
+
#include
+#include
#include
#include
@@ -298,4 +301,68 @@ expected_str> parseExamples(const QByteArray &manifestData,
return items;
}
+static bool sortByHighlightedAndName(ExampleItem *first, ExampleItem *second)
+{
+ if (first->isHighlighted && !second->isHighlighted)
+ return true;
+ if (!first->isHighlighted && second->isHighlighted)
+ return false;
+ return first->name.compare(second->name, Qt::CaseInsensitive) < 0;
+}
+
+QList>> getCategories(const QList &items,
+ bool sortIntoCategories)
+{
+ static const QString otherDisplayName = Tr::tr("Other", "Category for all other examples");
+ const bool useCategories = sortIntoCategories
+ || qtcEnvironmentVariableIsSet("QTC_USE_EXAMPLE_CATEGORIES");
+ QList other;
+ QMap> categoryMap;
+ if (useCategories) {
+ // Append copies of the items and delete the original ones,
+ // because items might be added to multiple categories and that needs individual items
+ for (ExampleItem *item : items) {
+ const QStringList itemCategories = Utils::filteredUnique(
+ item->metaData.value("category"));
+ for (const QString &category : itemCategories)
+ categoryMap[category].append(new ExampleItem(*item));
+ if (itemCategories.isEmpty())
+ other.append(new ExampleItem(*item));
+ }
+ }
+ QList>> categories;
+ if (categoryMap.isEmpty()) {
+ // If we tried sorting into categories, but none were defined, we copied the items
+ // into "other", which we don't use here. Get rid of them again.
+ qDeleteAll(other);
+ // The example set doesn't define categories. Consider the "highlighted" ones as "featured"
+ QList featured;
+ QList allOther;
+ std::tie(featured, allOther) = Utils::partition(items, [](ExampleItem *i) {
+ return i->isHighlighted;
+ });
+ if (!featured.isEmpty()) {
+ categories.append(
+ {{Tr::tr("Featured", "Category for highlighted examples"), 0}, featured});
+ }
+ if (!allOther.isEmpty())
+ categories.append({{otherDisplayName, 1}, allOther});
+ } else {
+ // All original items have been copied into a category or other, delete.
+ qDeleteAll(items);
+ int index = 0;
+ const auto end = categoryMap.constKeyValueEnd();
+ for (auto it = categoryMap.constKeyValueBegin(); it != end; ++it) {
+ categories.append({{it->first, index, /*maxRows=*/index == 0 ? 2 : 1}, it->second});
+ ++index;
+ }
+ if (!other.isEmpty())
+ categories.append({{otherDisplayName, index, /*maxRows=*/1}, other});
+ }
+ const auto end = categories.end();
+ for (auto it = categories.begin(); it != end; ++it)
+ sort(it->second, sortByHighlightedAndName);
+ return categories;
+}
+
} // namespace QtSupport::Internal
diff --git a/src/plugins/qtsupport/examplesparser.h b/src/plugins/qtsupport/examplesparser.h
index 2d1afa54838..bfe65721c22 100644
--- a/src/plugins/qtsupport/examplesparser.h
+++ b/src/plugins/qtsupport/examplesparser.h
@@ -44,6 +44,9 @@ QTSUPPORT_EXPORT Utils::expected_str> parseExamples(
const Utils::FilePath &demosInstallPath,
bool examples);
+QTSUPPORT_TEST_EXPORT QList>> getCategories(
+ const QList &items, bool sortIntoCategories);
+
} // namespace QtSupport::Internal
Q_DECLARE_METATYPE(QtSupport::Internal::ExampleItem *)
diff --git a/src/plugins/qtsupport/qtsupport_global.h b/src/plugins/qtsupport/qtsupport_global.h
index aca20f5aa27..60c9bf0c128 100644
--- a/src/plugins/qtsupport/qtsupport_global.h
+++ b/src/plugins/qtsupport/qtsupport_global.h
@@ -12,3 +12,15 @@
#else
# define QTSUPPORT_EXPORT Q_DECL_IMPORT
#endif
+
+#if defined(WITH_TESTS)
+# if defined(QTSUPPORT_LIBRARY)
+# define QTSUPPORT_TEST_EXPORT Q_DECL_EXPORT
+# elif defined(QTSUPPORT_STATIC_LIBRARY)
+# define QTSUPPORT_TEST_EXPORT
+# else
+# define QTSUPPORT_TEST_EXPORT Q_DECL_IMPORT
+# endif
+#else
+# define QTSUPPORT_TEST_EXPORT
+#endif
diff --git a/tests/auto/examples/tst_examples.cpp b/tests/auto/examples/tst_examples.cpp
index eef0429d29f..d6639663adf 100644
--- a/tests/auto/examples/tst_examples.cpp
+++ b/tests/auto/examples/tst_examples.cpp
@@ -6,6 +6,7 @@
#include
+using namespace Core;
using namespace Utils;
using namespace QtSupport::Internal;
@@ -88,6 +89,7 @@ void tst_Examples::parsing_data()
QTest::addColumn("videoLength");
QTest::addColumn("platforms");
QTest::addColumn("metaData");
+ QTest::addColumn("categories");
QTest::addRow("example")
<< QByteArray(R"raw(
@@ -102,6 +104,8 @@ void tst_Examples::parsing_data()
widgets/widgets/analogclock/analogclock.cppGraphics
+ Graphics
+ Foobarwidgets
@@ -120,13 +124,29 @@ void tst_Examples::parsing_data()
"examples/widgets/widgets/analogclock/analogclock.cpp")}
<< FilePath::fromUserInput("examples/widgets/widgets/analogclock/analogclock.cpp")
<< FilePaths() << Example << true << false << false << ""
- << "" << QStringList() << MetaData({{"category", {"Graphics"}}, {"tags", {"widgets"}}});
+ << "" << QStringList()
+ << MetaData({{"category", {"Graphics", "Graphics", "Foobar"}}, {"tags", {"widgets"}}})
+ << QStringList{"Foobar", "Graphics"};
+
+ QTest::addRow("no category, highlighted")
+ << QByteArray(R"raw(
+
+
+
+
+ )raw") << /*isExamples=*/true
+ << "No Category, highlighted" << QString() << QString() << QStringList()
+ << FilePath("examples") << QString() << FilePaths() << FilePath() << FilePaths() << Example
+ << /*hasSourceCode=*/false << false << /*isHighlighted=*/true << ""
+ << "" << QStringList() << MetaData() << QStringList{"Featured"};
}
void tst_Examples::parsing()
{
QFETCH(QByteArray, data);
QFETCH(bool, isExamples);
+ QFETCH(QStringList, categories);
const ExampleItem expected = fetchItem();
const expected_str> result
= parseExamples(data,
@@ -154,7 +174,17 @@ void tst_Examples::parsing()
QCOMPARE(item.videoLength, expected.videoLength);
QCOMPARE(item.platforms, expected.platforms);
QCOMPARE(item.metaData, expected.metaData);
- qDeleteAll(*result);
+
+ const QList>> resultCategories = getCategories(*result,
+ true);
+ QCOMPARE(resultCategories.size(), categories.size());
+ for (int i = 0; i < resultCategories.size(); ++i) {
+ QCOMPARE(resultCategories.at(i).first.name, categories.at(i));
+ QCOMPARE(resultCategories.at(i).second.size(), 1);
+ }
+
+ for (const auto &category : resultCategories)
+ qDeleteAll(category.second);
}
QTEST_APPLESS_MAIN(tst_Examples)