forked from qt-creator/qt-creator
Vcpkg: Initial commit
This introduces the vcpkg support plugin. Initial features are: - Options page for defining vcpkg installation location - Search dialog for searching/selecting a package (incl. parsing autotest) - TextEditor that shows search/options toolbuttons - File wizard that creates a vcpkg.json manifest Change-Id: I098784100c869e0bb2ed6f60db4dedad559a142a Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -27,6 +27,7 @@ add_subdirectory(help)
|
|||||||
add_subdirectory(resourceeditor)
|
add_subdirectory(resourceeditor)
|
||||||
add_subdirectory(nim)
|
add_subdirectory(nim)
|
||||||
add_subdirectory(conan)
|
add_subdirectory(conan)
|
||||||
|
add_subdirectory(vcpkg)
|
||||||
|
|
||||||
# Level 4: (only depends on Level 3 and below)
|
# Level 4: (only depends on Level 3 and below)
|
||||||
add_subdirectory(classview)
|
add_subdirectory(classview)
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ Project {
|
|||||||
"todo/todo.qbs",
|
"todo/todo.qbs",
|
||||||
"updateinfo/updateinfo.qbs",
|
"updateinfo/updateinfo.qbs",
|
||||||
"valgrind/valgrind.qbs",
|
"valgrind/valgrind.qbs",
|
||||||
|
"vcpkg/vcpkg.qbs",
|
||||||
"vcsbase/vcsbase.qbs",
|
"vcsbase/vcsbase.qbs",
|
||||||
"webassembly/webassembly.qbs",
|
"webassembly/webassembly.qbs",
|
||||||
"welcome/welcome.qbs",
|
"welcome/welcome.qbs",
|
||||||
|
|||||||
16
src/plugins/vcpkg/CMakeLists.txt
Normal file
16
src/plugins/vcpkg/CMakeLists.txt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
add_qtc_plugin(Vcpkg
|
||||||
|
PLUGIN_DEPENDS Core ProjectExplorer
|
||||||
|
SOURCES
|
||||||
|
vcpkg.qrc
|
||||||
|
vcpkgconstants.h
|
||||||
|
vcpkgmanifesteditor.cpp vcpkgmanifesteditor.h
|
||||||
|
vcpkgplugin.cpp vcpkgplugin.h
|
||||||
|
vcpkgsearch.cpp vcpkgsearch.h
|
||||||
|
vcpkgsettings.cpp vcpkgsettings.h
|
||||||
|
)
|
||||||
|
|
||||||
|
extend_qtc_plugin(Vcpkg
|
||||||
|
CONDITION WITH_TESTS
|
||||||
|
SOURCES
|
||||||
|
vcpkg_test.cpp vcpkg_test.h
|
||||||
|
)
|
||||||
30
src/plugins/vcpkg/Vcpkg.json.in
Normal file
30
src/plugins/vcpkg/Vcpkg.json.in
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
\"Name\" : \"Vcpkg\",
|
||||||
|
\"Version\" : \"$$QTCREATOR_VERSION\",
|
||||||
|
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
|
||||||
|
\"Vendor\" : \"The Qt Company Ltd\",
|
||||||
|
\"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\",
|
||||||
|
\"License\" : [ \"Commercial Usage\",
|
||||||
|
\"\",
|
||||||
|
\"Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and The Qt Company.\",
|
||||||
|
\"\",
|
||||||
|
\"GNU General Public License Usage\",
|
||||||
|
\"\",
|
||||||
|
\"Alternatively, this plugin may be used under the terms of the GNU General Public License version 3 as published by the Free Software Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT included in the packaging of this plugin. Please review the following information to ensure the GNU General Public License requirements will be met: https://www.gnu.org/licenses/gpl-3.0.html.\"
|
||||||
|
],
|
||||||
|
\"Experimental\" : true,
|
||||||
|
\"Description\" : \"vcpkg integration.\",
|
||||||
|
\"Url\" : \"http://www.qt.io\",
|
||||||
|
$$dependencyList,
|
||||||
|
|
||||||
|
\"Mimetypes\" : [
|
||||||
|
\"<?xml version=\'1.0\' encoding=\'UTF-8\'?>\",
|
||||||
|
\"<mime-info xmlns=\'http://www.freedesktop.org/standards/shared-mime-info\'>\",
|
||||||
|
\" <mime-type type=\'application/vcpkg.manifest+json\'>\",
|
||||||
|
\" <sub-class-of type=\'application/json\'/>\",
|
||||||
|
\" <comment>Vcpkg Manifest File</comment>\",
|
||||||
|
\" <glob pattern=\'vcpkg.json\' weight=\'71\'/>\",
|
||||||
|
\" </mime-type>\",
|
||||||
|
\"</mime-info>\"
|
||||||
|
]
|
||||||
|
}
|
||||||
34
src/plugins/vcpkg/vcpkg.qbs
Normal file
34
src/plugins/vcpkg/vcpkg.qbs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import qbs 1.0
|
||||||
|
|
||||||
|
QtcPlugin {
|
||||||
|
name: "Vcpkg"
|
||||||
|
|
||||||
|
Depends { name: "Qt.widgets" }
|
||||||
|
Depends { name: "Utils" }
|
||||||
|
|
||||||
|
Depends { name: "Core" }
|
||||||
|
Depends { name: "ProjectExplorer" }
|
||||||
|
Depends { name: "TextEditor" }
|
||||||
|
|
||||||
|
files: [
|
||||||
|
"vcpkg.qrc",
|
||||||
|
"vcpkgconstants.h",
|
||||||
|
"vcpkgmanifesteditor.cpp",
|
||||||
|
"vcpkgmanifesteditor.h",
|
||||||
|
"vcpkgplugin.cpp",
|
||||||
|
"vcpkgplugin.h",
|
||||||
|
"vcpkgsearch.cpp",
|
||||||
|
"vcpkgsearch.h",
|
||||||
|
"vcpkgsettings.cpp",
|
||||||
|
"vcpkgsettings.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
Group {
|
||||||
|
name: "Unit tests"
|
||||||
|
condition: qtc.testsEnabled
|
||||||
|
files: [
|
||||||
|
"vcpkg_test.h",
|
||||||
|
"vcpkg_test.cpp",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/plugins/vcpkg/vcpkg.qrc
Normal file
6
src/plugins/vcpkg/vcpkg.qrc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/vcpkg">
|
||||||
|
<file>wizards/manifest/vcpkg.json.tpl</file>
|
||||||
|
<file>wizards/manifest/wizard.json</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
110
src/plugins/vcpkg/vcpkg_test.cpp
Normal file
110
src/plugins/vcpkg/vcpkg_test.cpp
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "vcpkg_test.h"
|
||||||
|
|
||||||
|
#include "vcpkgsearch.h"
|
||||||
|
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal {
|
||||||
|
|
||||||
|
VcpkgSearchTest::VcpkgSearchTest(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
VcpkgSearchTest::~VcpkgSearchTest() = default;
|
||||||
|
|
||||||
|
void VcpkgSearchTest::testVcpkgJsonParser_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("vcpkgManifestJsonData");
|
||||||
|
QTest::addColumn<QString>("name");
|
||||||
|
QTest::addColumn<QString>("version");
|
||||||
|
QTest::addColumn<QString>("license");
|
||||||
|
QTest::addColumn<QString>("shortDescription");
|
||||||
|
QTest::addColumn<QStringList>("description");
|
||||||
|
QTest::addColumn<QUrl>("homepage");
|
||||||
|
QTest::addColumn<bool>("success");
|
||||||
|
|
||||||
|
QTest::newRow("cimg, version, short description")
|
||||||
|
<< R"({
|
||||||
|
"name": "cimg",
|
||||||
|
"version": "2.9.9",
|
||||||
|
"description": "The CImg Library is a small, open-source, and modern C++ toolkit for image processing",
|
||||||
|
"homepage": "https://github.com/dtschump/CImg",
|
||||||
|
"dependencies": [
|
||||||
|
{
|
||||||
|
"name": "vcpkg-cmake",
|
||||||
|
"host": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})"
|
||||||
|
<< "cimg"
|
||||||
|
<< "2.9.9"
|
||||||
|
<< ""
|
||||||
|
<< "The CImg Library is a small, open-source, and modern C++ toolkit for image processing"
|
||||||
|
<< QStringList()
|
||||||
|
<< QUrl::fromUserInput("https://github.com/dtschump/CImg")
|
||||||
|
<< true;
|
||||||
|
|
||||||
|
QTest::newRow("catch-classic, version-string, complete description")
|
||||||
|
<< R"({
|
||||||
|
"name": "catch-classic",
|
||||||
|
"version-string": "1.12.2",
|
||||||
|
"port-version": 1,
|
||||||
|
"description": [
|
||||||
|
"A modern, header-only test framework for unit tests",
|
||||||
|
"This is specifically the legacy 1.x branch provided for compatibility",
|
||||||
|
"with older compilers."
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/catchorg/Catch2"
|
||||||
|
})"
|
||||||
|
<< "catch-classic"
|
||||||
|
<< "1.12.2"
|
||||||
|
<< ""
|
||||||
|
<< "A modern, header-only test framework for unit tests"
|
||||||
|
<< QStringList({"This is specifically the legacy 1.x branch provided for compatibility",
|
||||||
|
"with older compilers."})
|
||||||
|
<< QUrl::fromUserInput("https://github.com/catchorg/Catch2")
|
||||||
|
<< true;
|
||||||
|
|
||||||
|
QTest::newRow("Incomplete")
|
||||||
|
<< R"({
|
||||||
|
"version-semver": "1.0",
|
||||||
|
"description": "foo",
|
||||||
|
"license": "WTFPL"
|
||||||
|
})"
|
||||||
|
<< ""
|
||||||
|
<< "1.0"
|
||||||
|
<< "WTFPL"
|
||||||
|
<< "foo"
|
||||||
|
<< QStringList()
|
||||||
|
<< QUrl()
|
||||||
|
<< false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VcpkgSearchTest::testVcpkgJsonParser()
|
||||||
|
{
|
||||||
|
QFETCH(QString, vcpkgManifestJsonData);
|
||||||
|
QFETCH(QString, name);
|
||||||
|
QFETCH(QString, version);
|
||||||
|
QFETCH(QString, license);
|
||||||
|
QFETCH(QString, shortDescription);
|
||||||
|
QFETCH(QStringList, description);
|
||||||
|
QFETCH(QUrl, homepage);
|
||||||
|
QFETCH(bool, success);
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
const Search::VcpkgManifest mf =
|
||||||
|
Search::parseVcpkgManifest(vcpkgManifestJsonData.toUtf8(), &ok);
|
||||||
|
|
||||||
|
QCOMPARE(mf.name, name);
|
||||||
|
QCOMPARE(mf.version, version);
|
||||||
|
QCOMPARE(mf.license, license);
|
||||||
|
QCOMPARE(mf.shortDescription, shortDescription);
|
||||||
|
QCOMPARE(mf.description, description);
|
||||||
|
QCOMPARE(mf.homepage, homepage);
|
||||||
|
QCOMPARE(ok, success);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal
|
||||||
24
src/plugins/vcpkg/vcpkg_test.h
Normal file
24
src/plugins/vcpkg/vcpkg_test.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <coreplugin/dialogs/ioptionspage.h>
|
||||||
|
#include <utils/aspects.h>
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal {
|
||||||
|
|
||||||
|
class VcpkgSearchTest : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
VcpkgSearchTest(QObject *parent = nullptr);
|
||||||
|
~VcpkgSearchTest();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void testVcpkgJsonParser_data();
|
||||||
|
void testVcpkgJsonParser();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal
|
||||||
14
src/plugins/vcpkg/vcpkgconstants.h
Normal file
14
src/plugins/vcpkg/vcpkgconstants.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Vcpkg::Constants {
|
||||||
|
|
||||||
|
const char TOOLSSETTINGSPAGE_ID[] = "Vcpkg.VcpkgSettings";
|
||||||
|
const char WEBSITE_URL[] = "https://vcpkg.io/";
|
||||||
|
const char ENVVAR_VCPKG_ROOT[] = "VCPKG_ROOT";
|
||||||
|
const char VCPKGMANIFEST_EDITOR_ID[] = "Vcpkg.VcpkgManifestEditor";
|
||||||
|
const char VCPKGMANIFEST_MIMETYPE[] = "application/vcpkg.manifest+json";
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Constants
|
||||||
71
src/plugins/vcpkg/vcpkgmanifesteditor.cpp
Normal file
71
src/plugins/vcpkg/vcpkgmanifesteditor.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "vcpkgmanifesteditor.h"
|
||||||
|
|
||||||
|
#include "vcpkgconstants.h"
|
||||||
|
#include "vcpkgsearch.h"
|
||||||
|
#include "vcpkgsettings.h"
|
||||||
|
#include "vcpkgtr.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <texteditor/textdocument.h>
|
||||||
|
|
||||||
|
#include <QToolBar>
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal {
|
||||||
|
|
||||||
|
class VcpkgManifestEditorWidget : public TextEditor::TextEditorWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VcpkgManifestEditorWidget()
|
||||||
|
{
|
||||||
|
m_searchPkgAction = toolBar()->addAction(Utils::Icons::ZOOM_TOOLBAR.icon(),
|
||||||
|
Tr::tr("Search package..."));
|
||||||
|
connect(m_searchPkgAction, &QAction::triggered, this, [this] {
|
||||||
|
const Search::VcpkgManifest package = Search::showVcpkgPackageSearchDialog();
|
||||||
|
if (!package.name.isEmpty())
|
||||||
|
textCursor().insertText(package.name);
|
||||||
|
});
|
||||||
|
updateToolBar();
|
||||||
|
|
||||||
|
QAction *optionsAction = toolBar()->addAction(Utils::Icons::SETTINGS_TOOLBAR.icon(),
|
||||||
|
Core::ICore::msgShowOptionsDialog());
|
||||||
|
connect(optionsAction, &QAction::triggered, [] {
|
||||||
|
Core::ICore::showOptionsDialog(Constants::TOOLSSETTINGSPAGE_ID);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&VcpkgSettings::instance()->vcpkgRoot, &Utils::BaseAspect::changed,
|
||||||
|
this, &VcpkgManifestEditorWidget::updateToolBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateToolBar()
|
||||||
|
{
|
||||||
|
m_searchPkgAction->setEnabled(VcpkgSettings::instance()->vcpkgRootValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QAction *m_searchPkgAction;
|
||||||
|
};
|
||||||
|
|
||||||
|
static TextEditor::TextDocument *createVcpkgManifestDocument()
|
||||||
|
{
|
||||||
|
auto doc = new TextEditor::TextDocument;
|
||||||
|
doc->setId(Constants::VCPKGMANIFEST_EDITOR_ID);
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
VcpkgManifestEditorFactory::VcpkgManifestEditorFactory()
|
||||||
|
{
|
||||||
|
setId(Constants::VCPKGMANIFEST_EDITOR_ID);
|
||||||
|
setDisplayName(Tr::tr("Vcpkg Manifest Editor"));
|
||||||
|
addMimeType(Constants::VCPKGMANIFEST_MIMETYPE);
|
||||||
|
setDocumentCreator(createVcpkgManifestDocument);
|
||||||
|
setEditorWidgetCreator([] { return new VcpkgManifestEditorWidget; });
|
||||||
|
setUseGenericHighlighter(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal
|
||||||
16
src/plugins/vcpkg/vcpkgmanifesteditor.h
Normal file
16
src/plugins/vcpkg/vcpkgmanifesteditor.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <texteditor/texteditor.h>
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal {
|
||||||
|
|
||||||
|
class VcpkgManifestEditorFactory : public TextEditor::TextEditorFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VcpkgManifestEditorFactory();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal
|
||||||
38
src/plugins/vcpkg/vcpkgplugin.cpp
Normal file
38
src/plugins/vcpkg/vcpkgplugin.cpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "vcpkgplugin.h"
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
#include "vcpkg_test.h"
|
||||||
|
#endif // WITH_TESTS
|
||||||
|
#include "vcpkgmanifesteditor.h"
|
||||||
|
#include "vcpkgsettings.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal {
|
||||||
|
|
||||||
|
class VcpkgPluginPrivate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VcpkgManifestEditorFactory manifestEditorFactory;
|
||||||
|
VcpkgSettingsPage settingsPage;
|
||||||
|
};
|
||||||
|
|
||||||
|
VcpkgPlugin::~VcpkgPlugin()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VcpkgPlugin::initialize()
|
||||||
|
{
|
||||||
|
d = new VcpkgPluginPrivate;
|
||||||
|
ProjectExplorer::JsonWizardFactory::addWizardPath(":/vcpkg/wizards/");
|
||||||
|
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
addTest<VcpkgSearchTest>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal
|
||||||
26
src/plugins/vcpkg/vcpkgplugin.h
Normal file
26
src/plugins/vcpkg/vcpkgplugin.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
|
namespace ProjectExplorer { class Project; }
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal {
|
||||||
|
|
||||||
|
class VcpkgPlugin final : public ExtensionSystem::IPlugin
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "Vcpkg.json")
|
||||||
|
|
||||||
|
public:
|
||||||
|
~VcpkgPlugin();
|
||||||
|
|
||||||
|
void initialize() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class VcpkgPluginPrivate *d = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal
|
||||||
214
src/plugins/vcpkg/vcpkgsearch.cpp
Normal file
214
src/plugins/vcpkg/vcpkgsearch.cpp
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "vcpkgsearch.h"
|
||||||
|
|
||||||
|
#include "qpushbutton.h"
|
||||||
|
#include "vcpkgsettings.h"
|
||||||
|
#include "vcpkgtr.h"
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/fancylineedit.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/itemviews.h>
|
||||||
|
#include <utils/layoutbuilder.h>
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QTextBrowser>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal::Search {
|
||||||
|
|
||||||
|
class VcpkgPackageSearchDialog : public QDialog
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit VcpkgPackageSearchDialog(QWidget *parent);
|
||||||
|
|
||||||
|
VcpkgManifest selectedPackage() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void listPackages(const QString &filter);
|
||||||
|
void showPackageDetails(const QString &packageName);
|
||||||
|
|
||||||
|
VcpkgManifests m_allPackages;
|
||||||
|
VcpkgManifest m_selectedPackage;
|
||||||
|
|
||||||
|
FancyLineEdit *m_packagesFilter;
|
||||||
|
ListWidget *m_packagesList;
|
||||||
|
QLineEdit *m_vcpkgName;
|
||||||
|
QLabel *m_vcpkgVersion;
|
||||||
|
QLabel *m_vcpkgLicense;
|
||||||
|
QTextBrowser *m_vcpkgDescription;
|
||||||
|
QLabel *m_vcpkgHomepage;
|
||||||
|
QDialogButtonBox *m_buttonBox;
|
||||||
|
};
|
||||||
|
|
||||||
|
VcpkgPackageSearchDialog::VcpkgPackageSearchDialog(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
{
|
||||||
|
resize(920, 400);
|
||||||
|
|
||||||
|
m_packagesFilter = new FancyLineEdit;
|
||||||
|
m_packagesFilter->setFiltering(true);
|
||||||
|
m_packagesFilter->setFocus();
|
||||||
|
m_packagesFilter->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
|
||||||
|
|
||||||
|
m_packagesList = new ListWidget;
|
||||||
|
m_packagesList->setMaximumWidth(300);
|
||||||
|
|
||||||
|
m_vcpkgName = new QLineEdit;
|
||||||
|
m_vcpkgName->setReadOnly(true);
|
||||||
|
|
||||||
|
m_vcpkgVersion = new QLabel;
|
||||||
|
m_vcpkgLicense = new QLabel;
|
||||||
|
m_vcpkgDescription = new QTextBrowser;
|
||||||
|
|
||||||
|
m_vcpkgHomepage = new QLabel;
|
||||||
|
m_vcpkgHomepage->setOpenExternalLinks(true);
|
||||||
|
m_vcpkgHomepage->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
|
||||||
|
m_vcpkgHomepage->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
|
|
||||||
|
m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Close);
|
||||||
|
|
||||||
|
using namespace Utils::Layouting;
|
||||||
|
Column {
|
||||||
|
Row {
|
||||||
|
Column {
|
||||||
|
m_packagesFilter,
|
||||||
|
m_packagesList,
|
||||||
|
},
|
||||||
|
Form {
|
||||||
|
Tr::tr("Name:"), m_vcpkgName, br,
|
||||||
|
Tr::tr("Version:"), m_vcpkgVersion, br,
|
||||||
|
Tr::tr("License:"), m_vcpkgLicense, br,
|
||||||
|
Tr::tr("Description:"), m_vcpkgDescription, br,
|
||||||
|
Tr::tr("Homepage:"), m_vcpkgHomepage, br,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
m_buttonBox,
|
||||||
|
}.attachTo(this);
|
||||||
|
|
||||||
|
m_allPackages = vcpkgManifests(VcpkgSettings::instance()->vcpkgRoot.filePath());
|
||||||
|
|
||||||
|
listPackages({});
|
||||||
|
|
||||||
|
connect(m_packagesFilter, &FancyLineEdit::filterChanged,
|
||||||
|
this, &VcpkgPackageSearchDialog::listPackages);
|
||||||
|
connect(m_packagesList, &ListWidget::currentTextChanged,
|
||||||
|
this, &VcpkgPackageSearchDialog::showPackageDetails);
|
||||||
|
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||||
|
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
VcpkgManifest VcpkgPackageSearchDialog::selectedPackage() const
|
||||||
|
{
|
||||||
|
return m_selectedPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VcpkgPackageSearchDialog::listPackages(const QString &filter)
|
||||||
|
{
|
||||||
|
const VcpkgManifests filteredPackages = filtered(m_allPackages,
|
||||||
|
[&filter] (const VcpkgManifest &package) {
|
||||||
|
return filter.isEmpty()
|
||||||
|
|| package.name.contains(filter, Qt::CaseInsensitive)
|
||||||
|
|| package.shortDescription.contains(filter, Qt::CaseInsensitive)
|
||||||
|
|| package.description.contains(filter, Qt::CaseInsensitive);
|
||||||
|
});
|
||||||
|
QStringList names = transform(filteredPackages, [] (const VcpkgManifest &package) {
|
||||||
|
return package.name;
|
||||||
|
});
|
||||||
|
names.sort();
|
||||||
|
m_packagesList->clear();
|
||||||
|
m_packagesList->addItems(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VcpkgPackageSearchDialog::showPackageDetails(const QString &packageName)
|
||||||
|
{
|
||||||
|
const VcpkgManifest manifest = findOrDefault(m_allPackages,
|
||||||
|
[&packageName] (const VcpkgManifest &m) {
|
||||||
|
return m.name == packageName;
|
||||||
|
});
|
||||||
|
|
||||||
|
m_vcpkgName->setText(manifest.name);
|
||||||
|
m_vcpkgVersion->setText(manifest.version);
|
||||||
|
m_vcpkgLicense->setText(manifest.license);
|
||||||
|
QString description = manifest.shortDescription;
|
||||||
|
if (!manifest.description.isEmpty())
|
||||||
|
description.append("<p>" + manifest.description.join("</p><p>") + "</p>");
|
||||||
|
m_vcpkgDescription->setText(description);
|
||||||
|
m_vcpkgHomepage->setText(QString::fromLatin1("<a href=\"%1\">%1</a>")
|
||||||
|
.arg(manifest.homepage.toDisplayString()));
|
||||||
|
|
||||||
|
m_selectedPackage = manifest;
|
||||||
|
m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!manifest.name.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
VcpkgManifest parseVcpkgManifest(const QByteArray &vcpkgManifestJsonData, bool *ok)
|
||||||
|
{
|
||||||
|
// https://learn.microsoft.com/en-us/vcpkg/reference/vcpkg-json
|
||||||
|
VcpkgManifest result;
|
||||||
|
const QJsonObject jsonObject = QJsonDocument::fromJson(vcpkgManifestJsonData).object();
|
||||||
|
if (const QJsonValue name = jsonObject.value("name"); !name.isUndefined())
|
||||||
|
result.name = name.toString();
|
||||||
|
for (const char *key : {"version", "version-semver", "version-date", "version-string"} ) {
|
||||||
|
if (const QJsonValue ver = jsonObject.value(QLatin1String(key)); !ver.isUndefined()) {
|
||||||
|
result.version = ver.toString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (const QJsonValue license = jsonObject.value("license"); !license.isUndefined())
|
||||||
|
result.license = license.toString();
|
||||||
|
if (const QJsonValue description = jsonObject.value("description"); !description.isUndefined()) {
|
||||||
|
if (description.isArray()) {
|
||||||
|
const QJsonArray descriptionLines = description.toArray();
|
||||||
|
for (const QJsonValue &val : descriptionLines) {
|
||||||
|
const QString line = val.toString();
|
||||||
|
if (result.shortDescription.isEmpty()) {
|
||||||
|
result.shortDescription = line;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.description.append(line);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.shortDescription = description.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (const QJsonValue homepage = jsonObject.value("homepage"); !homepage.isUndefined())
|
||||||
|
result.homepage = QUrl::fromUserInput(homepage.toString());
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
*ok = !(result.name.isEmpty() || result.version.isEmpty());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VcpkgManifests vcpkgManifests(const FilePath &vcpkgRoot)
|
||||||
|
{
|
||||||
|
const FilePath portsDir = vcpkgRoot / "ports";
|
||||||
|
VcpkgManifests result;
|
||||||
|
const FilePaths manifestFiles =
|
||||||
|
portsDir.dirEntries({{"vcpkg.json"}, QDir::Files, QDirIterator::Subdirectories});
|
||||||
|
for (const FilePath &manifestFile : manifestFiles) {
|
||||||
|
FileReader reader;
|
||||||
|
if (reader.fetch(manifestFile)) {
|
||||||
|
const QByteArray &manifestData = reader.data();
|
||||||
|
const VcpkgManifest manifest = parseVcpkgManifest(manifestData);
|
||||||
|
result.append(manifest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VcpkgManifest showVcpkgPackageSearchDialog(QWidget *parent)
|
||||||
|
{
|
||||||
|
VcpkgPackageSearchDialog dlg(parent ? parent : Core::ICore::dialogParent());
|
||||||
|
return (dlg.exec() == QDialog::Accepted) ? dlg.selectedPackage() : VcpkgManifest();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal::Search
|
||||||
29
src/plugins/vcpkg/vcpkgsearch.h
Normal file
29
src/plugins/vcpkg/vcpkgsearch.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <coreplugin/dialogs/ioptionspage.h>
|
||||||
|
#include <utils/aspects.h>
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal::Search {
|
||||||
|
|
||||||
|
struct VcpkgManifest
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QString version;
|
||||||
|
QString license;
|
||||||
|
QString shortDescription;
|
||||||
|
QStringList description;
|
||||||
|
QUrl homepage;
|
||||||
|
};
|
||||||
|
|
||||||
|
using VcpkgManifests = QList<VcpkgManifest>;
|
||||||
|
|
||||||
|
VcpkgManifest parseVcpkgManifest(const QByteArray &vcpkgManifestJsonData, bool *ok = nullptr);
|
||||||
|
VcpkgManifests vcpkgManifests(const Utils::FilePath &vcpkgRoot);
|
||||||
|
VcpkgManifest showVcpkgPackageSearchDialog(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal::Search
|
||||||
80
src/plugins/vcpkg/vcpkgsettings.cpp
Normal file
80
src/plugins/vcpkg/vcpkgsettings.cpp
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#include "vcpkgsettings.h"
|
||||||
|
|
||||||
|
#include "vcpkgconstants.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <cmakeprojectmanager/cmakeprojectconstants.h>
|
||||||
|
|
||||||
|
#include <utils/aspects.h>
|
||||||
|
#include <utils/environment.h>
|
||||||
|
#include <utils/layoutbuilder.h>
|
||||||
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QToolButton>
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal {
|
||||||
|
|
||||||
|
VcpkgSettings::VcpkgSettings()
|
||||||
|
{
|
||||||
|
setSettingsGroup("Vcpkg");
|
||||||
|
|
||||||
|
registerAspect(&vcpkgRoot);
|
||||||
|
vcpkgRoot.setSettingsKey("VcpkgRoot");
|
||||||
|
vcpkgRoot.setDisplayStyle(Utils::StringAspect::PathChooserDisplay);
|
||||||
|
vcpkgRoot.setExpectedKind(Utils::PathChooser::ExistingDirectory);
|
||||||
|
vcpkgRoot.setDefaultValue(Utils::qtcEnvironmentVariable(Constants::ENVVAR_VCPKG_ROOT));
|
||||||
|
|
||||||
|
readSettings(Core::ICore::settings());
|
||||||
|
}
|
||||||
|
|
||||||
|
VcpkgSettings *VcpkgSettings::instance()
|
||||||
|
{
|
||||||
|
static VcpkgSettings s;
|
||||||
|
return &s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VcpkgSettings::vcpkgRootValid() const
|
||||||
|
{
|
||||||
|
return (vcpkgRoot.filePath() / "vcpkg").withExecutableSuffix().isExecutableFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
VcpkgSettingsPage::VcpkgSettingsPage()
|
||||||
|
{
|
||||||
|
setId(Constants::TOOLSSETTINGSPAGE_ID);
|
||||||
|
setDisplayName("Vcpkg");
|
||||||
|
setCategory(CMakeProjectManager::Constants::Settings::CATEGORY);
|
||||||
|
|
||||||
|
setLayouter([] (QWidget *widget) {
|
||||||
|
auto websiteButton = new QToolButton;
|
||||||
|
websiteButton->setIcon(Utils::Icons::ONLINE.icon());
|
||||||
|
websiteButton->setToolTip(Constants::WEBSITE_URL);
|
||||||
|
|
||||||
|
using namespace Utils::Layouting;
|
||||||
|
Column {
|
||||||
|
Group {
|
||||||
|
title(tr("Vcpkg installation")),
|
||||||
|
Form {
|
||||||
|
Utils::PathChooser::label(),
|
||||||
|
Span{ 2, Row{ VcpkgSettings::instance()->vcpkgRoot, websiteButton} },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
st,
|
||||||
|
}.attachTo(widget);
|
||||||
|
|
||||||
|
connect(websiteButton, &QAbstractButton::clicked, [] {
|
||||||
|
QDesktopServices::openUrl(QUrl::fromUserInput(Constants::WEBSITE_URL));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void VcpkgSettingsPage::apply()
|
||||||
|
{
|
||||||
|
VcpkgSettings::instance()->writeSettings(Core::ICore::settings());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal
|
||||||
30
src/plugins/vcpkg/vcpkgsettings.h
Normal file
30
src/plugins/vcpkg/vcpkgsettings.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <coreplugin/dialogs/ioptionspage.h>
|
||||||
|
#include <utils/aspects.h>
|
||||||
|
|
||||||
|
namespace Vcpkg::Internal {
|
||||||
|
|
||||||
|
class VcpkgSettings : public Utils::AspectContainer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VcpkgSettings();
|
||||||
|
|
||||||
|
static VcpkgSettings *instance();
|
||||||
|
bool vcpkgRootValid() const;
|
||||||
|
|
||||||
|
Utils::StringAspect vcpkgRoot;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VcpkgSettingsPage final : public Core::IOptionsPage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VcpkgSettingsPage();
|
||||||
|
|
||||||
|
void apply() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vcpkg::Internal
|
||||||
15
src/plugins/vcpkg/vcpkgtr.h
Normal file
15
src/plugins/vcpkg/vcpkgtr.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// Copyright (C) 2023 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
namespace Vcpkg {
|
||||||
|
|
||||||
|
struct Tr
|
||||||
|
{
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(Vcpkg)
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Vcpkg
|
||||||
6
src/plugins/vcpkg/wizards/manifest/vcpkg.json.tpl
Normal file
6
src/plugins/vcpkg/wizards/manifest/vcpkg.json.tpl
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
|
||||||
|
"name": "%{Name}",
|
||||||
|
"version-string": "%{VersionString}",
|
||||||
|
%{Dependencies}
|
||||||
|
}
|
||||||
80
src/plugins/vcpkg/wizards/manifest/wizard.json
Normal file
80
src/plugins/vcpkg/wizards/manifest/wizard.json
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"supportedProjectTypes": [ ],
|
||||||
|
"id": "VcpkgManifest.Json",
|
||||||
|
"category": "U.VcpkgManifest",
|
||||||
|
"trDescription": "Creates a vcpkg.json manifest file.",
|
||||||
|
"trDisplayName": "vcpkg.json Manifest File",
|
||||||
|
"trDisplayCategory": "vcpkg",
|
||||||
|
"iconText": "json",
|
||||||
|
|
||||||
|
"options": [
|
||||||
|
{ "key": "InitialFileName", "value": "vcpkg.json" },
|
||||||
|
{ "key": "TargetPath", "value": "%{Path}" }
|
||||||
|
],
|
||||||
|
|
||||||
|
"pages":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"trDisplayName": "Location",
|
||||||
|
"trShortTitle": "Location",
|
||||||
|
"typeId": "File"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"trDisplayName": "vcpkg.json Manifest File",
|
||||||
|
"trShortTitle": "Manifest fields",
|
||||||
|
"typeId": "Fields",
|
||||||
|
"data":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Name",
|
||||||
|
"trDisplayName": "Name:",
|
||||||
|
"mandatory": true,
|
||||||
|
"type": "LineEdit",
|
||||||
|
"data":
|
||||||
|
{
|
||||||
|
"trText": "mypackage",
|
||||||
|
"validator": "^[a-z_0-9]+$"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VersionString",
|
||||||
|
"trDisplayName": "Version string:",
|
||||||
|
"mandatory": true,
|
||||||
|
"type": "LineEdit",
|
||||||
|
"data":
|
||||||
|
{
|
||||||
|
"trText": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dependencies",
|
||||||
|
"trDisplayName": "Dependencies:",
|
||||||
|
"mandatory": false,
|
||||||
|
"type": "TextEdit",
|
||||||
|
"data":
|
||||||
|
{
|
||||||
|
"trText": " \"dependencies\": [\n \"fmt\"\n ]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"trDisplayName": "Project Management",
|
||||||
|
"trShortTitle": "Summary",
|
||||||
|
"typeId": "Summary"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generators":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"typeId": "File",
|
||||||
|
"data":
|
||||||
|
{
|
||||||
|
"source": "vcpkg.json.tpl",
|
||||||
|
"target": "%{Path}/vcpkg.json",
|
||||||
|
"openInEditor": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user