Skip to content

Commit 2bd1394

Browse files
committed
qt: Add Settings -> Integrate... menu item
1 parent 4ef0172 commit 2bd1394

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
@@ -22,6 +22,7 @@
2222
#endif // WIN32
2323

2424
#ifdef Q_OS_LINUX
25+
#include <cassert>
2526
#include <stdlib.h>
2627
#include <unistd.h>
2728
#endif // Q_OS_LINUX
@@ -30,6 +31,7 @@
3031
#include <QDir>
3132
#include <QFileDialog>
3233
#include <QFileInfo>
34+
#include <QPixmap>
3335
#include <QRegExp>
3436
#include <QStandardPaths>
3537
#include <QString>
@@ -49,11 +51,88 @@ std::string GetExecutablePathAsString()
4951
exe_path[r] = '\0';
5052
return exe_path;
5153
}
54+
55+
fs::path GetUserApplicationsDir()
56+
{
57+
const char* home_dir = getenv("HOME");
58+
if (!home_dir) return fs::path();
59+
return fs::path(home_dir) / ".local" / "share" / "applications";
60+
}
61+
62+
fs::path GetDesktopFilePath(std::string chain)
63+
{
64+
const auto app_dir = GetUserApplicationsDir();
65+
if (app_dir.empty()) return fs::path();
66+
if (!chain.empty()) {
67+
chain = "_" + chain;
68+
}
69+
return app_dir / strprintf("org.bitcoincore.BitcoinQt%s.desktop", chain);
70+
}
71+
72+
fs::path GetUserIconsDir()
73+
{
74+
const char* home_dir = getenv("HOME");
75+
if (!home_dir) return fs::path();
76+
return fs::path(home_dir) / ".local" / "share" / "icons";
77+
}
78+
79+
fs::path GetIconPath(std::string chain)
80+
{
81+
const auto icons_dir = GetUserIconsDir();
82+
if (icons_dir.empty()) return fs::path();
83+
if (!chain.empty()) {
84+
chain = "-" + chain;
85+
}
86+
return icons_dir / strprintf("bitcoin%s.png", chain);
87+
}
5288
#endif // Q_OS_LINUX
5389
} // namespace
5490

5591
namespace GUIUtil {
5692

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