After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 787426 - [Patch] Support more than one css file
[Patch] Support more than one css file
Status: RESOLVED OBSOLETE
Product: glade
Classification: Applications
Component: general
3.20.x
Other Linux
: Normal normal
: ---
Assigned To: Glade 3 Maintainers
Glade 3 Maintainers
Depends on:
Blocks:
 
 
Reported: 2017-09-08 05:54 UTC by Arnaud Rebillout
Modified: 2018-03-26 16:02 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Arnaud Rebillout 2017-09-08 05:54:35 UTC
Hi,

this is a feature request.

Use-case: I have a project where we create several GUI applications. We want the appearance to be consistent across all these apps, so we ended up creating a little toolkit that provides our custom widgets + a CSS file. This CSS file is used by all our applications.

Each application might have its own bits of CSS as well.

So in the end, each application needs to load two CSS files: the one from our toolkit, and its own CSS.

At the moment, Glade allow loading only one CSS file.

----

I already wrote a quick and dirty implementation for that, and here's how the glade file look like when two css files are saved.

    <!-- Generated with glade 3.20.0 -->
    <interface>
      <requires lib="gtk+" version="3.20"/>
      <!-- interface-css-provider-path mainwindow.css -->
      <!-- interface-css-provider-path testing.css -->
      ...

I discovered that Glade automatically saves the location of the css file as a relative path. While it makes sense for an application css, it does not make sense anymore for the use-case I describe, where I'd like to load one custom css from a toolkit (installed somewhere on the machine), and another css that is application dependent (and which should be saved as a relative path, indeed).

I don't know how to tackle this issue, regarding the UI mainly. It's easy to allow both relative and absolute paths in the Glade file, and let the user edit the glade file by hand and enter whatever he wants, and decide by himself if he wants relative or absolute path. But how to present that in the UI, I have no idea.

----

If someone are interested in this feature, my work in progress is available at:

- git: https://gitlab.com/arnaud-preevio/glade
- branch: 3.20/multicss-try1

This current version already works, as long as you're willing to edit the glade file by hand, rather than using the UI, to add your css files. You can add either relatives or absolute paths.

The current issues with this version:
- the UI part is not implemented
- glade-previewer is probably broken regarding css
- code is still hacky

If there's some interest in this feature from upstream, and a will to ultimately merge it, I'd be ok to iterate until the code is good enough.

Cheers !

  Arnaud
Comment 1 Juan Pablo Ugarte 2017-09-08 22:28:13 UTC
(In reply to Arnaud Rebillout from comment #0)
> Hi,
> 
> this is a feature request.
> 
> Use-case: I have a project where we create several GUI applications. We want
> the appearance to be consistent across all these apps, so we ended up
> creating a little toolkit that provides our custom widgets + a CSS file.
> This CSS file is used by all our applications.
> 
> Each application might have its own bits of CSS as well.

Right, in that case you could probably use the import CSS command, with the caveat that glade wont monitor imported files (maybe we should add a refresh action)

Anyways I looked at your branch, it looks good, the only major comment is that we do not break ABI, or at least we try not to.

BTW the plural form for path is paths, I think :)
Comment 2 Arnaud Rebillout 2017-09-09 08:52:25 UTC
> Right, in that case you could probably use the import CSS command, with the caveat that glade wont monitor imported files (maybe we should add a refresh action)

Oh, nice, I actually did not know about this CSS command. I just tried it, it works. Great.

Well let me dig in a bit more in this direction and see how much it does the trick.
Comment 3 Arnaud Rebillout 2017-09-14 03:35:12 UTC
Hi !

let me keep going on this conversation. Let me describe again my use-case, with a few more details.

I have a library (that I call a toolkit here) that holds widgets and css file. I have applications that use this toolkit.

The working directory looks like that.

    workdir
     \_ app1     (have its own css)
     \_ app2
     \_ ...
     \_ toolkit  (provides css for apps, bundled in a resource file)

Each app or the toolkit are cloned from independent git repositories.

Everyone here use GResource, which means that no css file ever gets installed on the system, only a resource file. At run time, applications use the toolkit. And the toolkit init code is in charge of loading the resource file and the css.

The discussion here is about being able to load two css files (the one from the toolkit + the one from the app) in Glade.

----

I did some test with using the import CSS command, as suggested by Juan Pablo Ugarte. The idea is to import the toolkit css from the application css. While it's possible to have something working it's not really satisfactory.

**Attempt 1**

I assume that the toolkit is installed on the system, and I load the toolkit css from the system directories. Aka:

    @import url('file:///usr/share/toolkit/style.css');

However, as I said above, the toolkit bundles its resource in a GResource file. So the css never gets installed on the system, and the file I'm trying to import here just doesn't exist.

**Attempt 2**

So, let's use the toolkit source code, the only place where I can access the css file. I assume here that the working directory is structured as described above, which is a reasonable assumption (I can ask to my fellow co-workers to follow this layout in their working directory).

Based on this assumption, I can try a relative import, aka:

    @import url('file:///../../../toolkit/data/style.css');

Which just doesn't work. Without digging too much into that, it seems that relative import is just not supported.

**Attempt 3**

So, I'm left with one last option. Import from the css from the toolkit source code, using an absolute path.

    @import url('file:///home/me/project/toolkit/data/style.css');

Does it work ? Yes, the import is successful, and I can see in Glade that the css is effective.

Can I commit that ? Nope. I have to add this line each time I work with Glade, and remove it when I'm done.

Can my co-worker do that ? Nope, because he's not a developer, he's a designer and I'd like things to work out of the box for him.

**Conclusion**

While it's possible to use the css import command as a workaround, it's not really usable in a daily workflow.

----

Ok, so I'm back with the idea of adding the feature to Glade, I still think it makes sense.

However, the situation is a bit more simple than in my first message. In my first message I was concerned about saving the css path absolute versus relative, because I thought I'd load my toolkit css from something like `/usr/share`.

Now that I realize that it's not possible because I use GResource, it actually simplifies the problem: let's just keep using relative paths, as it's done already in Glade.

The feature request in Glade just boils down to: support more than one CSS file.

Does it still make sense ?

----

And some more comments.

> we do not break ABI, or at least we try not to.

By ABI, you mean the ABI of libgladeui ? Is it used by something else that Glade itself ? I don't understand your concern here.

If you mean the content of the file that Glade saves, then as you can see in the snippet I pasted in my 1st message, I just add more lines like:

    <!-- interface-css-provider-path ... >

I don't think it really breaks anything, but I'm not sure how the current Glade handled a file with more than one line like that. I can test that.

> BTW the plural form for path is paths, I think :)

Hmm, well, yes, indeed, breaking the English here, on top of breaking the ABI ;)
Comment 4 Arnaud Rebillout 2017-09-22 04:26:10 UTC
Hey guys,

second iteration available here:

- git: https://gitlab.com/arnaud-preevio/glade
- branch: 3.20/multicss-try2

Here's the changelog

    Changes from 1st iteration are:
    
    - fix typo: pathes -> paths
    - add annotation for zero-terminated array
    - do not change the way Glade handles css file paths, that is:
      - write relative paths to the glade file
      - work with absolute paths internally
    
    Todolist
    
    - add the ui part
    - modify glade-preview to support multi css files
    - internally, handle the tuple path/provider/monitor better

Please let me know if this stuff is really wanted by Glade, and if someone will merge it in the end. If so, I'll keep on working on it, otherwise I stop here.

I mean, this stuff takes time, I won't do all the polishing if I'm the only one using it.

Cheers !
Comment 5 Tristan Van Berkom 2017-09-22 04:41:27 UTC
(In reply to Arnaud Rebillout from comment #3)
> Hi !
> 
> let me keep going on this conversation. Let me describe again my use-case,
> with a few more details.
> 
> I have a library (that I call a toolkit here) that holds widgets and css
> file. I have applications that use this toolkit.
> 
> The working directory looks like that.
> 
>     workdir
>      \_ app1     (have its own css)
>      \_ app2
>      \_ ...
>      \_ toolkit  (provides css for apps, bundled in a resource file)
> 
> Each app or the toolkit are cloned from independent git repositories.
> 
> Everyone here use GResource, which means that no css file ever gets
> installed on the system, only a resource file. At run time, applications use
> the toolkit. And the toolkit init code is in charge of loading the resource
> file and the css.
> 
> The discussion here is about being able to load two css files (the one from
> the toolkit + the one from the app) in Glade.

I dont think using import features is really the correct way to do this.

More below...

[...]
> Ok, so I'm back with the idea of adding the feature to Glade, I still think
> it makes sense.
> 
> However, the situation is a bit more simple than in my first message. In my
> first message I was concerned about saving the css path absolute versus
> relative, because I thought I'd load my toolkit css from something like
> `/usr/share`.
> 
> Now that I realize that it's not possible because I use GResource, it
> actually simplifies the problem: let's just keep using relative paths, as
> it's done already in Glade.
> 
> The feature request in Glade just boils down to: support more than one CSS
> file.
> 
> Does it still make sense ?

I think whichever way you fry the cat it can make sense to support this (of course in the Glade runtime, resources like CSS files and images and such are loaded differently than at target application runtime...).


So, considering your use case; I think this import stuff is not suitable for your purposes, or incorrect; maybe there are scenarios where importing CSS fragments make more sense (probably more for just creating a more structured package of CSS files ?).

The correct way, I believe, to achieve this; is to use multiple style providers with different priorities; this is how GTK+ manages to use a CSS "theme" which it applies to every application, and how then applications use their own custom CSS at a higher priority, overriding styles from the lower level priority.

So your toolkit, I expect probably offers some custom widgets which your apps use and some common functionality, when initializing it, your toolkit should immediately load the CSS with a GtkCssStyleProvider, perhaps at the GTK_STYLE_PROVIDER_PRIORITY_THEME priority (although you should probably check that doing this will not completely replace the target GTK+'s installation default theme, like adwaita or such, if you dont want that).

Then your apps would load their own custom CSS at the priority GTK_STYLE_PROVIDER_PRIORITY_APPLICATION.


It's not a clear picture, and you probably want to fact check what I'm saying since it's been a little while since I looked at this more closely, but I believe this is generally how the styling machinery is intended to work.
Comment 6 Arnaud Rebillout 2017-09-22 06:41:21 UTC
> 
> So your toolkit, I expect probably offers some custom widgets which your
> apps use and some common functionality, when initializing it, your toolkit
> should immediately load the CSS with a GtkCssStyleProvider, perhaps at the
> GTK_STYLE_PROVIDER_PRIORITY_THEME priority (although you should probably
> check that doing this will not completely replace the target GTK+'s
> installation default theme, like adwaita or such, if you dont want that).
> 
> Then your apps would load their own custom CSS at the priority
> GTK_STYLE_PROVIDER_PRIORITY_APPLICATION.
> 

Yep, and that's exactly the way it works, it's good to see that my implementation is roughly the way it should be :)

For the moment my toolkit uses the priority GTK_STYLE_PROVIDER_PRIORITY_APPLICATION, but I think it would be more correct to use the THEME priority as you suggest.
Comment 7 Arnaud Rebillout 2017-09-25 10:55:04 UTC
I gave a first try to the implementation on the gui side. There's one neat commit with explanation here:

    - git: https://gitlab.com/arnaud-preevio/glade
    - branch: 3.20/multicss-ui

If nobody speaks against, I'll go ahead and re-work the rest of the code I made previously. Cheers !
Comment 8 Arnaud Rebillout 2017-10-06 04:15:08 UTC
Dear all,

I implemented the whole thing and the patches are available here:

- git: https://gitlab.com/arnaud-preevio/glade
- branch: 3.20.1/multicss-try3

The branch is based on the tag `GLADE_3_20_1`. It can be rebased on `master` without conflict.

The "whole thing" include supports for multiple css files in glade-project and glade-previewer, and changes in the gui to add as many css files as you want.

Hope to hear from you guys soon,

  Arnaud
Comment 9 Juan Pablo Ugarte 2017-11-26 20:54:43 UTC
Hello Arnoud, I did not had time to do a detailed review but here are some comments.

- Do not break API (keep css-provider-path and add css-provider-paths)
- Make GladeCssManager private (no need to expose for the moment)
- In GladeCssManagerPrivate I think it would be cleaner if you use a data type with an associated destroy function like GHashTable instead of 3 pointer arrays

typedef struct {
  GtkCssProvider *provider;
  GFileMonitor *monitor;
} CssProvider;

struct _GladeCssManagerPrivate
{
  GHashTable *providers;
};

This way you can define the destroy function when you create the table and even use g_hash_table_get_keys_as_array() to get all the keys/filenames as a NULL terminated char**
Comment 10 GNOME Infrastructure Team 2018-03-26 16:02:40 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/glade/issues/280.