Internal
Public Access
The subtitle and version line used palette(mid), a role meant for 3D bevel/shadow decoration, not text -- it has poor contrast against the window background in dark themes. Replaced with a color blended from the widget's actual text/window palette colors, so it stays readable (de-emphasized but never low-contrast) in either theme. Also: QCoreApplication::applicationVersion() was never being set anywhere, so the dialog always showed "Development build" regardless of the actual built version. CMake's PROJECT_VERSION is now exposed to the app via a compile definition and wired into setApplicationVersion() at startup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
118 lines
4.8 KiB
C++
118 lines
4.8 KiB
C++
#include "about_dialog.h"
|
|
|
|
#include <QApplication>
|
|
#include <QCoreApplication>
|
|
#include <QDialogButtonBox>
|
|
#include <QHBoxLayout>
|
|
#include <QLabel>
|
|
#include <QTextBrowser>
|
|
#include <QVBoxLayout>
|
|
|
|
namespace {
|
|
// palette(mid) is meant for 3D bevel/shadow decoration, not text — it has
|
|
// poor contrast against the window background in dark themes (barely
|
|
// legible). Blend the widget's actual text and window colors instead, so
|
|
// the result is reliably readable — de-emphasized relative to full-strength
|
|
// text, but never low-contrast — in either a light or dark theme.
|
|
QColor mutedTextColor(const QWidget* widget)
|
|
{
|
|
const QPalette pal = widget->palette();
|
|
const QColor text = pal.color(QPalette::WindowText);
|
|
const QColor background = pal.color(QPalette::Window);
|
|
constexpr qreal kTextWeight = 0.65;
|
|
|
|
auto blend = [kTextWeight](int textChannel, int backgroundChannel) {
|
|
return qBound(0,
|
|
qRound(textChannel * kTextWeight + backgroundChannel * (1.0 - kTextWeight)),
|
|
255);
|
|
};
|
|
|
|
return QColor(blend(text.red(), background.red()),
|
|
blend(text.green(), background.green()),
|
|
blend(text.blue(), background.blue()));
|
|
}
|
|
}
|
|
|
|
AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent)
|
|
{
|
|
setWindowTitle(QStringLiteral("About OrbitHub"));
|
|
setWindowIcon(QApplication::windowIcon());
|
|
resize(760, 560);
|
|
|
|
auto* layout = new QVBoxLayout(this);
|
|
layout->setContentsMargins(16, 16, 16, 16);
|
|
layout->setSpacing(12);
|
|
|
|
auto* headerRow = new QHBoxLayout();
|
|
headerRow->setSpacing(12);
|
|
|
|
auto* iconLabel = new QLabel(this);
|
|
iconLabel->setFixedSize(80, 80);
|
|
iconLabel->setPixmap(QApplication::windowIcon().pixmap(80, 80));
|
|
iconLabel->setAlignment(Qt::AlignCenter);
|
|
|
|
auto* titleColumn = new QVBoxLayout();
|
|
titleColumn->setSpacing(4);
|
|
|
|
auto* title = new QLabel(QStringLiteral("<h1 style='margin:0'>OrbitHub</h1>"), this);
|
|
auto* subtitle = new QLabel(
|
|
QStringLiteral("Unified remote session manager for SSH, RDP, and VNC workflows."),
|
|
this);
|
|
subtitle->setWordWrap(true);
|
|
subtitle->setStyleSheet(QStringLiteral("color: %1;").arg(mutedTextColor(this).name()));
|
|
|
|
const QString version = QCoreApplication::applicationVersion().trimmed().isEmpty()
|
|
? QStringLiteral("Development build")
|
|
: QCoreApplication::applicationVersion().trimmed();
|
|
auto* buildLine = new QLabel(
|
|
QStringLiteral("Version: %1 | Qt runtime linked dynamically").arg(version),
|
|
this);
|
|
buildLine->setStyleSheet(QStringLiteral("color: %1;").arg(mutedTextColor(this).name()));
|
|
|
|
titleColumn->addWidget(title);
|
|
titleColumn->addWidget(subtitle);
|
|
titleColumn->addWidget(buildLine);
|
|
titleColumn->addStretch();
|
|
|
|
headerRow->addWidget(iconLabel, 0, Qt::AlignTop);
|
|
headerRow->addLayout(titleColumn, 1);
|
|
|
|
auto* browser = new QTextBrowser(this);
|
|
browser->setOpenExternalLinks(true);
|
|
browser->setStyleSheet(QStringLiteral(
|
|
"QTextBrowser { border: 1px solid palette(midlight); border-radius: 8px; padding: 8px; }"));
|
|
browser->setHtml(QStringLiteral(R"(
|
|
<h3 style="margin-top:0">Third-Party Libraries</h3>
|
|
<p>OrbitHub uses the following external libraries:</p>
|
|
<table cellspacing="0" cellpadding="6" border="1" style="border-collapse:collapse; width:100%;">
|
|
<tr><th align="left">Library</th><th align="left">License</th><th align="left">Upstream</th></tr>
|
|
<tr><td>Qt 6 (Widgets / SQL)</td><td>LGPLv3 / GPLv3 / Commercial</td><td><a href="https://www.qt.io/licensing">qt.io/licensing</a></td></tr>
|
|
<tr><td>KodoTerm</td><td>MIT</td><td><a href="https://github.com/diegoiast/KodoTerm">github.com/diegoiast/KodoTerm</a></td></tr>
|
|
<tr><td>libvterm</td><td>MIT</td><td><a href="https://github.com/neovim/libvterm">github.com/neovim/libvterm</a></td></tr>
|
|
<tr><td>FreeRDP / WinPR</td><td>Apache License 2.0</td><td><a href="https://github.com/FreeRDP/FreeRDP">github.com/FreeRDP/FreeRDP</a></td></tr>
|
|
</table>
|
|
|
|
<h3>License Links</h3>
|
|
<ul>
|
|
<li><a href="https://www.gnu.org/licenses/lgpl-3.0.html">GNU LGPLv3 (gnu.org)</a></li>
|
|
<li><a href="https://opensource.org/licenses/MIT">MIT License (opensource.org)</a></li>
|
|
<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache License 2.0 (apache.org)</a></li>
|
|
</ul>
|
|
|
|
<h3>License Files In This Repository</h3>
|
|
<ul>
|
|
<li><code>third_party/KodoTerm/LICENSE</code></li>
|
|
<li><code>third_party/FreeRDP/LICENSE</code></li>
|
|
<li><code>LICENSE</code> (project license)</li>
|
|
</ul>
|
|
)"));
|
|
|
|
auto* buttons = new QDialogButtonBox(QDialogButtonBox::Close, this);
|
|
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
|
|
|
layout->addLayout(headerRow);
|
|
layout->addWidget(browser, 1);
|
|
layout->addWidget(buttons);
|
|
}
|