在没有 Autotools 或 Meson 的情况下显示我的 Gtkmm 应用程序的帮助

Show help for my Gtkmm application without Autotools or Meson

我使用 Gtkmm 编写了一个小应用程序,我想为用户提供文档。为此,我想推出 Gnome help system from my application's menu (For a working example, one can look at gedit).

首先,我写了一个最小的 Mallard index.page 文件:

<page xmlns="http://projectmallard.org/1.0/"
      type="guide"
      id="index">
<title>Example help</title>
</page>

我可以通过从我的项目的根目录调用命令yelp help/C/index.page来查看:

然后,我写了一些最小的 C++ 应用程序 (Gtkmm 3.22) 来调用帮助系统:

#include <iostream>
#include <gtkmm.h>

constexpr char HELP_URI[] = "help:myapp";

int main(int argc, char* argv[]) 
{
    auto app = Gtk::Application::create(argc, argv, "bob.morane.question");

    Gtk::Window window;

    // 1. Add the help menu item:
    Gtk::MenuItem helpItem;
    helpItem.set_label("Help");

    Gtk::Menu helpMenu;
    Gtk::MenuItem openHelpItem;
    openHelpItem.set_label("Open help...");

    Gtk::MenuBar menuBar;
    menuBar.append(helpItem);
    helpItem.set_submenu(helpMenu);
    helpMenu.append(openHelpItem);

    window.add(menuBar);
    

    // 2. Link the help menu item to Mallard documentation:
    openHelpItem.signal_activate().connect([&window](){
        const guint32 timestamp = gtk_get_current_event_time();
        GError* error = nullptr;

        // This is the call that triggers gnome help system:
        const bool status = gtk_show_uri_on_window (window.gobj(),
                                                    HELP_URI,
                                                    timestamp,
                                                    &error);
        if(!status)
        {
            std::cout << "Unable to show help : " + std::string{error->message} << std::endl;
            return;
        }
    });

    window.show_all();
    return app->run(window);
}

我使用一个非常简单的 Makefile 构建:

all: main.cpp
    g++ -std=c++17 main.cpp -o myapp `pkg-config gtkmm-3.0 --cflags --libs`

当我点击 Open help... 菜单项时,我得到以下信息:

如果我将程序的第一行更改为:constexpr char HELP_URI[] = "help:gedit";,则 gedit 帮助会正常弹出。现在使用 Meson(如 gedit)或 Autotools(像 Gnome documentation 建议的)这样的构建系统对我来说太过分了。我希望能够显示我的帮助文件而无需处理这些文件(即我想继续使用我的 Makefile)。

*问题:如何在不使用 Meson 或 Autotools 的情况下显示我自己的帮助文件?

帮助文件必须在Yelp可以找到的地方。通常你会将它们安装到 /usr/share/help/LANG/APPID/,其中 LANG 是一个语言标识符(或者只是 C 对于未翻译的文档),APPID 是你的应用程序的一些标识符(匹配.desktop 文件的基本名称是一个很好的最佳做法)。

如果您使用 autotools,yelp.m4 会为您处理所有这些:http://yelp.io/tools/yelp.m4

如果您使用介子,gnome.yelp 函数会为您处理:https://mesonbuild.com/Gnome-module.html#gnomeyelp

但是,如果您不想使用构建系统,则必须自己设法将文件获取到某个地方。他们不必在 /usr/ 中。 Yelp 查找 XDG 基目录规范中 $XDG_DATA_HOME$XDG_DATA_DIRS 中目录的 help 子目录。默认情况下,这意味着它查看 ~/.local/share/help/:/usr/local/share/help/:/usr/share/help/。因此,您可以在 ~/.local/share/ 下本地安装文件以进行测试。

或者,如果您真的不想在任何地方安装文件,您可以按特定方式安排您的源代码树并设置环境变量。例如,如果您的源代码树以 ~/myapp/ 为根,则将您的页面文件放在 ~/myapp/help/C/myapp/ 下,并使用 XDG_DATA_HOME=~/myapp/ myapp.

调用您的应用程序

但实际上,如果您希望用户使用您的应用程序,您将不得不弄清楚如何在正确的位置安装文件。你最好为此使用现有的构建系统,即使你认为你的应用程序太小了。

我最后做了什么:因为我还不能移动到构建系统,我决定写一个小脚本将我的帮助内容复制到 ~/.local/share 以进行测试:

#!/bin/bash

TARGET=~/.local/share

if [[ -d "${TARGET}/" ]]
then
    cp -r ./help ${TARGET}
else
    echo "Error: ${TARGET} does not exist."
fi

有了这个,我可以开发我的帮助文档,而无需使用构建系统。请注意,为了使此脚本起作用,我已将我的 index.page 帮助文件添加到项目根目录的 help/C/myapp/index.page 下。这使我可以从我的 Makefile 中自动执行此脚本,因此我不必手动复制所有内容或自己致电 Yelp:

all: main.cpp
    ./installHelp.sh
    g++ -std=c++17 main.cpp -o myapp `pkg-config gtkmm-3.0 --cflags --libs`

正如 Shaun McCance 提到的那样,此解决方案不可移植,迟早我将不得不迁移到某个构建系统。