Skip to content
This repository has been archived by the owner on Aug 3, 2019. It is now read-only.

App is not relocatable #7

Open
popey opened this issue Feb 12, 2017 · 12 comments
Open

App is not relocatable #7

popey opened this issue Feb 12, 2017 · 12 comments

Comments

@popey
Copy link

popey commented Feb 12, 2017

in some places green-recorder has hard wired paths to files. e.g.

indicator = appindicator.Indicator.new("Green Recorder", '/usr/share/pixmaps/green-recorder.png', appindicator.IndicatorCategory.APPLICATION_STATUS)

and:-

builder.add_from_file("/usr/lib/green-recorder/ui.glade")

This assumption breaks the ability for green-recorder to work in some environments. Specifically when containerised or confined, that directory may be somewhere else (relative) on the filesystem, and not at that absolute path.

@mhsabbagh
Copy link
Owner

You are right. Any suggestion for determining those paths relatively?

@popey
Copy link
Author

popey commented Feb 12, 2017

Sorry, I don't know. Are there not XDG or LD environment variables which could be used? how do other gtk apps do this?

@mhsabbagh
Copy link
Owner

Unfortunately - as far as I know - no. There doesn't exist such variables to use. So implementing such solution would require some hard coding. Or maybe there's a library which provides such functionality and I don't know about it.

@phw
Copy link

phw commented Mar 6, 2017

Other GTK apps often compile pixmaps, glade UI and CSS files as a gresource. This way you don't have to rely on hard coded paths, but use URIs like "resource:///com/uploadedlobster/peek/css/peek.css" defined inside the resource file. See https://developer.gnome.org/gio/stable/GResource.html

Not quite sure how this works with Python, though. If using C or Vala one can simply compile the resources in, removing the needs for file system paths entirely. On Python you have to still load the compiled gresource file with some code like this:

DATA_DIR = "data/"
resource = Gio.resource_load(DATA_DIR + "green-recorder.gresource")
Gio.Resource._register(self.resource)
builder = Gtk.Builder()
builder.add_from_resource('/some/path/to/resource/window.ui')

Again one typical approach is to set the DATA_DIR path during installation. Or you search for it in known locations.

@SafaAlfulaij
Copy link

SafaAlfulaij commented Mar 7, 2017

Since a GNOME app uses a hardcoded path, I don't see it's that bad...

@phw
Copy link

phw commented Mar 7, 2017

That's not a hard coded file system path, that is the path inside the compiled resources ;) It is independent of the install location.

@SafaAlfulaij
Copy link

@gort818
Copy link
Contributor

gort818 commented Mar 10, 2017

@phw I do not understand , it is a python application how are there compiled resources?

@julianrichen
Copy link

julianrichen commented Mar 10, 2017

@gort818 The ui, images, and whatever assets you want inside the resources can be either

  1. Compiled into the c code (if your using c)
  2. Compiled into a .gresource file (what most Python people do)
  3. Loaded directly

You create the gresource file by using glib-compile-resources:

glib-compile-resources test.gresource.xml --target=test.gresource

Creates a test.gresource file containing the compiled resources.

Then you can access it with:

resource = Gio.resource_load(os.path.join(PACKAGE_DATA_DIR, 'test.gresource'))
Gio.Resource._register(resource)

and loaded resources from it with:

builder = Gtk.Builder()
builder.add_from_resource('/tld/domain/project/resource.ui')

Where /tld/domain/project is the application id for the project, and is included in the gresource. Normally it follows the standard of a domain + name, example:

gnome.org/music

becomes:

/org/gnome/music

A lot of people on Github do:

github.com/green-project/green-recorder
green-project.github.io/green-recorder

becomes:

/io/github/green-project/green-recorder

@gort818
Copy link
Contributor

gort818 commented Mar 10, 2017

@julianrichen Wow thank you very informative!

@julianrichen
Copy link

julianrichen commented Mar 10, 2017

Also forgot a few things. Gtk can automatically implement parts of your program with resources (page I linked -> Description -> Automatic resources). For example the app-menu and menubar can be loaded automatically by linking a ui file in the gresoures.xml that is either at gtk/menus.ui or has an alias to it. They can also be split into gtk/menus-appmenu.ui or gtk/menus-traditional.ui.

Same can also be done with for Keyboard shortcuts via gtk/help-overlay.ui.

Here is an example that links up Preferences, Keyboard Shortcuts, Help, About and Quit to the app-menu/menubar to the application + adds the help-overlay (GAction is win.show-help-overlay). This only setsup the menus, besides the help-overlay you would need to create the preferences, about, help, quit actions your self. If you wanted to add them of course.

gtk/menus.ui

<?xml version="1.0"?>
<interface>
    <menu id="app-menu">
        <section>
            <item>
                <attribute name="label" translatable="yes">_Preferences</attribute>
                <attribute name="action">app.preferences</attribute>
              	<attribute name="accel">&lt;Primary&gt;comma</attribute>
            </item>
        </section>
        <section>
            <item>
                <attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
                <attribute name="action">win.show-help-overlay</attribute>
            </item>
            <item>
                <attribute name="label" translatable="yes">_Help</attribute>
                <attribute name="action">app.help</attribute>
              	<attribute name="accel">F1</attribute>
            </item>
            <item>
                <attribute name="label" translatable="yes">_About</attribute>
                <attribute name="action">app.about</attribute>
              	<attribute name="accel">F2</attribute>
            </item>
            <item>
                <attribute name="label" translatable="yes">_Quit</attribute>
                <attribute name="action">app.quit</attribute>
              	<attribute name="accel">&lt;Primary&gt;q</attribute>
            </item>
        </section>
    </menu>
    <menu id="menubar">
        <submenu>
            <attribute name="label">_File</attribute>
            <section>
                <item>
                    <attribute name="label" translatable="yes">_Quit</attribute>
                    <attribute name="action">app.quit</attribute>
                  	<attribute name="accel">&lt;Primary&gt;q</attribute>
                </item>
            </section>
        </submenu>
        <submenu>
            <attribute name="label">_Edit</attribute>
            <section>
                <item>
                    <attribute name="label" translatable="yes">_Preferences</attribute>
                    <attribute name="action">app.preferences</attribute>
                  	<attribute name="accel">&lt;Primary&gt;comma</attribute>
                </item>
            </section>
        </submenu>
        <submenu>
            <attribute name="label">_Help</attribute>
            <section>
                <item>
                    <attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
                    <attribute name="action">win.show-help-overlay</attribute>
                </item>
                <item>
                    <attribute name="label" translatable="yes">_Help</attribute>
                    <attribute name="action">app.help</attribute>
                  	<attribute name="accel">F1</attribute>
                </item>
                <item>
                    <attribute name="label" translatable="yes">_About</attribute>
                    <attribute name="action">app.about</attribute>
                  	<attribute name="accel">F2</attribute>
                </item>
            </section>
        </submenu>
    </menu>
</interface>

gtk/help-overlay.ui

<?xml version="1.0" encoding="UTF-8"?>
<interface>
    <object class="GtkShortcutsWindow" id="help_overlay">
        <property name="modal">True</property>
        <child>
            <object class="GtkShortcutsSection">
                <property name="visible">True</property>
                <property name="section-name">shortcuts</property>
                <property name="max-height">17</property>
                <child>
                    <object class="GtkShortcutsGroup">
                        <property name="visible">True</property>
                        <property name="title" translatable="yes" context="shortcut window">General</property>
                        <child>
                            <object class="GtkShortcutsShortcut">
                                <property name="visible">True</property>
                                <property name="title" translatable="yes" context="shortcut window">Preferences</property>
                                <property name="accelerator">&lt;Primary&gt;comma</property>
                            </object>
                        </child>
                        <child>
                            <object class="GtkShortcutsShortcut">
                                <property name="visible">True</property>
                                <property name="title" translatable="yes" context="shortcut window">Keyboard Shortcuts</property>
                                <property name="accelerator">&lt;Primary&gt;F1</property>
                                <property name="accelerator">&lt;Primary&gt;&lt;Shift&gt;question</property>
                            </object>
                        </child>
                        <child>
                            <object class="GtkShortcutsShortcut">
                                <property name="visible">True</property>
                                <property name="title" translatable="yes" context="shortcut window">Help</property>
                                <property name="accelerator">F1</property>
                            </object>
                        </child>
                        <child>
                            <object class="GtkShortcutsShortcut">
                                <property name="visible">True</property>
                                <property name="title" translatable="yes" context="shortcut window">About</property>
                                <property name="accelerator">F2</property>
                            </object>
                        </child>
                        <child>
                            <object class="GtkShortcutsShortcut">
                                <property name="visible">True</property>
                                <property name="title" translatable="yes" context="shortcut window">Quit</property>
                                <property name="accelerator">&lt;Primary&gt;Q</property>
                            </object>
                        </child>
                    </object>
                </child>
            </object>
        </child>
    </object>
</interface>

ui/window.ui (your current ui/ui.glade)

xml code...
``

`io.github.green-project.green-recorder.gresource.xml`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
    <gresource prefix="/io/github/green-project/green-recorder/">
        <file alias="gtk/menus.ui">gtk/menus.ui</file>
        <file alias="gtk/help-overlay.ui" preprocess="xml-stripblanks" compressed="true">gtk/help-overlay.ui</file>
        <file preprocess="xml-stripblanks" compressed="true">ui/window.ui</file>
    </gresource>
</gresources>

I would refrain from doing to many images as it can make the size of the gresource massive. SVG's are ok since they tend to be small and you only need one for most sizes.

@ghost
Copy link

ghost commented May 23, 2018

I've made a PR which should fix the issue, the commit in question: 59f0890

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants