Добры молодцы из команды GTK навертали чертову уйму классов для отделения логики от интерфейса. Все эти GtkAction, GtkUiManager, GtkActivatable и прочие упоительные названия.
У GtkAction есть имя, иконка, тултип, состояния sensetive и visible. На их основе генерируется внешний вид и состояния менюшечек и тулбаров. Короче, всё как у взрослых.
Почти. Если не считать того досадного факта, что тултип абсолютно бесполезен, т.к. не используется при создании меню.
Ладно. Решаю по-быстрому накалякать пару костылей — у нас же ООП, реюз кода во все поля и всё такое прочее. Мы можем переопределять поведение объектов и разводить руками тучи.
GtkImageMenuItem реализует интерфейс GtkActivatable и через него получает апдейты состояния. Ок, унаследуем свой класс от GtkImageMenuItem и допишем нужный код по установке тултипа.
GtkAction рожает из себя менюшки на основе класса, указанного в одном из полей своего класса. Ок, унаследуем свой класс от GtkAction и переопределим поле, засунув туда собственный класс менюитема.
Всё красиво, всё поООПшному, архитектурные космонавты в восторге.
Стоп. Про что-то мы забыли. А кто создаёт GtkAction-ы? GtkAction-ы создаёт GtkActionGroup. Открываем код. Смотрим. Еще раз смотрим. Хлопаем глазами и не верим в то, что видим:
void
gtk_action_group_add_actions_full (GtkActionGroup *action_group,
const GtkActionEntry *entries,
guint n_entries,
gpointer user_data,
GDestroyNotify destroy)
{
/* Keep this in sync with the other
* gtk_action_group_add_..._actions_full() functions.
*/
guint i;
SharedData *shared_data;
g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
shared_data = g_slice_new0 (SharedData);
shared_data->ref_count = 1;
shared_data->data = user_data;
shared_data->destroy = destroy;
for (i = 0; i < n_entries; i++)
{
GtkAction *action;
const gchar *label;
const gchar *tooltip;
if (!check_unique_action (action_group, entries[i].name))
continue;
label = gtk_action_group_translate_string (action_group, entries[i].label);
tooltip = gtk_action_group_translate_string (action_group, entries[i].tooltip);
action = gtk_action_new (entries[i].name,
label,
tooltip,
NULL);
Даааа, дааа, да! Развесистое дерево наследований. Абстрактные интерфейсы. Переменные класса. Фантастика на грани техники. Чертова уйма overengineered кода, который абсолютно бесполезен, потому что в итоге всё равно вся эта развесистая космическая архитектура запинается о вовремя подставленный gtk_action_new(), падает и разбивается к едреней фене. И хоронит под собой все ваши иллюзии, будто ООП волшебным образом превращает всех плохих программистов в хороших. Enjoy your code reuse.
А, да: баг репортить не буду. Если кому надо, репортите сами. Я ж обещал, что к разработке стека гномобиблиотек и пальцем не притронусь, даже на уровне отсылки багов. Лучше пойду придумаю обычный костыль с ручным назначением тултипов, без всей этой архитектурной космонавтики.