Merge pull request #149 from teto/cb
Allowing for personalized callbacks while keeping backwards compatibility
This commit is contained in:
commit
b3e45177d3
@ -46,6 +46,11 @@ class ALSA(IntervalModule):
|
|||||||
alsamixer = None
|
alsamixer = None
|
||||||
has_mute = True
|
has_mute = True
|
||||||
|
|
||||||
|
on_upscroll = "increase_volume"
|
||||||
|
on_downscroll = "decrease_volume"
|
||||||
|
on_leftclick = "switch_mute"
|
||||||
|
on_rightclick = on_leftclick
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.create_mixer()
|
self.create_mixer()
|
||||||
try:
|
try:
|
||||||
@ -82,18 +87,15 @@ class ALSA(IntervalModule):
|
|||||||
"color": self.color_muted if muted else self.color,
|
"color": self.color_muted if muted else self.color,
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def switch_mute(self):
|
||||||
self.on_rightclick()
|
|
||||||
|
|
||||||
def on_rightclick(self):
|
|
||||||
if self.has_mute:
|
if self.has_mute:
|
||||||
muted = self.alsamixer.getmute()[self.channel]
|
muted = self.alsamixer.getmute()[self.channel]
|
||||||
self.alsamixer.setmute(not muted)
|
self.alsamixer.setmute(not muted)
|
||||||
|
|
||||||
def on_upscroll(self):
|
def increase_volume(self, delta=None):
|
||||||
vol = self.alsamixer.getvolume()[self.channel]
|
vol = self.alsamixer.getvolume()[self.channel]
|
||||||
self.alsamixer.setvolume(min(100, vol + self.increment))
|
self.alsamixer.setvolume(min(100, vol + (delta if delta else self.increment)))
|
||||||
|
|
||||||
def on_downscroll(self):
|
def decrease_volume(self, delta=None):
|
||||||
vol = self.alsamixer.getvolume()[self.channel]
|
vol = self.alsamixer.getvolume()[self.channel]
|
||||||
self.alsamixer.setvolume(max(0, vol - self.increment))
|
self.alsamixer.setvolume(max(0, vol - (delta if delta else self.increment)))
|
||||||
|
@ -59,6 +59,9 @@ class Bitcoin(IntervalModule):
|
|||||||
"price_down": "▼",
|
"price_down": "▼",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on_leftclick = "handle_leftclick"
|
||||||
|
on_rightclick = "handle_rightclick"
|
||||||
|
|
||||||
_price_prev = 0
|
_price_prev = 0
|
||||||
|
|
||||||
def _fetch_price_data(self):
|
def _fetch_price_data(self):
|
||||||
@ -122,8 +125,8 @@ class Bitcoin(IntervalModule):
|
|||||||
"color": color,
|
"color": color,
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def handle_leftclick(self):
|
||||||
user_open(self.leftclick)
|
user_open(self.leftclick)
|
||||||
|
|
||||||
def on_rightclick(self):
|
def handle_rightclick(self):
|
||||||
user_open(self.rightclick)
|
user_open(self.rightclick)
|
||||||
|
@ -28,6 +28,8 @@ class Clock(IntervalModule):
|
|||||||
color = "#ffffff"
|
color = "#ffffff"
|
||||||
interval = 1
|
interval = 1
|
||||||
current_format_id = 0
|
current_format_id = 0
|
||||||
|
on_upscroll = ["scroll_format", 1]
|
||||||
|
on_downscroll = ["scroll_format", -1]
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
if self.format is None:
|
if self.format is None:
|
||||||
@ -78,8 +80,5 @@ class Clock(IntervalModule):
|
|||||||
if self.color != "i3Bar":
|
if self.color != "i3Bar":
|
||||||
self.output["color"] = self.color
|
self.output["color"] = self.color
|
||||||
|
|
||||||
def on_upscroll(self):
|
def scroll_format(self, step=1):
|
||||||
self.current_format_id = (self.current_format_id + 1) % len(self.format)
|
self.current_format_id = (self.current_format_id + step) % len(self.format)
|
||||||
|
|
||||||
def on_downscroll(self):
|
|
||||||
self.current_format_id = (self.current_format_id - 1) % len(self.format)
|
|
||||||
|
@ -49,6 +49,11 @@ class Cmus(IntervalModule):
|
|||||||
"stopped": "◾",
|
"stopped": "◾",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on_leftclick = "playpause"
|
||||||
|
on_rightclick = "next_song"
|
||||||
|
on_upscroll = "next_song"
|
||||||
|
on_downscroll = "previous_song"
|
||||||
|
|
||||||
def _cmus_command(self, command):
|
def _cmus_command(self, command):
|
||||||
p = subprocess.Popen('cmus-remote --{command}'.format(command=command), shell=True,
|
p = subprocess.Popen('cmus-remote --{command}'.format(command=command), shell=True,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
@ -108,7 +113,7 @@ class Cmus(IntervalModule):
|
|||||||
"color": self.color
|
"color": self.color
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def playpause(self):
|
||||||
status = self._query_cmus().get('status', '')
|
status = self._query_cmus().get('status', '')
|
||||||
if status == 'playing':
|
if status == 'playing':
|
||||||
self._cmus_command('pause')
|
self._cmus_command('pause')
|
||||||
@ -117,11 +122,8 @@ class Cmus(IntervalModule):
|
|||||||
if status == 'stopped':
|
if status == 'stopped':
|
||||||
self._cmus_command('play')
|
self._cmus_command('play')
|
||||||
|
|
||||||
def on_rightclick(self):
|
def next_song(self):
|
||||||
self._cmus_command("next")
|
self._cmus_command("next")
|
||||||
|
|
||||||
def on_upscroll(self):
|
def previous_song(self):
|
||||||
self._cmus_command("next")
|
|
||||||
|
|
||||||
def on_downscroll(self):
|
|
||||||
self._cmus_command("prev")
|
self._cmus_command("prev")
|
||||||
|
@ -1,12 +1,24 @@
|
|||||||
from i3pystatus.core.settings import SettingsBase
|
from i3pystatus.core.settings import SettingsBase
|
||||||
from i3pystatus.core.threading import Manager
|
from i3pystatus.core.threading import Manager
|
||||||
from i3pystatus.core.util import convert_position
|
from i3pystatus.core.util import convert_position
|
||||||
|
from i3pystatus.core.command import run_through_shell
|
||||||
|
|
||||||
|
|
||||||
class Module(SettingsBase):
|
class Module(SettingsBase):
|
||||||
output = None
|
output = None
|
||||||
position = 0
|
position = 0
|
||||||
|
|
||||||
|
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)",
|
||||||
|
)
|
||||||
|
|
||||||
|
on_leftclick = None
|
||||||
|
on_rightclick = None
|
||||||
|
on_upscroll = None
|
||||||
|
on_downscroll = None
|
||||||
|
|
||||||
def registered(self, status_handler):
|
def registered(self, status_handler):
|
||||||
"""Called when this module is registered with a status handler"""
|
"""Called when this module is registered with a status handler"""
|
||||||
|
|
||||||
@ -23,31 +35,71 @@ class Module(SettingsBase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def on_click(self, button):
|
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 the name of a method of the current module (string)
|
||||||
|
|
||||||
|
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
|
||||||
|
on_upscroll= [print, "hello world"] , # call python function print
|
||||||
|
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
|
if button == 1: # Left mouse button
|
||||||
self.on_leftclick()
|
cb = self.on_leftclick
|
||||||
elif button == 3: # Right mouse button
|
elif button == 3: # Right mouse button
|
||||||
self.on_rightclick()
|
cb = self.on_rightclick
|
||||||
elif button == 4: # mouse wheel up
|
elif button == 4: # mouse wheel up
|
||||||
self.on_upscroll()
|
cb = self.on_upscroll
|
||||||
elif button == 5: # mouse wheel down
|
elif button == 5: # mouse wheel down
|
||||||
self.on_downscroll()
|
cb = self.on_downscroll
|
||||||
|
else:
|
||||||
|
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)(*args)
|
||||||
|
else:
|
||||||
|
return run_through_shell(cb, *args)
|
||||||
|
|
||||||
def move(self, position):
|
def move(self, position):
|
||||||
self.position = position
|
self.position = position
|
||||||
return self
|
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):
|
class IntervalModuleMeta(type):
|
||||||
"""Add interval setting to `settings` attribute if it does not exist."""
|
"""Add interval setting to `settings` attribute if it does not exist."""
|
||||||
|
@ -431,7 +431,7 @@ def make_bar(percentage):
|
|||||||
def user_open(url_or_command):
|
def user_open(url_or_command):
|
||||||
"""Open the specified paramater in the web browser if a URL is detected,
|
"""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
|
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
|
:param url_or_command: String containing URL or command
|
||||||
"""
|
"""
|
||||||
|
@ -38,6 +38,8 @@ class Mail(IntervalModule):
|
|||||||
hide_if_null = True
|
hide_if_null = True
|
||||||
email_client = None
|
email_client = None
|
||||||
|
|
||||||
|
on_leftclick = "open_client"
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
for backend in self.backends:
|
for backend in self.backends:
|
||||||
pass
|
pass
|
||||||
@ -69,11 +71,8 @@ class Mail(IntervalModule):
|
|||||||
"color": color,
|
"color": color,
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def open_client(self):
|
||||||
if self.email_client:
|
if self.email_client:
|
||||||
retcode, _, stderr = run_through_shell(self.email_client)
|
retcode, _, stderr = run_through_shell(self.email_client)
|
||||||
if retcode != 0 and stderr:
|
if retcode != 0 and stderr:
|
||||||
self.logger.error(stderr)
|
self.logger.error(stderr)
|
||||||
|
|
||||||
def on_rightclick(self):
|
|
||||||
self.run()
|
|
||||||
|
@ -35,6 +35,8 @@ class ModsDeChecker(IntervalModule):
|
|||||||
cj = None
|
cj = None
|
||||||
logged_in = False
|
logged_in = False
|
||||||
|
|
||||||
|
on_leftclick = "open_browser"
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.cj = http.cookiejar.CookieJar()
|
self.cj = http.cookiejar.CookieJar()
|
||||||
self.opener = urllib.request.build_opener(
|
self.opener = urllib.request.build_opener(
|
||||||
@ -94,5 +96,5 @@ class ModsDeChecker(IntervalModule):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def on_leftclick(self):
|
def open_browser(self):
|
||||||
webbrowser.open_new_tab("http://forum.mods.de/bb/")
|
webbrowser.open_new_tab("http://forum.mods.de/bb/")
|
||||||
|
@ -50,6 +50,10 @@ class MPD(IntervalModule):
|
|||||||
color = "#FFFFFF"
|
color = "#FFFFFF"
|
||||||
text_len = 25
|
text_len = 25
|
||||||
truncate_fields = ("title", "album", "artist")
|
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):
|
def _mpd_command(self, sock, command):
|
||||||
try:
|
try:
|
||||||
@ -101,26 +105,20 @@ class MPD(IntervalModule):
|
|||||||
"color": self.color,
|
"color": self.color,
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def switch_playpause(self):
|
||||||
try:
|
try:
|
||||||
self._mpd_command(self.s, "%s" %
|
self._mpd_command(self.s, "%s" %
|
||||||
("play" if self._mpd_command(self.s, "status")["state"] in ["pause", "stop"] else "pause"))
|
("play" if self._mpd_command(self.s, "status")["state"] in ["pause", "stop"] else "pause"))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_rightclick(self):
|
def next_song(self):
|
||||||
try:
|
try:
|
||||||
self._mpd_command(self.s, "next")
|
self._mpd_command(self.s, "next")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def on_upscroll(self):
|
def previous_song(self):
|
||||||
try:
|
|
||||||
self._mpd_command(self.s, "next")
|
|
||||||
except Exception as e:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_downscroll(self):
|
|
||||||
try:
|
try:
|
||||||
self._mpd_command(self.s, "previous")
|
self._mpd_command(self.s, "previous")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -105,6 +105,7 @@ class Network(IntervalModule):
|
|||||||
color_down = "#FF0000"
|
color_down = "#FF0000"
|
||||||
detached_down = True
|
detached_down = True
|
||||||
unknown_up = False
|
unknown_up = False
|
||||||
|
on_leftclick = "nm-connection-editor"
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
if self.interface not in netifaces.interfaces() and not self.detached_down:
|
if self.interface not in netifaces.interfaces() and not self.detached_down:
|
||||||
@ -174,6 +175,3 @@ class Network(IntervalModule):
|
|||||||
"color": color,
|
"color": color,
|
||||||
"instance": self.interface
|
"instance": self.interface
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
|
||||||
subprocess.Popen(["nm-connection-editor"])
|
|
||||||
|
@ -54,6 +54,8 @@ class NowPlaying(IntervalModule):
|
|||||||
color = "#FFFFFF"
|
color = "#FFFFFF"
|
||||||
|
|
||||||
old_player = None
|
old_player = None
|
||||||
|
on_leftclick = "playpause"
|
||||||
|
on_rightclick = "next_song"
|
||||||
|
|
||||||
def find_player(self):
|
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.")]
|
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,
|
"color": self.color,
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def playpause(self):
|
||||||
self.get_player().PlayPause()
|
self.get_player().PlayPause()
|
||||||
|
|
||||||
def on_rightclick(self):
|
def next_song(self):
|
||||||
self.get_player().Next()
|
self.get_player().Next()
|
||||||
|
@ -153,6 +153,7 @@ class ParcelTracker(IntervalModule):
|
|||||||
required = ("instance",)
|
required = ("instance",)
|
||||||
|
|
||||||
format = "{name}:{progress}"
|
format = "{name}:{progress}"
|
||||||
|
on_leftclick = "open_browser"
|
||||||
|
|
||||||
@require(internet)
|
@require(internet)
|
||||||
def run(self):
|
def run(self):
|
||||||
@ -166,5 +167,5 @@ class ParcelTracker(IntervalModule):
|
|||||||
"instance": self.name,
|
"instance": self.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def open_browser(self):
|
||||||
webbrowser.open_new_tab(self.instance.get_url())
|
webbrowser.open_new_tab(self.instance.get_url())
|
||||||
|
@ -27,6 +27,11 @@ class Pianobar(IntervalModule):
|
|||||||
required = ("format", "songfile", "ctlfile")
|
required = ("format", "songfile", "ctlfile")
|
||||||
color = "#FFFFFF"
|
color = "#FFFFFF"
|
||||||
|
|
||||||
|
on_leftclick = "playpause"
|
||||||
|
on_rightclick = "next_song"
|
||||||
|
on_upscroll = "increase_volume"
|
||||||
|
on_downscroll = "decrease_volume"
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
with open(self.songfile, "r") as f:
|
with open(self.songfile, "r") as f:
|
||||||
contents = f.readlines()
|
contents = f.readlines()
|
||||||
@ -39,14 +44,14 @@ class Pianobar(IntervalModule):
|
|||||||
"color": self.color
|
"color": self.color
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def playpause(self):
|
||||||
open(self.ctlfile, "w").write("p")
|
open(self.ctlfile, "w").write("p")
|
||||||
|
|
||||||
def on_rightclick(self):
|
def next_song(self):
|
||||||
open(self.ctlfile, "w").write("n")
|
open(self.ctlfile, "w").write("n")
|
||||||
|
|
||||||
def on_upscroll(self):
|
def increase_volume(self):
|
||||||
open(self.ctlfile, "w").write(")")
|
open(self.ctlfile, "w").write(")")
|
||||||
|
|
||||||
def on_downscroll(self):
|
def decrease_volume(self):
|
||||||
open(self.ctlfile, "w").write("(")
|
open(self.ctlfile, "w").write("(")
|
||||||
|
@ -42,6 +42,9 @@ class Pomodoro(IntervalModule):
|
|||||||
break_duration = 5 * 60
|
break_duration = 5 * 60
|
||||||
long_break_duration = 15 * 60
|
long_break_duration = 15 * 60
|
||||||
|
|
||||||
|
on_rightclick = "stop"
|
||||||
|
on_leftclick = "start"
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# state could be either running/break or stopped
|
# state could be either running/break or stopped
|
||||||
self.state = 'stopped'
|
self.state = 'stopped'
|
||||||
@ -90,12 +93,12 @@ class Pomodoro(IntervalModule):
|
|||||||
'color': color
|
'color': color
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def start(self):
|
||||||
self.state = 'running'
|
self.state = 'running'
|
||||||
self.time = datetime.now() + timedelta(seconds=self.pomodoro_duration)
|
self.time = datetime.now() + timedelta(seconds=self.pomodoro_duration)
|
||||||
self.breaks = 0
|
self.breaks = 0
|
||||||
|
|
||||||
def on_rightclick(self):
|
def stop(self):
|
||||||
self.state = 'stopped'
|
self.state = 'stopped'
|
||||||
self.time = None
|
self.time = None
|
||||||
|
|
||||||
|
@ -50,6 +50,11 @@ class PulseAudio(Module, ColorRangeModule):
|
|||||||
bar_type = 'vertical'
|
bar_type = 'vertical'
|
||||||
vertical_bar_width = 2
|
vertical_bar_width = 2
|
||||||
|
|
||||||
|
on_rightclick = "switch_mute"
|
||||||
|
on_leftclick = "pavucontrol"
|
||||||
|
on_upscroll = "increase_volume"
|
||||||
|
on_downscroll = "decrease_volume"
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
"""Creates context, when context is ready context_notify_cb is called"""
|
"""Creates context, when context is ready context_notify_cb is called"""
|
||||||
# Wrap callback methods in appropriate ctypefunc instances so
|
# Wrap callback methods in appropriate ctypefunc instances so
|
||||||
@ -155,10 +160,7 @@ class PulseAudio(Module, ColorRangeModule):
|
|||||||
volume_bar=volume_bar),
|
volume_bar=volume_bar),
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def switch_mute(self):
|
||||||
subprocess.Popen(["pavucontrol"])
|
|
||||||
|
|
||||||
def on_rightclick(self):
|
|
||||||
if self.has_amixer:
|
if self.has_amixer:
|
||||||
command = "amixer -q -D pulse sset Master "
|
command = "amixer -q -D pulse sset Master "
|
||||||
if self.currently_muted:
|
if self.currently_muted:
|
||||||
@ -167,12 +169,12 @@ class PulseAudio(Module, ColorRangeModule):
|
|||||||
command += 'mute'
|
command += 'mute'
|
||||||
subprocess.Popen(command.split())
|
subprocess.Popen(command.split())
|
||||||
|
|
||||||
def on_upscroll(self):
|
def increase_volume(self):
|
||||||
if self.has_amixer:
|
if self.has_amixer:
|
||||||
command = "amixer -q -D pulse sset Master %s%%+" % self.step
|
command = "amixer -q -D pulse sset Master %s%%+" % self.step
|
||||||
subprocess.Popen(command.split())
|
subprocess.Popen(command.split())
|
||||||
|
|
||||||
def on_downscroll(self):
|
def decrease_volume(self):
|
||||||
if self.has_amixer:
|
if self.has_amixer:
|
||||||
command = "amixer -q -D pulse sset Master %s%%-" % self.step
|
command = "amixer -q -D pulse sset Master %s%%-" % self.step
|
||||||
subprocess.Popen(command.split())
|
subprocess.Popen(command.split())
|
||||||
|
@ -39,6 +39,7 @@ class pyLoad(IntervalModule):
|
|||||||
captcha_false = ""
|
captcha_false = ""
|
||||||
download_true = "Downloads enabled"
|
download_true = "Downloads enabled"
|
||||||
download_false = "Downloads disabled"
|
download_false = "Downloads disabled"
|
||||||
|
on_leftclick = "open_webbrowser"
|
||||||
|
|
||||||
def _rpc_call(self, method, data=None):
|
def _rpc_call(self, method, data=None):
|
||||||
if not data:
|
if not data:
|
||||||
@ -83,5 +84,5 @@ class pyLoad(IntervalModule):
|
|||||||
"instance": self.address,
|
"instance": self.address,
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def open_webbrowser(self):
|
||||||
webbrowser.open_new_tab(self.address)
|
webbrowser.open_new_tab(self.address)
|
||||||
|
@ -61,6 +61,9 @@ class Reddit(IntervalModule):
|
|||||||
"no_mail": "",
|
"no_mail": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on_leftclick = "open_permalink"
|
||||||
|
on_click = "open_link"
|
||||||
|
|
||||||
_permalink = ""
|
_permalink = ""
|
||||||
_url = ""
|
_url = ""
|
||||||
|
|
||||||
@ -133,8 +136,8 @@ class Reddit(IntervalModule):
|
|||||||
"color": color,
|
"color": color,
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def open_permalink(self):
|
||||||
user_open(self._permalink)
|
user_open(self._permalink)
|
||||||
|
|
||||||
def on_rightclick(self):
|
def open_link(self):
|
||||||
user_open(self._url)
|
user_open(self._url)
|
||||||
|
@ -23,6 +23,9 @@ class Spotify(Module):
|
|||||||
("color", "color of the output"),
|
("color", "color of the output"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
on_leftclick = "switch_playpause"
|
||||||
|
on_rightclick = "next_song"
|
||||||
|
|
||||||
def main_loop(self):
|
def main_loop(self):
|
||||||
""" Mainloop blocks so we thread it."""
|
""" Mainloop blocks so we thread it."""
|
||||||
self.player = Playerctl.Player()
|
self.player = Playerctl.Player()
|
||||||
@ -62,8 +65,8 @@ class Spotify(Module):
|
|||||||
"color": self.color
|
"color": self.color
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_leftclick(self):
|
def switch_playpause(self):
|
||||||
self.player.play_pause()
|
self.player.play_pause()
|
||||||
|
|
||||||
def on_rightclick(self):
|
def next_song(self):
|
||||||
self.player.next()
|
self.player.next()
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import subprocess
|
|
||||||
|
|
||||||
from i3pystatus import Module
|
from i3pystatus import Module
|
||||||
|
|
||||||
|
|
||||||
@ -11,14 +9,10 @@ class Text(Module):
|
|||||||
settings = (
|
settings = (
|
||||||
"text",
|
"text",
|
||||||
("color", "HTML color code #RRGGBB"),
|
("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",)
|
required = ("text",)
|
||||||
|
|
||||||
color = None
|
color = None
|
||||||
cmd_leftclick = "test"
|
|
||||||
cmd_rightclick = "test"
|
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.output = {
|
self.output = {
|
||||||
@ -26,9 +20,3 @@ class Text(Module):
|
|||||||
}
|
}
|
||||||
if self.color:
|
if self.color:
|
||||||
self.output["color"] = 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)
|
|
||||||
|
68
tests/test_callbacks.py
Normal file
68
tests/test_callbacks.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
from i3pystatus.core.modules import Module
|
||||||
|
|
||||||
|
|
||||||
|
class CallbacksMetaTest(unittest.TestCase):
|
||||||
|
|
||||||
|
valid_msg_count = "hello world"
|
||||||
|
notmuch_config = "notmuch-config"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def send_clicks(module):
|
||||||
|
# simulate click events for buttons 1 to 10
|
||||||
|
for button in range(1, 10):
|
||||||
|
module.on_click(button)
|
||||||
|
|
||||||
|
class NoDefaultCounter(Module):
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
|
||||||
|
def update_counter(self, step=1):
|
||||||
|
self.counter = self.counter + step
|
||||||
|
|
||||||
|
class WithDefaultsCounter(NoDefaultCounter):
|
||||||
|
on_leftclick = "update_counter"
|
||||||
|
on_rightclick = ["update_counter", 2]
|
||||||
|
on_upscroll = ["callable_callback", "i3 is", "awesome"]
|
||||||
|
on_downscroll = ["update_counter", -1]
|
||||||
|
|
||||||
|
def test_count_is_correct(self):
|
||||||
|
"""Checks module works in the intended way, ie increase correctly
|
||||||
|
a counter"""
|
||||||
|
counter = self.NoDefaultCounter()
|
||||||
|
self.assertEqual(counter.counter, 0)
|
||||||
|
counter.update_counter(1)
|
||||||
|
self.assertEqual(counter.counter, 1)
|
||||||
|
counter.update_counter(2)
|
||||||
|
self.assertEqual(counter.counter, 3)
|
||||||
|
counter.update_counter(-2)
|
||||||
|
self.assertEqual(counter.counter, 1)
|
||||||
|
|
||||||
|
CallbacksMetaTest.send_clicks(counter)
|
||||||
|
|
||||||
|
# retcode, out, err = run_through_shell("notmuch --config=%s new" % (self.notmuch_config), enable_shell=True)
|
||||||
|
|
||||||
|
# self.assertEqual(out.strip(), self.valid_output)
|
||||||
|
def test_callback_set_post_instanciation(self):
|
||||||
|
|
||||||
|
counter = self.NoDefaultCounter()
|
||||||
|
|
||||||
|
# set callbacks
|
||||||
|
counter.on_leftclick = "update_counter"
|
||||||
|
counter.on_rightclick = ["update_counter", 2]
|
||||||
|
counter.on_upscroll = [print, "i3 is", "awesome"]
|
||||||
|
counter.on_downscroll = ["update_counter", -1]
|
||||||
|
|
||||||
|
self.assertEqual(counter.counter, 0)
|
||||||
|
counter.on_click(1) # left_click
|
||||||
|
self.assertEqual(counter.counter, 1)
|
||||||
|
counter.on_click(2) # middle button
|
||||||
|
self.assertEqual(counter.counter, 1)
|
||||||
|
counter.on_click(3) # right click
|
||||||
|
self.assertEqual(counter.counter, 3)
|
||||||
|
counter.on_click(4) # upscroll
|
||||||
|
self.assertEqual(counter.counter, 3)
|
||||||
|
counter.on_click(5) # downscroll
|
||||||
|
self.assertEqual(counter.counter, 2)
|
Loading…
Reference in New Issue
Block a user