If a module defines a callback for a widget's text, an optional
decorator "@bumblebee.output.scrollable" can be used to make the text
scrollable.
In those cases, the desired width is set to (in decreasing order of
priority):
1. whatever the widget defines as "theme.width"
2. whatever the theme defines as "width" for the module
3. whatever the commandline parameter "width" for the module is set to
4. 30 (determined by unfair dice roll)
see #27
Added theme-options ("minwidth" and "align") for setting the minimum
width and the alignment of a widget.
Also, allow widget to provide defaults for the theme options by setting
an attribute in their store called "theme-<name of the theme option>".
For example, a widget can now define a default alignment by using:
widget.set("theme-align", "default-value").
Set the minimum width for uplink and downlink widgets to "down 1000MB",
which should be plenty, and change alignment to right (personally, I
find this looks nicer).
To not have the icons on the left side "jump around" depending on the
value, make them suffixes.
If this solution is not sufficient, alternatively, the widget itself
could perform value padding. In that case, the whole alignment and
min-width settings would be obsolete and the icons could remain on the
left side.
Added theme-options ("minwidth" and "align") for setting the minimum
width and the alignment of a widget.
Also, allow widget to provide defaults for the theme options by setting
an attribute in their store called "theme-<name of the theme option>".
For example, a widget can now define a default alignment by using:
widget.set("theme-align", "default-value").
* use psutil instead of "ifconfig" in order to avoid external command
calls
* fix a small bug in the ascii theme (missing colon)
* show statistics per-nic
* If an exception is thrown, catch it and show a (somewhat) nice error
message in the i3bar instead of the normal content
* Add a flag "-d" for debugging into a debug log. Currently, this only
logs commandline calls as they occur and their return values, as well
as exceptions.
fixes#58
Until now, manually specifying an interval did not work, as a cast to
float was missing. Now, it's possible to specify an update interval in
seconds via "-p interval=<interval>"
fixes#54
Seems like subprocess and friends (Popen, communicate) are not so easy
to mock cleanly. Therefore, start from scratch and carefully write test
by test, until (at least) the old test coverage has been restored.
Instead of executing an external call to "uname", use the standard
Python module "platform" to retrieve information about the kernel used.
Positive side-effect: This is portable, if i3 ever exists on Windows :P
Since requests works the same for python2.7 and python3.x, use requests
instead of urllib (which returns a string in python2.7, but byte data in
python3.0, at least).
* Use app-specific API key for bumblebee-status
* Add some parameters (location, unit, update interval)
* Make interval calculation based on time, not number of calls
Somehow, the fix in the previous commit didn't work, it seems that
sometimes epoll() doesn't trigger, even if there is more data in
sys.stdin. I'm sure I'm doing something horribly wrong here.
Anyhow, as a quick fix, check for the open bracket to be sure to not
buffer the first event too long.
Re-enable the possibility to define custom mouse actions by binding
commands to "<alias|module>.<left-click|right-click|...>". These
commands are then executed as shell commands.
fixes#30
Instead of having a thread that runs in the background continuously,
spawn a new one for every update interval. That speeds up the tests
quite a lot.
see #23
Show RTT measured by ICMP echo request/replies for a given host.
For that to work correctly, change the "full_text" callback for a widget
so that the widget itself is also passed as argument in the callback
method. That actually makes a lot of sense, since the widget can now be
used as a repository of state information.
see #23
Quite a lot of modules use the "if higher X -> critical, if higher Y ->
warning" idiom now, so extracted that into a common function for reuse.
see #23
Until now, as soon as a widget registered *any* callback, the default
callbacks (e.g. scroll up/down to go to next/previous workspace) didn't
work anymore, as there was a better match for the general registration
(even though not for the button).
To fix this, merge the callback registration into a flat registration,
where a key is calculated from the ID of the registrar and the
registered button.
see #23
If the computer runs on AC, display that instead of showing "100%" in
the status.
Also, if reading the charging status fails for some reason (except the
computer being on AC), go into critical state and display "n/a".
see #23
Allow modules to define aliases. This replaces the symlink mechanism
that was in place previously, because it was a bit ugly (and confused
code climate).
see #23
Make input thread non-blocking by using select(). This increases the CPU
utilization a bit (depending on the timeout), but makes the thread exit
cleanly, even if an exception is thrown in the main thread.
see #23
If a widget exists for an interface that is not there anymore (i.e. a
tunnel interface that has been removed, or a USB device that has been
unplugged), remove that widget from the list.
see #23
Re-add the NIC module with all its functionality (hopefully...).
This introduces a new concept: Instead of having separate queries for
critical and warning (which really are just another set of states), a
module can now return a list of states for each widget. All the state
information is then merged together into a single theme. So, for
instance, the NIC module can return a state saying "critical -
wlan-down", which applies the theme information for both "critical" and
"wlan-down".
see #23
I cannot get the min_width property to work right now, so in order to
fix the width of the CPU widget, pad the utilization to 3 digits (so
that even 100% aligns nicely).
see #23
The cpu module now has cpu.warning and cpu.critical thresholds. If the
CPU utilization is higher than any of those values, the widget's state
changes to warning or critical, respectively.
see #23
Create infrastructure for input event handling and add i3bar event
processing. For each event, callbacks can be registered in the input
module.
Modules and widgets both identify themselves using a unique ID (the
module name for modules, a generated UUID for the widgets). This ID is
then used for registering the callbacks. This is possible since both
widgets and modules are statically allocated & do not change their IDs.
Callback actions can be either callable Python objects (in which case
the event is passed as parameter), or strings, in which case the string
is interpreted as a shell command.
see #23
Each widget can now return a state using the method "state()". This
string is then used to look up a theme information which is used instead
of the default or module theme, if found.
see #23
Add customized separators:
* The default separators are automatically disabled if custom separators
are used (to "just" disable the default, use empty custom separators)
* Use previous background color as their background color and the
current background color as foreground color
* Allow the separator-block-width to be configured
see #23
Allow a theme to define a "cycle" of attributes that are cycled through
on a widget-per-widget basis (e.g. for alternating the widget
background). These cycles take precedence over the default values, but
can be overridden by module-specific theme instructions.
see #23
Make the format string of the datetime module configurable using the new
parameter() method in the module.
Also, restructured the setting of the config information a bit so that
the parameter() method can be used in the constructor of a module.
see #23
User can now use -p <key>=<value> to pass configuration parameters to
modules. For this, the module gets a "parameter()" method. Parameter
keys are in the format <name>.<key> where <name> is the name of the
loaded module. This is either the name of the module itself (e.g. "cpu")
or its alias, if the user specified it, for example:
bumblebee-status -m cpu -p cpu.warning=90
vs.
bumblebee-status -m cpu:test -p test.warning=90
see #23
Add an interface that allows arbitrary objects to store/retrieve
arbitrary key/value pairs. This will be used for different purposes in
the future:
* Config class(es) can store user-defined parameters for modules
* Widgets can store state
* ???
see #23
Add a helper function that lists all existing modules and modify the CPU
module test so that it now generically iterates all available modules
and tests their widgets.
see #23
Allow module-specific theme information to overload "default"
configuration. I.e. it is now possible to have specific prefix or
postfix configurations for different modules. The module name is derived
for each widget from the module (__module__) from which it was
instantiated.
see #23
Allow sub-themes ("iconsets") to be merged into the "main" theme. That
way, effectively, it's possible to define colors and icons in separate
JSON files.
see #23
Until now, widgets were re-created during each iteration. For multiple,
reasons, using static widget objects is much easier, so instead of
creating new widgets continuously, modules now create the widgets during
instantiation and get the list of widgets passed as parameter whenever
an update occurs. During the update, they can still manipulate the
widget list by removing and adding elements as needed.
Advantages:
* Less memory fragmentation (fewer (de)allocations)
* Easier event management (widgets now have static IDs)
* Easier module code (widget contents can simply be the result of a
callback)
see #23
Add custom exceptions and add error handling to the engine's module
loading logic. I.e. when a non-existent module is loaded, an exception
is thrown now.
see #23
Add basic drawing of widgets. Each module instance returns a list of
widgets using the widgets() method which is then forwarded to the draw()
method of the configured output.
see #23
Allow the user to provide aliases when loading a module multiple times
so that the modules can be differentiated (e.g. for passing parameters
to a module).
see #23
This is going to be a bit more comprehensive than anticipated. In order
to cleanly refactor the core and the engine, basically start from
scratch with the implementation.
Goals:
* Test coverage
* Maintain backwards compatibility with module interface as much as
possible (but still make modules easier to code)
* Simplicity
see #23