Browse Source
[cmake, desktop] feat: show dependencies and versions
[cmake, desktop] feat: show dependencies and versions
Signed-off-by: crueter <crueter@eden-emu.dev>pull/238/head
15 changed files with 433 additions and 9 deletions
-
27CMakeLists.txt
-
17CMakeModules/CPMUtil.cmake
-
21CMakeModules/GenerateDepHashes.cmake
-
2externals/CMakeLists.txt
-
2src/CMakeLists.txt
-
3src/common/CMakeLists.txt
-
20src/dep_hashes.h.in
-
4src/yuzu/CMakeLists.txt
-
2src/yuzu/aboutdialog.ui
-
121src/yuzu/deps_dialog.cpp
-
41src/yuzu/deps_dialog.h
-
166src/yuzu/deps_dialog.ui
-
9src/yuzu/main.cpp
-
1src/yuzu/main.h
-
6src/yuzu/main.ui
@ -0,0 +1,21 @@ |
|||
# SPDX-FileCopyrightText: 2025 Eden Emulator Project |
|||
# SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
get_property(NAMES GLOBAL PROPERTY CPM_PACKAGE_NAMES) |
|||
get_property(SHAS GLOBAL PROPERTY CPM_PACKAGE_SHAS) |
|||
get_property(URLS GLOBAL PROPERTY CPM_PACKAGE_URLS) |
|||
|
|||
list(LENGTH NAMES DEPS_LENGTH) |
|||
|
|||
list(JOIN NAMES "\",\n\t\"" DEP_NAME_DIRTY) |
|||
set(DEP_NAMES "\t\"${DEP_NAME_DIRTY}\"") |
|||
|
|||
list(JOIN SHAS "\",\n\t\"" DEP_SHAS_DIRTY) |
|||
set(DEP_SHAS "\t\"${DEP_SHAS_DIRTY}\"") |
|||
|
|||
list(JOIN URLS "\",\n\t\"" DEP_URLS_DIRTY) |
|||
set(DEP_URLS "\t\"${DEP_URLS_DIRTY}\"") |
|||
|
|||
configure_file(dep_hashes.h.in dep_hashes.h @ONLY) |
|||
target_sources(common PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/dep_hashes.h) |
|||
target_include_directories(common PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) |
|||
@ -0,0 +1,20 @@ |
|||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
namespace Common { |
|||
|
|||
static const constexpr std::array<const char *, @DEPS_LENGTH@> dep_names = { |
|||
@DEP_NAMES@ |
|||
}; |
|||
|
|||
static const constexpr std::array<const char *, @DEPS_LENGTH@> dep_hashes = { |
|||
@DEP_SHAS@ |
|||
}; |
|||
|
|||
static const constexpr std::array<const char *, @DEPS_LENGTH@> dep_urls = { |
|||
@DEP_URLS@ |
|||
}; |
|||
|
|||
} // namespace Common |
|||
@ -0,0 +1,121 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|||
|
|||
#include "yuzu/deps_dialog.h"
|
|||
#include <QAbstractTextDocumentLayout>
|
|||
#include <QDesktopServices>
|
|||
#include <QIcon>
|
|||
#include <QPainter>
|
|||
#include <QTableWidget>
|
|||
#include <QTextEdit>
|
|||
#include "dep_hashes.h"
|
|||
#include "ui_deps_dialog.h"
|
|||
#include <fmt/ranges.h>
|
|||
|
|||
DepsDialog::DepsDialog(QWidget* parent) |
|||
: QDialog(parent) |
|||
, ui{std::make_unique<Ui::DepsDialog>()} |
|||
{ |
|||
ui->setupUi(this); |
|||
|
|||
constexpr size_t rows = Common::dep_hashes.size(); |
|||
ui->tableDeps->setRowCount(rows); |
|||
|
|||
QStringList labels; |
|||
labels << tr("Dependency") << tr("Version"); |
|||
|
|||
ui->tableDeps->setHorizontalHeaderLabels(labels); |
|||
ui->tableDeps->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch); |
|||
ui->tableDeps->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Fixed); |
|||
ui->tableDeps->horizontalHeader()->setMinimumSectionSize(200); |
|||
|
|||
for (size_t i = 0; i < rows; ++i) { |
|||
const std::string name = Common::dep_names.at(i); |
|||
const std::string sha = Common::dep_hashes.at(i); |
|||
const std::string url = Common::dep_urls.at(i); |
|||
|
|||
std::string dependency = fmt::format("<a href=\"{}\">{}</a>", url, name); |
|||
|
|||
QTableWidgetItem *nameItem = new QTableWidgetItem(QString::fromStdString(dependency)); |
|||
QTableWidgetItem *shaItem = new QTableWidgetItem(QString::fromStdString(sha)); |
|||
|
|||
ui->tableDeps->setItem(i, 0, nameItem); |
|||
ui->tableDeps->setItem(i, 1, shaItem); |
|||
} |
|||
|
|||
ui->tableDeps->setItemDelegateForColumn(0, new LinkItemDelegate(this)); |
|||
} |
|||
|
|||
DepsDialog::~DepsDialog() = default; |
|||
|
|||
LinkItemDelegate::LinkItemDelegate(QObject *parent) |
|||
: QStyledItemDelegate(parent) |
|||
{} |
|||
|
|||
void LinkItemDelegate::paint(QPainter *painter, |
|||
const QStyleOptionViewItem &option, |
|||
const QModelIndex &index) const |
|||
{ |
|||
auto options = option; |
|||
initStyleOption(&options, index); |
|||
|
|||
QTextDocument doc; |
|||
QString html = index.data(Qt::DisplayRole).toString(); |
|||
doc.setHtml(html); |
|||
|
|||
options.text.clear(); |
|||
|
|||
painter->save(); |
|||
painter->translate(options.rect.topLeft()); |
|||
doc.drawContents(painter, QRectF(0, 0, options.rect.width(), options.rect.height())); |
|||
painter->restore(); |
|||
} |
|||
|
|||
QSize LinkItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const |
|||
{ |
|||
QStyleOptionViewItem options = option; |
|||
initStyleOption(&options, index); |
|||
|
|||
QTextDocument doc; |
|||
doc.setHtml(options.text); |
|||
doc.setTextWidth(options.rect.width()); |
|||
return QSize(doc.idealWidth(), doc.size().height()); |
|||
} |
|||
|
|||
bool LinkItemDelegate::editorEvent(QEvent *event, |
|||
QAbstractItemModel *model, |
|||
const QStyleOptionViewItem &option, |
|||
const QModelIndex &index) |
|||
{ |
|||
if (event->type() == QEvent::MouseButtonRelease) { |
|||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); |
|||
if (mouseEvent->button() == Qt::LeftButton) { |
|||
QString html = index.data(Qt::DisplayRole).toString(); |
|||
QTextDocument doc; |
|||
doc.setHtml(html); |
|||
doc.setTextWidth(option.rect.width()); |
|||
|
|||
// this is kinda silly but it werks
|
|||
QAbstractTextDocumentLayout *layout = doc.documentLayout(); |
|||
|
|||
QPoint pos = mouseEvent->pos() - option.rect.topLeft(); |
|||
int charPos = layout->hitTest(pos, Qt::ExactHit); |
|||
|
|||
if (charPos >= 0) { |
|||
QTextCursor cursor(&doc); |
|||
cursor.setPosition(charPos); |
|||
|
|||
QTextCharFormat format = cursor.charFormat(); |
|||
|
|||
if (format.isAnchor()) { |
|||
QString href = format.anchorHref(); |
|||
if (!href.isEmpty()) { |
|||
QDesktopServices::openUrl(QUrl(href)); |
|||
return true; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return QStyledItemDelegate::editorEvent(event, model, option, index); |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project |
|||
// SPDX-License-Identifier: GPL-3.0-or-later |
|||
|
|||
#pragma once |
|||
|
|||
#include <QDialog> |
|||
#include <QStyledItemDelegate> |
|||
#include <QTableView> |
|||
#include <memory> |
|||
|
|||
namespace Ui { class DepsDialog; } |
|||
|
|||
class DepsDialog : public QDialog |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
explicit DepsDialog(QWidget *parent); |
|||
~DepsDialog() override; |
|||
|
|||
private: |
|||
std::unique_ptr<Ui::DepsDialog> ui; |
|||
}; |
|||
|
|||
class LinkItemDelegate : public QStyledItemDelegate |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
explicit LinkItemDelegate(QObject *parent = 0); |
|||
|
|||
protected: |
|||
void paint(QPainter *painter, |
|||
const QStyleOptionViewItem &option, |
|||
const QModelIndex &index) const override; |
|||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; |
|||
bool editorEvent(QEvent *event, |
|||
QAbstractItemModel *model, |
|||
const QStyleOptionViewItem &option, |
|||
const QModelIndex &index) override; |
|||
}; |
|||
@ -0,0 +1,166 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<ui version="4.0"> |
|||
<class>DepsDialog</class> |
|||
<widget class="QDialog" name="DepsDialog"> |
|||
<property name="geometry"> |
|||
<rect> |
|||
<x>0</x> |
|||
<y>0</y> |
|||
<width>701</width> |
|||
<height>500</height> |
|||
</rect> |
|||
</property> |
|||
<property name="windowTitle"> |
|||
<string>Eden Dependencies</string> |
|||
</property> |
|||
<layout class="QVBoxLayout" name="verticalLayout_3"> |
|||
<item> |
|||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1"> |
|||
<item> |
|||
<layout class="QVBoxLayout" name="verticalLayout_2"> |
|||
<item> |
|||
<widget class="QLabel" name="labelLogo"> |
|||
<property name="sizePolicy"> |
|||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
|||
<horstretch>0</horstretch> |
|||
<verstretch>0</verstretch> |
|||
</sizepolicy> |
|||
</property> |
|||
<property name="maximumSize"> |
|||
<size> |
|||
<width>200</width> |
|||
<height>200</height> |
|||
</size> |
|||
</property> |
|||
<property name="text"> |
|||
<string/> |
|||
</property> |
|||
<property name="pixmap"> |
|||
<pixmap resource="../../dist/qt_themes/default/default.qrc">:/icons/default/256x256/eden.png</pixmap> |
|||
</property> |
|||
<property name="scaledContents"> |
|||
<bool>true</bool> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<spacer name="verticalSpacer"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Orientation::Vertical</enum> |
|||
</property> |
|||
<property name="sizeHint" stdset="0"> |
|||
<size> |
|||
<width>20</width> |
|||
<height>40</height> |
|||
</size> |
|||
</property> |
|||
</spacer> |
|||
</item> |
|||
</layout> |
|||
</item> |
|||
<item> |
|||
<layout class="QVBoxLayout" name="verticalLayout"> |
|||
<item> |
|||
<widget class="QLabel" name="labelEden"> |
|||
<property name="sizePolicy"> |
|||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
|||
<horstretch>0</horstretch> |
|||
<verstretch>0</verstretch> |
|||
</sizepolicy> |
|||
</property> |
|||
<property name="text"> |
|||
<string><html><head/><body><p><span style=" font-size:28pt;">Eden Dependencies</span></p></body></html></string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QLabel" name="labelInfo"> |
|||
<property name="sizePolicy"> |
|||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
|||
<horstretch>0</horstretch> |
|||
<verstretch>0</verstretch> |
|||
</sizepolicy> |
|||
</property> |
|||
<property name="text"> |
|||
<string><html><head/><body><p>The projects that make Eden possible</p></body></html></string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item> |
|||
<widget class="QTableWidget" name="tableDeps"> |
|||
<property name="editTriggers"> |
|||
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set> |
|||
</property> |
|||
<property name="alternatingRowColors"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<property name="selectionMode"> |
|||
<enum>QAbstractItemView::SelectionMode::NoSelection</enum> |
|||
</property> |
|||
<property name="columnCount"> |
|||
<number>2</number> |
|||
</property> |
|||
<attribute name="horizontalHeaderShowSortIndicator" stdset="0"> |
|||
<bool>false</bool> |
|||
</attribute> |
|||
<attribute name="verticalHeaderVisible"> |
|||
<bool>false</bool> |
|||
</attribute> |
|||
<column/> |
|||
<column/> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</item> |
|||
</layout> |
|||
</item> |
|||
<item> |
|||
<widget class="QDialogButtonBox" name="buttonBox"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Orientation::Horizontal</enum> |
|||
</property> |
|||
<property name="standardButtons"> |
|||
<set>QDialogButtonBox::StandardButton::Ok</set> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
<resources> |
|||
<include location="../../dist/qt_themes/default/default.qrc"/> |
|||
</resources> |
|||
<connections> |
|||
<connection> |
|||
<sender>buttonBox</sender> |
|||
<signal>accepted()</signal> |
|||
<receiver>DepsDialog</receiver> |
|||
<slot>accept()</slot> |
|||
<hints> |
|||
<hint type="sourcelabel"> |
|||
<x>20</x> |
|||
<y>20</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>20</x> |
|||
<y>20</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
<connection> |
|||
<sender>buttonBox</sender> |
|||
<signal>rejected()</signal> |
|||
<receiver>DepsDialog</receiver> |
|||
<slot>reject()</slot> |
|||
<hints> |
|||
<hint type="sourcelabel"> |
|||
<x>20</x> |
|||
<y>20</y> |
|||
</hint> |
|||
<hint type="destinationlabel"> |
|||
<x>20</x> |
|||
<y>20</y> |
|||
</hint> |
|||
</hints> |
|||
</connection> |
|||
</connections> |
|||
</ui> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue