Skip to content

Commit 95c0cff

Browse files
committed
qt: Add Settings -> Integrate... menu item
1 parent f14ca7d commit 95c0cff

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

src/qt/bitcoingui.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <qt/clientmodel.h>
99
#include <qt/createwalletdialog.h>
1010
#include <qt/guiconstants.h>
11+
#include <qt/guifileutil.h>
1112
#include <qt/guiutil.h>
1213
#include <qt/modaloverlay.h>
1314
#include <qt/networkstyle.h>
@@ -479,6 +480,21 @@ void BitcoinGUI::createMenuBar()
479480
settings->addSeparator();
480481
}
481482
settings->addAction(optionsAction);
483+
#ifdef Q_OS_LINUX
484+
if (gArgs.GetChainName() != CBaseChainParams::REGTEST) {
485+
settings->addSeparator();
486+
QAction* integrate_with_DE = settings->addAction(tr("&Integrate with desktop environment"));
487+
connect(integrate_with_DE, &QAction::triggered, [this] {
488+
if (GUIUtil::IntegrateWithDesktopEnvironment(m_network_style->getTrayAndWindowIcon())) {
489+
QMessageBox::information(this, tr("Application registered"),
490+
tr("Now you are able to launch " PACKAGE_NAME " from the desktop menu."));
491+
} else {
492+
QMessageBox::warning(this, tr("Application registration failed"),
493+
tr("" PACKAGE_NAME " failed integration with your desktop environment."));
494+
}
495+
});
496+
}
497+
#endif // Q_OS_LINUX
482498

483499
QMenu* window_menu = appMenuBar->addMenu(tr("&Window"));
484500

src/qt/guifileutil.cpp

+79
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#endif // WIN32
1818

1919
#ifdef Q_OS_LINUX
20+
#include <cassert>
2021
#include <stdlib.h>
2122
#include <unistd.h>
2223
#endif // Q_OS_LINUX
@@ -25,6 +26,7 @@
2526
#include <QDir>
2627
#include <QFileDialog>
2728
#include <QFileInfo>
29+
#include <QPixmap>
2830
#include <QRegExp>
2931
#include <QStandardPaths>
3032
#include <QString>
@@ -44,11 +46,88 @@ std::string GetExecutablePathAsString()
4446
exe_path[r] = '\0';
4547
return exe_path;
4648
}
49+
50+
fs::path GetUserApplicationsDir()
51+
{
52+
const char* home_dir = getenv("HOME");
53+
if (!home_dir) return fs::path();
54+
return fs::path(home_dir) / ".local" / "share" / "applications";
55+
}
56+
57+
fs::path GetDesktopFilePath(std::string chain)
58+
{
59+
const auto app_dir = GetUserApplicationsDir();
60+
if (app_dir.empty()) return fs::path();
61+
if (!chain.empty()) {
62+
chain = "_" + chain;
63+
}
64+
return app_dir / strprintf("org.bitcoincore.BitcoinQt%s.desktop", chain);
65+
}
66+
67+
fs::path GetUserIconsDir()
68+
{
69+
const char* home_dir = getenv("HOME");
70+
if (!home_dir) return fs::path();
71+
return fs::path(home_dir) / ".local" / "share" / "icons";
72+
}
73+
74+
fs::path GetIconPath(std::string chain)
75+
{
76+
const auto icons_dir = GetUserIconsDir();
77+
if (icons_dir.empty()) return fs::path();
78+
if (!chain.empty()) {
79+
chain = "-" + chain;
80+
}
81+
return icons_dir / strprintf("bitcoin%s.png", chain);
82+
}
4783
#endif // Q_OS_LINUX
4884
} // namespace
4985

5086
namespace GUIUtil {
5187

88+
#ifdef Q_OS_LINUX
89+
bool IntegrateWithDesktopEnvironment(QIcon icon)
90+
{
91+
std::string chain = gArgs.GetChainName();
92+
assert(chain == CBaseChainParams::MAIN || chain == CBaseChainParams::TESTNET);
93+
if (chain == CBaseChainParams::MAIN) {
94+
chain.clear();
95+
}
96+
97+
const auto icon_path = GetIconPath(chain);
98+
if (icon_path.empty() || !icon.pixmap(256).save(boostPathToQString(icon_path))) return false;
99+
const auto exe_path = GetExecutablePathAsString();
100+
if (exe_path.empty()) return false;
101+
const auto desktop_file_path = GetDesktopFilePath(chain);
102+
if (desktop_file_path.empty()) return false;
103+
fsbridge::ofstream desktop_file(desktop_file_path, std::ios_base::out | std::ios_base::trunc);
104+
if (!desktop_file.good()) return false;
105+
106+
desktop_file << "[Desktop Entry]\n";
107+
desktop_file << "Type=Application\n";
108+
desktop_file << "Version=1.1\n";
109+
desktop_file << "GenericName=Bitcoin client\n";
110+
desktop_file << "Comment=Bitcoin full node and wallet\n";
111+
desktop_file << strprintf("Icon=%s\n", icon_path.stem().string());
112+
desktop_file << strprintf("TryExec=%s\n", exe_path);
113+
desktop_file << "Categories=Network;Office;Finance;\n";
114+
if (chain.empty()) {
115+
desktop_file << "Name=" PACKAGE_NAME "\n";
116+
desktop_file << strprintf("Exec=%s %%u\n", exe_path);
117+
desktop_file << "Actions=Testnet;\n";
118+
desktop_file << "[Desktop Action Testnet]\n";
119+
desktop_file << strprintf("Exec=%s -testnet\n", exe_path);
120+
desktop_file << "Name=Testnet mode\n";
121+
} else {
122+
desktop_file << "Name=" PACKAGE_NAME " - Testnet\n";
123+
desktop_file << strprintf("Exec=%s -testnet %%u\n", exe_path);
124+
}
125+
126+
desktop_file.close();
127+
return true;
128+
}
129+
#endif // Q_OS_LINUX
130+
52131
QString getDefaultDataDirectory()
53132
{
54133
return boostPathToQString(GetDefaultDataDir());

src/qt/guifileutil.h

+7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77

88
#include <fs.h>
99

10+
#include <QIcon>
1011
#include <QString>
12+
#include <QtGlobal>
1113

1214
QT_BEGIN_NAMESPACE
1315
class QWidget;
@@ -16,6 +18,11 @@ QT_END_NAMESPACE
1618
/** Filesystem utility functions used by the GUI.
1719
*/
1820
namespace GUIUtil {
21+
22+
#ifdef Q_OS_LINUX
23+
bool IntegrateWithDesktopEnvironment(QIcon icon);
24+
#endif // Q_OS_LINUX
25+
1926
/**
2027
* Determine default data directory for operating system.
2128
*/

0 commit comments

Comments
 (0)