How difficult would it be to show battery information similar to what showtime and the weather app show on the desktop

O O

Nice! What are you using?

vala of course. code is not good enough though. Probably placed stuff in places it should not be :smiley:

  • Still working on getting the info from upower. I can’t yet figure out how to get “state”.
  • I assume I need to use a gsettings call to store and fetch the variables.
  • The message on screen is fixed at the moment. How to make it refresh every X minutes eludes me. Assuming the upower bit needs to go into a main loop that calls itself. But then I need to figure out how to get the message into your bit.

using Gtk;
using Cairo;
using GLib;

// valac --pkg gtk+-3.0 --pkg cairo indicator.vala

int vertical = 300; 
int horizontal = 1200;
int fontsize = 50;

namespace UPower {

    [DBus (name = "org.freedesktop.UPower")]
    public interface Base : GLib.Object {
        public abstract bool on_battery {get;}
    }

    [CCode (type_signature = "u")]
    public enum DeviceState {
        UNKNOWN = 0,
        CHARGING = 1,
        DISCHARGING = 2,
        EMPTY = 3,
        CHARGED = 4,
        PENDING_CHARGE = 5,
        PENDING_DISCHARGE = 6
    }

    [DBus (name = "org.freedesktop.UPower.Device")]
    public interface Device : Object {
        public abstract string vendor {owned get;}
        [DBus (name = "Type")]
        public abstract int64 time_to_empty {get;}
        public abstract int64 time_to_full {get;}
        public abstract double percentage {get;}
        public abstract bool is_present {get;}
        public abstract DeviceState state {get;}
    }
}

  namespace TransparentWindowTest {

    public static void main(string[] args) {
        Gtk.init(ref args);
        new TransparentWindow ();
        Gtk.main();
    }

    public class TransparentWindow : Gtk.Window {
        string indicatorcss = """
        .indicatorfont {
        font-size: {fontsize}px;
        color: red;
        }
        """.replace("{fontsize}",fontsize.to_string());
        Label indicatorlabel;

        public TransparentWindow () {
            this.set_title ("Desktop battery indicator");
            this.set_type_hint(Gdk.WindowTypeHint.DESKTOP);
            this.set_decorated(false);
      
            var maingrid = new Grid();
            this.add(maingrid);
           
	    UPower.Base upower;
	    upower = Bus.get_proxy_sync(BusType.SYSTEM, "org.freedesktop.UPower",
		                        "/org/freedesktop/UPower");
	    string message;
	    string percentage;
            string time_to_full;
            string time_to_empty;

	    UPower.Device upower1;
	    upower1 = Bus.get_proxy_sync(BusType.SYSTEM, "org.freedesktop.UPower",
		                        "/org/freedesktop/UPower/devices/battery_BAT0");
	    percentage = upower1.percentage.to_string();
            time_to_full = upower1.time_to_full.to_string();
            time_to_empty = upower1.time_to_empty.to_string();

	    if (upower.on_battery) {
		message = "Battery";
               message += " - " + time_to_empty.to_string();
	    }
	    else {
		message = "Charging";
               message += " - " + time_to_full.to_string();
	    }
	    message += " - " + percentage + "%";            

            indicatorlabel = new Label(message);
            maingrid.attach(indicatorlabel, 0, 0, 1, 1);
            this.destroy.connect(Gtk.main_quit);

            var screen = this.get_screen();
            this.set_app_paintable(true);
            var visual = screen.get_rgba_visual();
            this.set_visual(visual);
            this.draw.connect(on_draw);

            set_indicatorfont(screen);
            this.move(horizontal, vertical);
            this.show_all();
        }

        private bool on_draw (Widget da, Context ctx) {
            ctx.set_source_rgba(0, 0, 0, 0);
            ctx.set_operator(Cairo.Operator.SOURCE);
            ctx.paint();
            ctx.set_operator(Cairo.Operator.OVER);
            return false;
        }

        public void set_indicatorfont (Gdk.Screen screen) {
            Gtk.CssProvider css_provider = new Gtk.CssProvider();
            try {
                css_provider.load_from_data(indicatorcss);
                Gtk.StyleContext.add_provider_for_screen(
                    screen, css_provider, Gtk.STYLE_PROVIDER_PRIORITY_USER
                );
                indicatorlabel.get_style_context().add_class("indicatorfont");
            }
            catch (Error e) {
                print("Error\n");
            }
        }
    }
}

Refreshing could be done with GLib.Timeout.add(), then updating gui from idle, else Gtk thread will crash sooner or later. Settings and connect / windowplacement is the easy part.

Curious if we don’t have a signal to use though.

namespace TransparentWindowTest {

public static void main(string[] args) {
    GLib.Timeout.add (60000, reload);
    Gtk.init(ref args);
    new TransparentWindow ();
    Gtk.main();
}

public bool reload () {
    GLib.Timeout.add (60000, reload);
    new TransparentWindow ();
    Gtk.main();
    return true;
}

Is that a good way to reload the window?

Settings

Making a schema and loading from it done already. That part was easy.

a second… posting to experimental

Posted a reduced version of dynamically updating stuff + acting on gsettings change here. I left out the window transparency etc.

css_provider.load_from_data(indicatorcss);

errors out and I can not figure out why. The CSS =is= loading (xpos, ypos etc have values).


public void set_font () {
        css_provider.load_from_data(indicatorcss);
        try {
            css_provider.load_from_data(indicatorcss);
       ...

Warning during compilation:

batterystatus.vala:62.13-62.53: warning: unhandled error `GLib.Error'
        css_provider.load_from_data(indicatorcss);
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Compilation succeeded - 1 warning(s)

Run time error:

** (batterystatus:41018): CRITICAL **: 16:19:12.963: file /discworld/projects/batterystatus.vala.c: line 774: uncaught error: :3:19not a number (gtk-css-provider-error-quark, 1)

Errors on the linked snippet?

Stupid me got distracted looking at slack :stuck_out_tongue:

I have working script with the exception of the css so I am decently happy.

Could not have done it without your examples. Really. Still stumped at half of the code I see. But google got me a long way.

Used your 2 examples plus snippets from https://github.com/rilian-la-te/vala-panel-extras/blob/master/applets/batt/battery.vala and info from https://upower.freedesktop.org/docs/Device.html

Screenshot from 2020-02-08 18-51-19

Screenshot from 2020-02-08 18-51-38

When the warning level is low, critical or action I add a 2nd line. Fake message:

Screenshot from 2020-02-08 18-56-22

Screenshot from 2020-02-08 18-55-52

Screenshot from 2020-02-08 18-55-28

Still tweaking but the general idea works.

It would be awesome if this could be packaged up as an applet, and have a transparent background.

Oh that is the idea. I am not done yet :smiley: I am facing a bug in the css I really don’t get (in a bit from the code from überboss Vlijm). The 1st example he made css worked. See the image from 20h ago (full desktop).

It is all part of a combination of assignments. My personal need to understand desktop enhancements, gtk3, gsettings with python (but that turned into vala quickly). A work related one would be to give instructions on how github works to my co-workers. I host a few computers and got asked by a couple of elderly people if it was possible to get a largish battery on the desktop since the panel was far to small for them. So I thought I’d combine it.


Added time remaining to full/empty.

TO DO:

  • background is not transparent. Probably need cairo; 1st example did work so trying things.
  • settings.
  • github it.

Found it! And in any place where I blamed you do a s/you/me/g :smiley:

Could look at the ShowTime applet for an example to make the background transparent.

Jacob provided me with 2 examples. The 1st was with cairo, where it works. The 2nd was without cairo and that one didn’t. Merged the 2 and got it working now.

Next task: a way to manipulate the settings besides manual editing dconf.