This commit removes and replaces all the old methods 'on_*' by settings
with the same name. The old methods were renamed into more explicit names that can be used for the callbacks like "next_song","mute" etc...
For instance, you can test with:
status.register("clock",
	format=[
	    ("Format 0",'Europe/London'),
	    ("%a %-d Format 1",'Europe/Dublin'),
	    "%a %-d %b %X format 2",
	    ("%a %-d %b %X format 3", 'Europe/Paris'),
	],
	on_leftclick= ["urxvtc"] , # launch urxvtc on left click
	on_rightclick= ["scroll_format", 2] , # update format by steps of 2
	log_level=logging.DEBUG,
	)

This way much code could be removed from other modules, though I did it only for the clock module here.
This commit is contained in:
Matthieu Coudron 2014-12-20 15:30:41 +01:00
parent 98e46ac3d6
commit d31cc380ef
19 changed files with 129 additions and 100 deletions

View File

@ -46,10 +46,10 @@ class ALSA(IntervalModule):
alsamixer = None
has_mute = True
on_scrollup = "increase_volume"
on_scrolldown = "decrease_volume"
on_lclick = "switch_mute"
on_rclick = on_lclick
on_upscroll = "increase_volume"
on_downscroll = "decrease_volume"
on_leftclick = "switch_mute"
on_rightclick = on_leftclick
def init(self):
self.create_mixer()

View File

@ -59,6 +59,9 @@ class Bitcoin(IntervalModule):
"price_down": "",
}
on_leftclick = "handle_leftclick"
on_rightclick = "handle_rightclick"
_price_prev = 0
def _fetch_price_data(self):
@ -122,8 +125,8 @@ class Bitcoin(IntervalModule):
"color": color,
}
def on_leftclick(self):
def handle_leftclick(self):
user_open(self.leftclick)
def on_rightclick(self):
def handle_rightclick(self):
user_open(self.rightclick)

View File

@ -28,8 +28,8 @@ class Clock(IntervalModule):
color = "#ffffff"
interval = 1
current_format_id = 0
on_scrollup = "next_format"
on_scrolldown = "next_format"
on_upscroll = ["scroll_format", 1]
on_downscroll = ["scroll_format", -1]
def init(self):
if self.format is None:
@ -80,8 +80,5 @@ class Clock(IntervalModule):
if self.color != "i3Bar":
self.output["color"] = self.color
def next_format(self):
self.current_format_id = (self.current_format_id + 1) % len(self.format)
def previous_format(self):
self.current_format_id = (self.current_format_id - 1) % len(self.format)
def scroll_format(self, step=1):
self.current_format_id = (self.current_format_id + step) % len(self.format)

View File

@ -49,6 +49,11 @@ class Cmus(IntervalModule):
"stopped": "",
}
on_leftclick = "playpause"
on_rightclick = "next_song"
on_upscroll = "next_song"
on_downscroll = "previous_song"
def _cmus_command(self, command):
p = subprocess.Popen('cmus-remote --{command}'.format(command=command), shell=True,
stdout=subprocess.PIPE,
@ -108,7 +113,7 @@ class Cmus(IntervalModule):
"color": self.color
}
def on_leftclick(self):
def playpause(self):
status = self._query_cmus().get('status', '')
if status == 'playing':
self._cmus_command('pause')
@ -117,11 +122,8 @@ class Cmus(IntervalModule):
if status == 'stopped':
self._cmus_command('play')
def on_rightclick(self):
def next_song(self):
self._cmus_command("next")
def on_upscroll(self):
self._cmus_command("next")
def on_downscroll(self):
def previous_song(self):
self._cmus_command("prev")

View File

@ -8,20 +8,16 @@ class Module(SettingsBase):
output = None
position = 0
settings = ('on_lclick', "Callback called on left click",
'on_rclick', "Callback called on right click",
'on_scrollup', "Callback called on scrolling up",
'on_scrolldown', "Callback called on scrolling down",
settings = ('on_leftclick', "Callback called on left click (string)",
'on_rightclick', "Callback called on right click (string)",
'on_upscroll', "Callback called on scrolling up (string)",
'on_downscroll', "Callback called on scrolling down (string)",
)
# this allows for backward compatibility
on_lclick = None
on_rclick = None
on_scrollup = None
on_scrolldown = None
# on_rclick = "on_rightclick"
# on_scrollup = "on_upscroll"
# on_scrolldown = "on_downscroll"
on_leftclick = None
on_rightclick = None
on_upscroll = None
on_downscroll = None
def registered(self, status_handler):
"""Called when this module is registered with a status handler"""
@ -39,42 +35,68 @@ class Module(SettingsBase):
pass
def on_click(self, button):
"""
Maps a click event (include mousewheel events) with its associated callback.
It then triggers the callback depending on the nature (ie type) of
the callback variable:
1. if null callback, do nothing
2. if it's a python function
3. if it's a method of the current module
To setup the callbacks, you can set the settings 'on_leftclick',
'on_rightclick', 'on_upscroll', 'on_downscroll'.
For instance, you can test with:
status.register("clock",
format=[
("Format 0",'Europe/London'),
("%a %-d Format 1",'Europe/Dublin'),
"%a %-d %b %X format 2",
("%a %-d %b %X format 3", 'Europe/Paris'),
],
on_leftclick= ["urxvtc"] , # launch urxvtc on left click
on_rightclick= ["scroll_format", 2] , # update format by steps of 2
log_level=logging.DEBUG,
)
"""
def split_callback_and_args(cb):
if isinstance(cb, list):
return cb[0], cb[1:]
else:
return cb, []
cb = None
if button == 1: # Left mouse button
cb = self.on_lclick or "on_leftclick"
cb = self.on_leftclick
elif button == 3: # Right mouse button
cb = self.on_rclick or "on_rightclick"
cb = self.on_rightclick
elif button == 4: # mouse wheel up
cb = self.on_scrollup or "on_upscroll"
cb = self.on_upscroll
elif button == 5: # mouse wheel down
cb = self.on_scrolldown or "on_downscroll"
cb = self.on_downscroll
else:
self.logger.debug("Button not handled")
self.logger.info("Button '%d' not handled yet." % (button))
return
if not cb:
self.logger.info("no cb attached")
return
else:
cb, args = split_callback_and_args(cb)
self.logger.debug("cb=%s args=%s" % (cb, args))
if callable(cb):
return cb(self)
elif hasattr(self, cb):
return getattr(self, cb)()
return getattr(self, cb)(*args)
else:
return run_through_shell(cb)
return run_through_shell(cb, *args)
def move(self, position):
self.position = position
return self
def on_leftclick(self):
pass
def on_rightclick(self):
pass
def on_upscroll(self):
pass
def on_downscroll(self):
pass
class IntervalModuleMeta(type):
"""Add interval setting to `settings` attribute if it does not exist."""

View File

@ -431,7 +431,7 @@ def make_bar(percentage):
def user_open(url_or_command):
"""Open the specified paramater in the web browser if a URL is detected,
othewrise pass the paramater to the shell as a subprocess. This function
is inteded to bu used in on_leftclick()/on_rightclick() events.
is inteded to bu used in on_leftclick/on_rightclick callbacks.
:param url_or_command: String containing URL or command
"""

View File

@ -38,6 +38,8 @@ class Mail(IntervalModule):
hide_if_null = True
email_client = None
on_leftclick = "open_client"
def init(self):
for backend in self.backends:
pass
@ -69,11 +71,8 @@ class Mail(IntervalModule):
"color": color,
}
def on_leftclick(self):
def open_client(self):
if self.email_client:
retcode, _, stderr = run_through_shell(self.email_client)
if retcode != 0 and stderr:
self.logger.error(stderr)
def on_rightclick(self):
self.run()

View File

@ -35,6 +35,8 @@ class ModsDeChecker(IntervalModule):
cj = None
logged_in = False
on_leftclick = "open_browser"
def init(self):
self.cj = http.cookiejar.CookieJar()
self.opener = urllib.request.build_opener(
@ -94,5 +96,5 @@ class ModsDeChecker(IntervalModule):
return True
return False
def on_leftclick(self):
def open_browser(self):
webbrowser.open_new_tab("http://forum.mods.de/bb/")

View File

@ -50,6 +50,10 @@ class MPD(IntervalModule):
color = "#FFFFFF"
text_len = 25
truncate_fields = ("title", "album", "artist")
on_leftclick = "switch_playpause"
on_rightclick = "next_song"
on_upscroll = on_rightclick
on_downscroll = "previous_song"
def _mpd_command(self, sock, command):
try:
@ -101,26 +105,20 @@ class MPD(IntervalModule):
"color": self.color,
}
def on_leftclick(self):
def switch_playpause(self):
try:
self._mpd_command(self.s, "%s" %
("play" if self._mpd_command(self.s, "status")["state"] in ["pause", "stop"] else "pause"))
except Exception as e:
pass
def on_rightclick(self):
def next_song(self):
try:
self._mpd_command(self.s, "next")
except Exception as e:
pass
def on_upscroll(self):
try:
self._mpd_command(self.s, "next")
except Exception as e:
pass
def on_downscroll(self):
def previous_song(self):
try:
self._mpd_command(self.s, "previous")
except Exception as e:

View File

@ -105,6 +105,7 @@ class Network(IntervalModule):
color_down = "#FF0000"
detached_down = True
unknown_up = False
on_leftclick = "nm-connection-editor"
def init(self):
if self.interface not in netifaces.interfaces() and not self.detached_down:
@ -174,6 +175,3 @@ class Network(IntervalModule):
"color": color,
"instance": self.interface
}
def on_leftclick(self):
subprocess.Popen(["nm-connection-editor"])

View File

@ -54,6 +54,8 @@ class NowPlaying(IntervalModule):
color = "#FFFFFF"
old_player = None
on_leftclick = "playpause"
on_rightclick = "next_song"
def find_player(self):
players = [a for a in dbus.SessionBus().get_object("org.freedesktop.DBus", "/org/freedesktop/DBus").ListNames() if a.startswith("org.mpris.MediaPlayer2.")]
@ -111,8 +113,8 @@ class NowPlaying(IntervalModule):
"color": self.color,
}
def on_leftclick(self):
def playpause(self):
self.get_player().PlayPause()
def on_rightclick(self):
def next_song(self):
self.get_player().Next()

View File

@ -153,6 +153,7 @@ class ParcelTracker(IntervalModule):
required = ("instance",)
format = "{name}:{progress}"
on_leftclick = "open_browser"
@require(internet)
def run(self):
@ -166,5 +167,5 @@ class ParcelTracker(IntervalModule):
"instance": self.name,
}
def on_leftclick(self):
def open_browser(self):
webbrowser.open_new_tab(self.instance.get_url())

View File

@ -27,6 +27,11 @@ class Pianobar(IntervalModule):
required = ("format", "songfile", "ctlfile")
color = "#FFFFFF"
on_leftclick = "playpause"
on_rightclick = "next_song"
on_upscroll = "increase_volume"
on_downscroll = "decrease_volume"
def run(self):
with open(self.songfile, "r") as f:
contents = f.readlines()
@ -39,14 +44,14 @@ class Pianobar(IntervalModule):
"color": self.color
}
def on_leftclick(self):
def playpause(self):
open(self.ctlfile, "w").write("p")
def on_rightclick(self):
def next_song(self):
open(self.ctlfile, "w").write("n")
def on_upscroll(self):
def increase_volume(self):
open(self.ctlfile, "w").write(")")
def on_downscroll(self):
def decrease_volume(self):
open(self.ctlfile, "w").write("(")

View File

@ -42,6 +42,9 @@ class Pomodoro(IntervalModule):
break_duration = 5 * 60
long_break_duration = 15 * 60
on_rightclick = "stop"
on_leftclick = "start"
def init(self):
# state could be either running/break or stopped
self.state = 'stopped'
@ -90,12 +93,12 @@ class Pomodoro(IntervalModule):
'color': color
}
def on_leftclick(self):
def start(self):
self.state = 'running'
self.time = datetime.now() + timedelta(seconds=self.pomodoro_duration)
self.breaks = 0
def on_rightclick(self):
def stop(self):
self.state = 'stopped'
self.time = None

View File

@ -50,6 +50,11 @@ class PulseAudio(Module, ColorRangeModule):
bar_type = 'vertical'
vertical_bar_width = 2
on_rightclick = "switch_mute"
on_leftclick = "pavucontrol"
on_upscroll = "increase_volume"
on_downscroll = "decrease_volume"
def init(self):
"""Creates context, when context is ready context_notify_cb is called"""
# Wrap callback methods in appropriate ctypefunc instances so
@ -155,10 +160,7 @@ class PulseAudio(Module, ColorRangeModule):
volume_bar=volume_bar),
}
def on_leftclick(self):
subprocess.Popen(["pavucontrol"])
def on_rightclick(self):
def switch_mute(self):
if self.has_amixer:
command = "amixer -q -D pulse sset Master "
if self.currently_muted:
@ -167,12 +169,12 @@ class PulseAudio(Module, ColorRangeModule):
command += 'mute'
subprocess.Popen(command.split())
def on_upscroll(self):
def increase_volume(self):
if self.has_amixer:
command = "amixer -q -D pulse sset Master %s%%+" % self.step
subprocess.Popen(command.split())
def on_downscroll(self):
def decrease_volume(self):
if self.has_amixer:
command = "amixer -q -D pulse sset Master %s%%-" % self.step
subprocess.Popen(command.split())

View File

@ -39,6 +39,7 @@ class pyLoad(IntervalModule):
captcha_false = ""
download_true = "Downloads enabled"
download_false = "Downloads disabled"
on_leftclick = "open_webbrowser"
def _rpc_call(self, method, data=None):
if not data:
@ -83,5 +84,5 @@ class pyLoad(IntervalModule):
"instance": self.address,
}
def on_leftclick(self):
def open_webbrowser(self):
webbrowser.open_new_tab(self.address)

View File

@ -61,6 +61,9 @@ class Reddit(IntervalModule):
"no_mail": "",
}
on_leftclick = "open_permalink"
on_click = "open_link"
_permalink = ""
_url = ""
@ -133,8 +136,8 @@ class Reddit(IntervalModule):
"color": color,
}
def on_leftclick(self):
def open_permalink(self):
user_open(self._permalink)
def on_rightclick(self):
def open_link(self):
user_open(self._url)

View File

@ -23,6 +23,9 @@ class Spotify(Module):
("color", "color of the output"),
)
on_leftclick = "switch_playpause"
on_rightclick = "next_song"
def main_loop(self):
""" Mainloop blocks so we thread it."""
self.player = Playerctl.Player()
@ -62,8 +65,8 @@ class Spotify(Module):
"color": self.color
}
def on_leftclick(self):
def switch_playpause(self):
self.player.play_pause()
def on_rightclick(self):
def next_song(self):
self.player.next()

View File

@ -1,5 +1,3 @@
import subprocess
from i3pystatus import Module
@ -11,14 +9,10 @@ class Text(Module):
settings = (
"text",
("color", "HTML color code #RRGGBB"),
("cmd_leftclick", "Shell command to execute on left click"),
("cmd_rightclick", "Shell command to execute on right click"),
)
required = ("text",)
color = None
cmd_leftclick = "test"
cmd_rightclick = "test"
def init(self):
self.output = {
@ -26,9 +20,3 @@ class Text(Module):
}
if self.color:
self.output["color"] = self.color
def on_leftclick(self):
subprocess.call(self.cmd_leftclick, shell=True)
def on_rightclick(self):
subprocess.call(self.cmd_rightclick, shell=True)