Skip to content

Instantly share code, notes, and snippets.

@kronn
Created August 29, 2018 08:43
Show Gist options
  • Save kronn/d0841c304cad8abac8d3147eca9adfc3 to your computer and use it in GitHub Desktop.
Save kronn/d0841c304cad8abac8d3147eca9adfc3 to your computer and use it in GitHub Desktop.
A small tool to query workrave via DBus and implement a text-based widget for status-bars
#!/usr/bin/env /home/mviehweger/.rvm/wrappers/ruby-2.4.2/ruby
# frozen_string_literal: true
# http://trac.luon.net/data/ruby-dbus/tutorial/basic_client.html
# for ubuntu, there is d-feet
begin
require 'dbus'
rescue LoadError => e
require 'rbconfig'
version = RbConfig::CONFIG['ruby_version']
puts "Please install 'ruby-dbus' for Ruby #{version}"
puts e.message
exit
end
# system_bus = DBus::SystemBus.instance
session_bus = DBus::SessionBus.instance
service = session_bus.service('org.workrave.Workrave')
workrave = service.object('/org/workrave/Workrave/Core')
workrave.introspect # populate the object with data from dbus
workrave_ui = service.object('/org/workrave/Workrave/UI')
workrave_ui.introspect # populate the object with data from dbus
core = workrave['org.workrave.CoreInterface']
# SetOperationMode
# GetOperationMode
# SetUsageMode
# GetUsageMode
# ReportActivity
# IsTimerRunning
# GetTimerIdle
# GetTimerElapsed
# GetTimerOverdue
# GetTime
# IsActive
# PostponeBreak
# SkipBreak
config = workrave['org.workrave.ConfigInterface']
# SetString
# SetInt
# SetBool
# SetDouble
# GetString
# GetInt
# GetBool
# GetDouble
control = workrave_ui['org.workrave.ControlInterface']
# About
# Excercises
# NetworkConnect
# NetworkDisconnect
# NetworkLog
# NetworkReconnect
# OpenMain
# Preferences
# Quit
# ReadingMode
# RestBreak
# Statistics
# main entry
class Workrave
attr_reader :core, :config, :control
def initialize(core, config, control)
@core = core
@config = config
@control = control
end
def mode
core.GetOperationMode.first
end
end
class Workrave
# one timer, could be microbreak, restbreak or daily limit
class Timer
def initialize(workrave, name = 'rest')
# interfaces
@core = workrave.core
@config = workrave.config
# timer names in interfaces
@core_name = name + 'break'
@config_name = name + '_break'
# output details
@name = name
@prefix = prefix
@style = 'pango' # default for now
end
def prefix
"#{@name[0].upcase}#{@name[1..-1]}: "
end
def idle
@core.GetTimerIdle(@core_name).first
end
def elapsed
@core.GetTimerElapsed(@core_name).first
end
def overdue
@core.GetTimerOverdue(@core_name).first
end
def limit
@config.GetInt("/timers/#{@config_name}/limit").first
end
def status
if idle_state
idle
elsif active_state
limit - elapsed
elsif overdue_state
overdue * -1
end
end
def idle_state
return false unless idle.positive?
@prefix = 'Idle: '
@color = :good
true
end
def active_state
return false unless elapsed <= limit
@prefix = prefix
@color = :neutral
true
end
def overdue_state
return false unless overdue.positive? || elapsed > limit
@prefix = prefix
@color = :bad
true
end
def to_s(style = @style)
# '%i:%02i' % status.divmod(60)
Workrave::Output.new(@prefix, status, @color, style).to_s
end
end
end
class Workrave
# translation of cli-commands to dbus-messages
class Command
def initialize(workrave)
@workrave = workrave
@core = workrave.core
@control = workrave.control
end
def silent!
@core.SetOperationMode('quiet')
end
def active!
@core.SetOperationMode('normal')
end
def restbreak!
@control.RestBreak
end
end
end
class Workrave
# formatting and colors
class Output
def initialize(prefix, seconds, status, style)
@prefix = prefix
@seconds = seconds
@status = status
@color = send(status)
@style = style
end
def to_s
# @prefix + wrap('%i:%02i' % @seconds.divmod(60), @color)
time = if @seconds > 3600
Time.at(@seconds).utc.strftime('%H:%M')
else
format('%2i:%02i', *@seconds.divmod(60))
end
wrap(time, @color, @style)
end
def good
'#00ff00'
end
def neutral
'#aaf'
end
def bad
'#ff0000'
end
def wrap(string, color, style)
case style
when 'lemonbar' then "%{F#{color}}#{string}%{F-}" # rubocop:disable Style/FormatStringToken,Metrics/LineLength
when 'pango' then "<fc=#{color}>#{string}</fc>"
else string
end
end
end
end
wr = Workrave.new(core, config, control)
rest = Workrave::Timer.new(wr, 'rest')
case ARGV[0]
when 'long'
micro = Workrave::Timer.new(wr, 'micro')
puts "workrave: micro: #{micro} rest: #{rest} (#{wr.mode})"
# require 'pry'; binding.pry
when 'do'
cmd = Workrave::Command.new(wr)
puts cmd.public_send(:"#{ARGV[1]}!")
when 'help'
# rubocop:disable Style/FormatStringToken
puts(<<-HELP)
#{$PROGRAM_NAME} [commands]
if no command is given, it just outputs the colored workrave time
it color shows which state it is in.
Commands
--------
long output verbose status of workrave
do send a command to workrave
silent set workrave into quiet mode
(just diplay the times, do not force breaks)
active set workrave into normal mode
(diplay the times, but also force breaks)
restbreak start a break right now
format show the short status of workrave, formatted as requested
lemonbar used by polybar and lemonbar (%{F...}%{F-})
pango used by xmobar (<fc=...></fc>)
plain no formatting-wrapper
help Unknown outcome.
HELP
# rubocop:enable Style/FormatStringToken
when 'format'
puts rest.to_s(ARGV[1])
else
puts rest
end
@rodfersou
Copy link

can you please post a screenshot of the app running?

@kronn
Copy link
Author

kronn commented Dec 21, 2021

Well, the script outputs text. I used this in xmobar and after that polybar. Both render text in a font of the users choosing.

So I fail to see the point of a screenshot. If you really want to, I can create one.

Since it connects via dbus to workrave, it starts that... are you refering to that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment