Skip to content

Commit

Permalink
Allow configuration of builtin main menu buttons (#174)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmgao authored Nov 27, 2024
1 parent 4b779df commit 2d06985
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 25 deletions.
25 changes: 19 additions & 6 deletions res/doc
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,27 @@
# Unknown options are ignored. If there are multiple declarations of an
# option, only the first one takes effect.
#
# <key> the option name, one of:
# menu_main_15505_enabled - controls enablement of the NickelMenu button on 4.23.15505+
# menu_main_15505_label - sets the label used for the NickelMenu button on 4.23.15505+
# menu_main_15505_icon - sets the icon used for the NickelMenu button on 4.23.15505+
# menu_main_15505_icon_active - sets the active icon used for the NickelMenu button on 4.23.15505+
# <key> the option name:
# main_menu_15505_<main menu option> - controls the added NickelMenu button
# main_menu_15505_<n>_<main_menu_option> - controls the main menu button at position n (indexed from 0)
# note that there may be already-hidden buttons in the list:
# on a Kobo Libra Colour running 4.41.23145, the button list is:
# 0 - Home
# 1 - My Books
# 2 - Activity [hidden]
# 3 - My Notebooks
# 4 - Discover
# 5 - More
#
# <main menu option> one of:
# enabled - controls enablement of the NickelMenu button on 4.23.15505+
# label - sets the label used for the NickelMenu button on 4.23.15505+
# icon - sets the icon used for the NickelMenu button on 4.23.15505+
# icon_active - sets the active icon used for the NickelMenu button on 4.23.15505+
#
# <val> the option value:
# menu_main_15505_enabled - 0 or 1
# menu_main_15505_label - the label to use instead of "NickelMenu"
# menu_main_15505_label - the label to use instead of the default value
# menu_main_15505_icon - the path passed to QPixmap
# menu_main_15505_icon_active - the path passed to QPixmap
#
Expand Down
101 changes: 82 additions & 19 deletions src/nickelmenu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <QFile>
#include <QLayout>
#include <QMenu>
#include <QMetaProperty>
#include <QPushButton>
#include <QRegularExpression>
#include <QString>
Expand Down Expand Up @@ -263,17 +264,50 @@ QString nm_menu_pixmap(const char *custom, const char *custom_temp_out, const ch
return QString(custom_temp_out);
}

extern "C" __attribute__((visibility("default"))) void _nm_menu_hook2(MainNavView *_this, QWidget *parent) {
NM_LOG("MainNavView::MainNavView(%p, %p)", _this, parent);
MainNavView_MainNavView(_this, parent);
static const char *nm_main_menu_config(int index, const char *option) {
char buf[strlen("menu_main_15505_9_icon_active") + 1];
if (snprintf(buf, sizeof(buf), "menu_main_15505_%d_%s", index, option) >= static_cast<ssize_t>(sizeof(buf))) {
NM_LOG("Failed to create main menu config key for index %d, option %s", index, option);
return nullptr;
}
return nm_global_config_experimental(buf);
}

const char *enabled = nm_global_config_experimental("menu_main_15505_enabled");
if (enabled && strcmp("0", enabled) == 0) {
NM_LOG("Main menu disabled");
return;
static void main_nav_button_configure(MainNavButton *btn, const char *label, const char *icon, const char *icon_fallback, const char *icon_active, const char *icon_active_fallback) {
if (label) {
MainNavButton_setText(btn, label);
}

NM_LOG("Adding main menu button in tab bar for firmware 4.23.15505+.");
if (icon || icon_fallback) {
QString pixmap = nm_menu_pixmap(
icon,
"/tmp/nm_menu.png",
icon_fallback
);
if (!pixmap.isEmpty()) {
MainNavButton_setPixmap(btn, pixmap);
}
}

if (icon_active || icon_active_fallback) {
QString pixmap = nm_menu_pixmap(
icon_active,
"/tmp/nm_menu.png",
icon_active_fallback
);
if (!pixmap.isEmpty()) {
MainNavButton_setActivePixmap(btn, pixmap);
}
}

if (icon || icon_fallback || icon_active || icon_active_fallback) {
QFile::remove("/tmp/nm_menu.png");
}
}

extern "C" __attribute__((visibility("default"))) void _nm_menu_hook2(MainNavView *_this, QWidget *parent) {
NM_LOG("MainNavView::MainNavView(%p, %p)", _this, parent);
MainNavView_MainNavView(_this, parent);

if (!MainNavButton_MainNavButton || !MainNavButton_setPixmap || !MainNavButton_setActivePixmap || !MainNavButton_setText || !MainNavButton_setText) {
NM_LOG("Could not find required MainNavButton symbols, cannot add tab button for NickelMenu main menu.");
Expand All @@ -286,26 +320,55 @@ extern "C" __attribute__((visibility("default"))) void _nm_menu_hook2(MainNavVie
return;
}

NM_LOG("Default main menu has %d buttons", bl->count());
for (int i = 0; i < bl->count(); ++i) {
QWidget *widget = bl->itemAt(i)->widget();
NM_LOG("Main menu button %d = %s", i, widget ->objectName().toUtf8().constData());

MainNavButton *btn = qobject_cast<MainNavButton*>(widget);
if (!btn) {
NM_LOG("qobject_cast<MainNavButton*> failed on button %d", i);
continue;
}

const char *label = nm_main_menu_config(i, "label");
const char *icon = nm_main_menu_config(i, "icon");
const char *icon_active = nm_main_menu_config(i, "icon_active");

const char *enabled = nm_main_menu_config(i, "enabled");
main_nav_button_configure(btn, label, icon, nullptr, icon_active, nullptr);
if (enabled) {
if (strcmp("0", enabled) == 0) {
NM_LOG("Main menu button %d disabled", i);
widget->hide();
} else if (strcmp("1", enabled) == 0) {
NM_LOG("Main menu button %d explicitly enabled", i);
widget->show();
}
}
}

const char *enabled = nm_global_config_experimental("menu_main_15505_enabled");
if (enabled && strcmp("0", enabled) == 0) {
NM_LOG("Main menu NickelMenu button disabled");
return;
}

NM_LOG("Adding main menu button in tab bar for firmware 4.23.15505+.");
MainNavButton *btn = reinterpret_cast<MainNavButton*>(calloc(1, 256));
if (!btn) { // way larger than a MainNavButton, but better to be safe
NM_LOG("Failed to allocate memory for MainNavButton, cannot add tab button for NickelMenu main menu.");
return;
}

MainNavButton_MainNavButton(btn, parent);
MainNavButton_setPixmap(btn, nm_menu_pixmap(
main_nav_button_configure(btn,
nm_global_config_experimental("menu_main_15505_label") ?: "NickelMenu",
nm_global_config_experimental("menu_main_15505_icon"),
"/tmp/nm_menu.png",
":/images/home/main_nav_more.png"
));
MainNavButton_setActivePixmap(btn, nm_menu_pixmap(
nm_global_config_experimental("menu_main_15505_icon_active")
?: nm_global_config_experimental("menu_main_15505_icon"),
"/tmp/nm_menu.png",
":/images/home/main_nav_more.png",
nm_global_config_experimental("menu_main_15505_icon_active"),
":/images/home/main_nav_more_active.png"
));
QFile::remove("/tmp/nm_menu.png");
MainNavButton_setText(btn, nm_global_config_experimental("menu_main_15505_label") ?: "NickelMenu");
);
btn->setObjectName("nmButton");

QPushButton *sh = new QPushButton(_this); // HACK: we use a QPushButton as an adaptor so we can connect an old-style signal with the new-style connect without needing a custom QObject
Expand Down

0 comments on commit 2d06985

Please sign in to comment.